Innhold i dette lysarksettet Dagens forelesning INF1010 Innhold i dette lysarksettet Hvordan jobbe med INF1010 Datastrukturer Algoritmer og datastrukturer Grafer (lister og trær) Objektorientert programmering Lister og køer Hva er en liste? Forskjellige implementasjoner av lister FIFO- og LIFO-lister Pekerkjedelister Pekerkjedelister Eksempel på enkeltkjedet liste: personliste Operasjoner på pekerkjedelister (enkeltkjedet) Øvelser Øvelser til neste fellesøvelse
Hvordan jobbe med INF1010 Studieaktiviteter i INF1010 Programmering (oppgaveløsning) alene/kollokvier programmeringslab (felles)øvelser forelesninger selvstudium lysark fra forelesningene egne notater og programmer oppgaver og løsningsforslsag Java-bøker Internett o.l. Husk INF1010 dreier seg først og fremst om å kunne lage javaprogrammer.
Hvordan jobbe med INF1010 Vi anbefaler et par bøker I tillegg et notat om binærsøk og quicksort. Disse brukes som referanselitteratur for temaene som behandles. Pensum framgår av lysarkene som brukes på forelesningene. Læringsmålet i INF1010 er ikke å kunne et pensum, men å kunne lage programmer (rimelig raskt) ved å bruke programmeringsteknikker som innøves i de forskjellige studieaktivitetene. Det er viktig å vite at man ikke kan lese seg til å nå dette målet.
Algoritmer og datastrukturer Ethvert program har en datastruktur som data manipuleres og lagres i. Programmet (algoritmene) virker på datastrukturen og endrer den. Datastrukturen endrer seg under programutførelsen. Å lage et «øyeblikksbilde» av datastrukturen i et program gir et godt bilde av hva programmet gjør. Objektdiagrammer er deler av et slikt bilde.
Algoritmer og datastrukturer Alle programmer har en datastruktur array HashMap grafer (lister og trær mm.) Som hjelpemiddel under programmeringen er en skisse av (deler av) datastrukturen meget nyttig. UML-diagram klassediagram objektdiagram strukturskisser annen skisse eller figur
Algoritmer og datastrukturer Beholdere (containers) I mange typer programmer betyr det lite hvordan dataene er organisert, så lenge vi kan oppbevare et objekt, sette det inn, finne det og fjerne det fra mengden av objekter, er vi fornøyd. Vi benytter da gjerne ferdiglagede programmoduler, jf. HashMap. Det skal vi ikke gjøre i dag. Istedet skal vi se på et eksempel på hvordan vi lager en konkret beholder for personer, en personliste.
Grafer (lister og trær) Pekerstrukturer Når vi har en datastruktur der objekter referer (peker på) andre objekter, får vi en graf. I hvert objekt kan vi ha mange pekere, og vi kan lage så komplekse grafer (nettverk) vi ønsker. En fordel med grafer sammenlignet I INF1010 skal vi nøye oss med å se på strukturene lister og binære trær som er de vanligste grafene i programmer.
Grafer (lister og trær) Valg av datastruktur Et viktig valg i programutviklingen er valg av datastruktur. Har vi mange objekter og det ikke er så viktig hvordan disse struktureres seg imellom, er det vanligvis aktuelt å velge en eller annen form for beholder: array hashmap liste (fil) tre annen grafstruktur
Objektorientert programmering Objektorientering «alt» er objekter informasjonsskjuling innkapsling generiske typer arv og polymorfisme et objekt er en instans av en klasse
Objektorientert programmering Perspektiv Husk perspektivet. Man kan ikke se alt med ett blikk. I en sammensatt datastruktur med mange objekter, er det fruktbart å skifte perspektiv fra det detaljerte, til det mer generelle, og tilbake. F.eks. vil vi noen ganger betrakte enkeltelementene i en liste som enkeltobjekter, andre ganger vil vi betrakte hele lista med tilhørende operasjoner som ett objekt. Begge måter er objektorienterte, men perspektivet skifter.
Hva er en liste? Eksempler på lister På norsk bruker vi vanligvis ordet «liste» for en oppramsing (gjerne vertikal) på et stykke papir e.l. kandidatliste handleliste spillerliste sensurliste deltakerliste gjesteliste sjekkliste ordliste resultatliste...
Hva er en liste? Lister er en sekvensiell datastruktur Vi bruker liste om en struktur som har en sekvensiell form. I programmering er lister den vanligst forekommende datastruktur. Alle sekvensielle data (i en array f.eks.) kan kalles en liste. En fil kan ses på som en liste av tekststrenger (linjer). En tekststreng er igjen en liste av tegn. En fil kan derfor ses på som en liste av lister av tegn.
Hva er en liste? Vi bruker flere ord for å betegne lister og mer bestemte typer av lister. Det viktigste ved en liste, er at det innebærer en ordning av objektene etter hverandre i sekvens, slik at man fra et element kan finne det neste (eller forrige). sequence list stack (LIFO) queue (FIFO) Med en kø forstår vi en liste hvor det finnes regler for hvordan elementer kommer inn og tas ut av lista. På engelsk brukes ordet «queue» oftest om en FIFO-liste. («rettferdig kø»)
Forskjellige implementasjoner av lister filer arrayer lenkede lister enkeltkjedete lister dobbeltkjedete lister med og uten listehode og -hale FIFO- og LIFO-køer Du vil lære mer om de forskjellige implementasjonene ved å løse oppgavene som blir gitt til neste fellesøvelse. Programmeringseksemplene i denne forelesningen begrenser seg til enkeltkjedete lister.
Forskjellige implementasjoner av lister Lister er mer enn struktur tellbarhet rekkefølge bare unike elementer sortering av elementene hvor i lista kommer nye elementer (køregler) hvor tas elementer ut (køregler)
FIFO- og LIFO-lister En tegning sier mer enn tusen ord inn ut ut FIFO (kø) Først inn først ut LIFO (stabel) Sist inn først ut inn
FIFO- og LIFO-lister FIFO First In First Out (queue) En FIFO-liste er en kø som har køregler som en «billettkø». Elementene rangeres etter hvor lang tid de har «stått i køen», slik at den står for tur som har stått lengst. En liste som administreres slik, kalles også «rettferdig kø». Eller bare «kø». Nyeste inn sist Eldste ligger først Eldste (første) er neste som betjenes (fjernes) Nyeste (siste) må vente lengst
FIFO- og LIFO-lister LIFO Last In First Out (stack) En LIFO-liste er en «kø» som har omvendte køregler i forhold til en FIFO-liste. Elementene rangeres etter hvor lang tid de har «stått i køen», slik at den står for tur som kom inn i køen sist. En liste som administreres slik, kalles også en «stabel», fordi elementet som kom sist ligger øverst og er det første til å tas ut. Nyeste inn først (øverst) Eldste ligger sist, bakerst (underst) Nyeste (øverste) er neste som betjenes (fjernes) Eldste (underste) må vente lengst
Pekerkjedelister Hva mener vi med en pekerkjedeliste Alle disse begrepene betegner det samme sammensatte objektet (en beholder): kjedet liste pekerliste lenkeliste linked list (Weiss) chained list Objektene i lista har pekere for å referere til neste (evt. forrige) objekt. Slik bygges lista opp som en sammenhengende kjede av objekter ved hjelp av pekere.
Eksempel på enkeltkjedet liste: personliste En første skisse av personlista. Først klassen som beskriver objektene (personene) som skal lenkes sammen. Deretter en klasse som beskriver selve lista. 1 class Person { 2 String navn; 3 Person nesteperson ; 4 // andre attributter 5 } 6 7 class Personer { 8 Person personliste ; 9 //... 10 } Lage en ny liste med personer: 1 Personer minevenner = new Personer ;
Eksempel på enkeltkjedet liste: personliste Personobjektet Hvert element (objekt) i lista har en peker til det neste elementet i lista, bortsett fra siste elementet som peker til null. type: String navn: navn type: Person "Sokrates" Sokrates Forenklet objekt navn: neste Et objekt av klassen Person
Eksempel på enkeltkjedet liste: personliste Et listeobjekt En instans av klassen Personer og de objektene (instanser av klassen Person) som er tilgjengelige fra den, dvs som programmet kan nå ved å følge pekerne. Person Person Person Person Person nesteperson String navn nesteperson String nesteperson String nesteperson String Jonathan Susanne Imran Nikita Elisabeth navn navn navn navn Person nesteperson String Figur: Objektdiagram av en personliste med 5 personer null personliste Et objekt av klassen Personer
Eksempel på enkeltkjedet liste: personliste Forenklet listeobjekt En instans av klassen Personer og de objektene (instanser av klassen Person) som er tilgjengelige fra den, dvs som programmet kan nå ved å følge pekerne. Jonathan Susanne Imran Nikita Elisabeth null personliste Jonathan Susanne Imran Nikita Elisabeth null personliste
Eksempel på enkeltkjedet liste: personliste Hvilke operasjoner trenger vi? sette inn en ny person finne en person fjerne en person bytte om to personer... Programskisse av listeklassen (husk perspektiv): 1 class Personer { 2 Person personliste ; 3 4 void setteinnperson ( Person inn ) { } ; 5 void finneperson ( Person p ) { } ; 6 void tautperson ( Person ut ) { } ; 7 //... 8 }
Operasjoner på pekerkjedelister (enkeltkjedet) Innsetting først sist sortert etter en attributtverdi prioritet tid i lista Før vi kan bestemme det, må vi vite hvordan lista skal administreres? F.eks. om den skal være FIFO eller LIFO. Hvis vi ikke vet det, kan vi lage flere innsettingsmetoder.
Operasjoner på pekerkjedelister (enkeltkjedet) Innsetting først 1 void settinnpersonforst( Person inn ) { 2 \\ Hvis l i s t a er tom, sett inn objektet 3 i f ( personliste == null ) personliste = inn ; 4 else { 5 \\ minst et objekt i lista 6 inn. nesteperson = personliste ; 7 personliste = inn 8 } 9 }
Operasjoner på pekerkjedelister (enkeltkjedet) Innsetting sist (uten «sistepeker») 1 void settinnpersonsist( Person inn ) { 2 \\ Hvis l i s t a er tom, sett inn objektet 3 i f ( personliste == null ) personliste = inn ; 4 else { 5 \\ finne siste element i lista 6 Person p = personliste ; 7 while (p. nesteperson! = null ) 8 p = p. nesteperson ; 9 \\ her er p. nesteperson==null, altså er p siste 10 p. nesteperson = inn 11 } 12 }
Operasjoner på pekerkjedelister (enkeltkjedet) Et listeobjekt med peker til siste element i lista Person Person Person Person Person nesteperson String navn nesteperson String nesteperson String nesteperson String nesteperson String Jonathan Susanne Imran Nikita Elisabeth navn navn navn navn null Person personliste Person sisteperson Et objekt av klassen Personer
Operasjoner på pekerkjedelister (enkeltkjedet) Innsetting og holde sortert Antar at Person-objektene i lista har et attributtint rang som objektene er sortert etter i stigende rekkefølge. Elementet som skal inn må da ikke havne så langt ut i lista at det får et element med høyere verdi på rang før seg selv. Vi leter oss fram til en tom nestepeker, eller til nesteperson peker på et objekt med høyere rang. Dette synes ganske enkelt, men vi vil se at når metoden skal virke både for en tom og en ikke-tom liste og for en liste som bare har et objekt, blir det nokså omstendelig. personliste == null innobjektet skal inn først innobjektet skal inn sist innobjektet skal hverken først eller sist
Operasjoner på pekerkjedelister (enkeltkjedet) 1 void settinnpersonetterrang( Person inn ) { 2 Person p = personliste ; 3 Boolean fortsett = true ; 4 inn. nesteperson = null ; // hvorfor? 5 while (p!= null && fortsett ) 6 if (p. nesteperson!= null && p. nesteperson. rang < inn. rang ) 7 p = p. nesteperson; 8 else fortsett = false ; 9 //p == null eller p. nesteperson. rang >= inn. rang 10 if (p == null ) { 11 // lista var tom 12 personliste = inn ; 13 } 14 else if (p == personliste ) { 15 if (p.rang < inn. rang ) { 16 inn. nesteperson = p. nesteperson; 17 personliste = inn ; 18 } 19 else { 20 inn. nesteperson = personliste ; 21 personliste = inn ; 22 } 23 } 24 else { 25 // inn skal inn mellom p og p. nesteperson 26 inn. nesteperson = p. nesteperson; 27 p. nesteperson = inn ; 28 } 29 }
Operasjoner på pekerkjedelister (enkeltkjedet) Skrive ut alle personene i lista 1 // I klassen Personer : 2 3 void skrivalle ( ) { 4 Person p = personliste ; 5 while (p! = null ) { 6 p. skriv ( ) ; 7 p = p. nesteperson ; 8 } 9 } 10 11 // I klassen Person : 12 void skriv ( ) { 13 System. out. println (... ) ; 14 }
Operasjoner på pekerkjedelister (enkeltkjedet) Fjerne person med gitt rang (en instans eller ingen) 1 Person fjern ( int rang) { 2 Person p = personliste ; 3 Person forrige = null ; 4 while (p!= null && p. rang!= rang { 5 forrige = p; 6 p = p. nesteperson; 7 } 8 // p er personen som skal fjernes, 9 // forrige er personen FØR denne i listen 10 if (p!= null ) { 11 i f ( p == personliste ) { 12 // Spesialtilfelle : p som skal fjernes står først 13 personliste = personliste. nesteperson; 14 } else { 15 forrige. nesteperson = p. nesteperson; 16 } 17 } 18 return p; 19 }
Øvelser til neste fellesøvelse Oppgaver Hvis du ikke har mulighet til å programmere alt, lag enkle programskisser. Oppgave 4 er fort gjort. 1. Finn feil i settinnpersonetterrang, eller overbevis deg selv om at den alltid virker korrekt. 2. Anta at personlista har listehode og hale. Gjør forenklinger i settinnpersonetterrang basert på denne antakelsen. 3. Lag en klasse LIFO-Personer etter modell av Personer-klassen med «LIFO-operasjonene»: settinnperson og tautperson. 4. Hvilken tilleggstruktur er nyttig hvis vi skal lage en tilsvarende FIFO-klasse? 5. Anta vi har en dobbeltkjedet personliste. (Person er utvidet med en peker som peker på forrige Personobjekt i lista. Gjør nødvendige forandringer i settinnpersonetterrang basert på dette. 6. Vi innfører arrayen personarray Person[400] i Personer. Lag en metode som overfører en FIFO-liste fra personliste til denne arrayen. Skriv metodene for å ta ut og sette personobjekter inn i personarrayen. Hint: Istedet for pekere bruker vi nå indekser i arrayen for første, neste, siste etc.