TDDC30 Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU På denna föreläsning: • Abstrakta datatyper • Listor • Stackar • Köer 1 Abstrakta Datatyper (ADT) • Abstraktion – (subst.) En tankeprocess i vilken man bortser från vissa egenskaper hos en företeelse eller ett föremål och i stället uppmärksammar en eller några få egenskaper Källa: Nationalencyklopedin (förkortad form) • Abstrakt datatyp – En datatyp där man bortser från implementationsspecifika egenskaper och istället uppmärksammar en eller några få egenskaper. ADT implementeras med lämpliga datastrukturer och algoritmer • Datastruktur - Logisk organisation av datorminne för lagring av data • Algoritm – En uppsättning instruktioner för att lösa en uppgift 2 Abstrakta Datatyper (ADT)(2) Flyttal: Ett oväntat exempel på en abstrakt datatyp(ADT) • Vi behöver ej känna till exakt hur flyttalet fungerar internt i datorn • Detaljer kan variera mellan programspråk • Formatet är rätt komplext, ex. Java definierar en float med formeln 𝑠 ∗ 𝑐 ∗ 2𝑞 , där s är -1/1, c 23 bit och q 8 bit • Allt vi behöver veta är operationerna, +, -, *, /, osv. • Vi förväntar oss samma uppsättning operationer på flyttal överallt • Endast flyttals-kontraktet måste följas • Kod som använder flyttal blir därmed frikopplad från specifik implementation 3 Abstrakta Datatyper (ADT)(3) Scenario: Du skriver ett program som hanterar samtliga studenter godkända på en kurs. Programmet ska spara för varje student om de klarat av kursen eller ej. Behov: En abstrakt datatyp(ADT) som kan hjälpa till med ovannämda • Steg 1: Planera en lämplig abstrakt datatyp • Bestäm både både domän och operationer • Steg 2: Implementera ADT:n som en datastruktur • Välj representation för datat • Skriv algoritmer för ADT:ns operationer • Steg 3: Använd ADT:ns operationer för att beskriva algoritmen som löser ditt problem 4 Abstrakta Datatyper (ADT)(4) Steg 1: Välj lämplig abstrakt datatyp Både domän och operationer ADT: Ordbok (nyckel-information par) • Domän: • En linjärt ordnad mängd nycklar K (studenter) • Information I (ja eller nej) • Operationer: • lookup(nyckel) => information • Ev. insättningsoperation? Fler detaljer än dessa inte synliga för användaren 5 Abstrakta Datatyper (ADT)(5) Steg 2: Implementera ADT:n som en datastruktur • Välj representation av datat • Konstruera algoritmer för operationerna MyDictionaryImpl - pnrs : Strings[] - passed : boolean[] +lookup(pnr : String) : boolean Steg 3: Använd ADT:ns operationer för att lösa din uppgift MyDictionaryImpl students = new MyDictionaryImpl(); students.lookup(”880725-9505”); 6 Abstrakta Datatyper (ADT)(5) • Men om vi vill ändra implementation senare? • Hur gör vi för att det inte skall bli fel på alla ställen där vi använder typen MyDictionaryImpl? Dictionary +lookup(pnr : String) : boolean MyDictionaryImpl - pnrs : Strings[] - passed : boolean[] +lookup(pnr : String) : boolean OtherDictionaryImpl - pnr : Strings - passed : boolean - next : OtherDictionaryImpl +lookup(pnr : String) : boolean Vi låter omvärlden använda datastrukturen genom en abstrakt klass, och polymorfi! Dictionary students = new MyDictionaryImpl(); // nu behöver vi endast ändra här students.lookup(”880725-9505”); 7 Abstrakta Datatyper (ADT)(5) Sammanfattning: • ADT:er säger vad som ska göras • För att bestämma hur det ska göras • Välj datastruktur • Konstruera algoritmer för ADT:ns operationer Dictionary +lookup(pnr : String) : boolean • Samma ADT kan implementeras MyDictionaryImpl med - pnrs : Strings[] • Olika datastrukturer - passed : boolean[] +lookup(pnr : String) : boolean • Olika algoritmer Välj den lösning som är mest effektiv i just ditt fall OtherDictionaryIm - pnr : Strings - passed : boolean - next : OtherDictiona +lookup(pnr : String) : boo 8 ADT Lista • En av de mest använda abstrakta datatyperna • Numrerad • Går att hämta element m.h.a. index • Går att använda Iteratorer för att traversera • Abstraherar bort indexering (om man vill) • Storleken: Antal element lagrade i listan • Kan implementeras både med array eller länkade noder 9 ADT Lista(2) En delmängd av standardgränssnittet för ADT Lista: void add(x) –Lägg till x i slutet av listan void addFirst(x) – Lägg till x i början av listan void remove(x), remove(i) –Ta bort x /elementet på plats i boolean contains(x) – True om det finns ett likadant element int indexOf(x) – Returnerar index för x x get(i) – Returnerar elementet på index i 10 ArrayList • En implementation av ADT:n Lista • Representerar datat i någon form av fält • + Kan hämta ut element med index snabbt • - Långsam vid insättning i början av listan • ... 11 Enkellänkad Lista • En implementation av ADT:n Lista • Representerar datat i noder med referens till efterföljande nod • Har ofta även ett ”huvud” med lite extra information H D D D / • + Kan lägga till element i (början av) listan snabbt • - Långsam då den hämtar ut element av ett visst index • ... 12 Lite om referenser… • Variabler av icke primitiva datatyper är alltid referenser i java. • Måste instansieras innan de används. • Två variabler kan referera till samma minnesutrymme. Human a = new Human(”Kalle”); Human b = a; b.setName(”Lisa”); a: ”Lisa” b: • Objekt behöver ej destrueras! (avallokeras) 13 Länkad struktur • En klass kan innehålla en variabel av samma typ som klassen själv! class Node { String data; Node next; } 14 Dubbellänkad Lista • En implementation av ADT:n Lista • Representerar datat i noder med referens till efterföljande och föregående nod • Har ofta även ett ”huvud” med lite extra information, ibland dessutom en ”svans”. Så kallade ”sentinel-noder” H / D D D / • + Snabbare att sortera • - Kräver större minnesutrymme • ... 15 Cirkulärt länkad Lista • En implementation av ADT:n Lista • Enkellänkade noder i en ring • Har ofta även ett ”huvud” / ”markör” för att peka ut den aktuella noden, ibland även en svans M D D D Implementerar vanligtvis även • D D • • • Används ofta när en ringbuffer behövs void add(E) – Lägger till element efter den aktuella noden E remove() – Tar bort noden efter den aktuella noden void advance() – Flyttar markören ett steg 16 Iteratorer • Harry har skrivit ett program som använder två cirkulära listor, en arraylista samt en dubbellänkad lista. • Han vill ha ett gemensamt sätt att besöka alla värden i alla dessa datastrukturer 17 Lösning: Iteratorer! Iteratorer(2) • Ett sätt att iterera över alla element i en datastruktur utan att behöva känna till implementationen! • Skapas oftast av datastrukturen genom att anropa metoden iterator() . List<String> myList = SingleLinkedList<String>(); Iterator<String> i = myList.iterator(); // Kan byta ut myList mot alla objekt // som kan skapa en iterator while (i.hasNext()) { System.out.print(i.next()); } // Inbyggt snabbsätt att iterera över datastrukturer // Fungerar eftersom myList har metoden iterator() for (String data : myList) { System.out.print(data); } 18 Kö (en. Queue) • Du är en kock på en restaurang. • Servitör / servitris kommer in med beställningar som läggs i kö. • När du skall göra en maträtt tar du alltid den beställning som ligger först i kön (den har väntat längst). mmmm…. 19 Kö (en. Queue) • Först in – först ut (FIFO) • Metoder • front() / peek() – Returnerar främsta elementet • dequeue() – Tar bort och returnerar det främsta elementet • void enqueue(E) – Lägger till ett element i slutet av kön • boolean isEmpty() – Returnerar sant om kön är tom • int size() – Returnerar antalet element i kön • Exempel på användning: Inmatningsbuffert 20 Stack • Du är en diskare på en restaurang. • Servitör / servitris bär in disk och lägger längst upp på din hög (en stack). • Du tar alltid översta tallriken när du skall diska nästa. 21 Stack • Sist in – först ut (LIFO) • Metoder • top() / peek() – Returnerar stackens toppelement utan att ta bort det • pop() – Tar bort och returnerar stackens toppelement • void push(Element) – Lägger till ett element på toppen av stacken • boolean isEmpty() – Returnerar sant om stacken är tom • int size() – Returnerar antal element i stacken • Obs! Datastrukturen kanske är implementerad precis som en annan ADT, men uppsättningen operationer skiljer. 22 Hitta felet! public class StackTest { public static void main(String[] args) { Stack stack = new Stack(); stack.push(34); int i = stack.pop(); stack.push(i); stack.pop(); stack.peek(); stack.pop(); } } Försäkra dig om att stacken inte är tom innan du försöker komma åt topelementet. (Ett Exception kommer att 23 kastas här!)