Seminarium 4 Köer och Stackar Innehåll ADT:erna Kö och Stack Definitioner Operationer Exempel på användning Givna klasser i Java Interfacet Queue Klassen Stack Klassen LinkedList Klassen PriorityQueue Implementering av köer och stackar Med delegation till intern listklass från JCF Med en enklare datastruktur Efter seminariet ska ni kunna lösa övningsuppgifterna t.o.m. kapitel 5 i övningshäftet. ADT Kö Definition En kö är en följd av element där insättning alltid görs sist i följden. borttagning alltid avser första elementet i följden. poll FIFO-kö (underförstått när vi pratar om köer) offer FK (Seminarium 4 Köer och Stackar) HT 06 / PFK (Seminarium 4 Köer och Stackar) HT 06 / Operationer ADT Stack Definition En stack är en följd av element där borttagning av ett element alltid avser det element som senast satts in. Sätt in x sist i kön (offer, enqueue) Ta reda på första elementet i kön (peek) Ta reda på och tar bort första elementet i kön (poll, dequeue) Kallas även LIFO-kö, Last In First Out FK (Seminarium 4 Köer och Stackar) HT 06 / PFK (Seminarium 4 Köer och Stackar) HT 06 4 /
ADT Stack Exempel på användning av stack En stack beskrivs oftast lodrätt orienterad. Operationer sker på toppen av stacken. Om ett aritmetiskt heltalsuttryck är skrivet i omvänd polsk notation (postfix notation) kan vi använda en stack för att beräkna uttryckets värde. push pop Operatorn placeras efter sina två operander: 0 Ex: 0 * i postfix notation motsvarar uttrycket * (0 ) i vanlig (infix) notation. Fördel: alla uttryck kan skrivas utan parenteser och deras värde kan enkelt evalueras med hjälp av en stack. FK (Seminarium 4 Köer och Stackar) HT 06 5 / Exempel på användning av stack Algoritm PFK (Seminarium 4 Köer och Stackar) HT 06 6 / Exempel på användning av stack Evaluering av uttrycket: 0 * skapa en tom stack s // s = new... så länge uttrycket ej är slut läs in nästa element (tal eller operator) om tal lägg talet på stacken // push annars (operator) hämta de två översta talen t och t // st. pop från stacken res = resultatet av operatorn använd på t och t lägg res på stacken // push Nu ska stacken bara innehålla ett värde resultatet. Läst: inget 0 - * 0 0 - Stack: tom -6 Om uttrycket är korrekt så ligger till sist resultatet som enda element på stacken. FK (Seminarium 4 Köer och Stackar) HT 06 7 / PFK (Seminarium 4 Köer och Stackar) HT 06 8 /
Kö och Stack i java.util ADT Stack i java.util «Interface» Collection «Interface» «Interface» List Queue Stack LinkedList PriorityQueue I Javas klassbibliotek har man inte infört något interface för ADT:n Stack. Det finns en klass Stack, som ärver en annan klass Vector. lägg ett element överst på stacken push(e) tag bort och returnera översta elementet pop() returnera översta elementet peek() Den innehåller också många metoder som inte förväntas av en stack. Klassen LinkedList i java.util innehåller även operationer som ska finnas för en ADT Stack: lägg ett element överst på stacken push(e) eller addfirst(e) tag bort och returnera översta elementet pop() eller removefirst() returnera översta elementet peek() eller peekfirst() FK (Seminarium 4 Köer och Stackar) HT 06 9 / Interface Stack som det borde se ut PFK (Seminarium 4 Köer och Stackar) HT 06 0 / Implementering av kö och stack Alternativ public interface Stack<E> { /** Lägger x överst på stacken. */ void push(e x); /** Tar bort och returnerar översta elementet från stacken. */ E pop(); Gör inte någon ny implementering utan utnyttja en list-klass (t ex java.util.linkedlist) men använd bara de operationer som är tillåtna för kö. + enkelt övriga metoder finns fortfarande tillgängliga /** Returnerar översta elementet på stacken. */ E peek(); /** Undersöker om stacken är tom. */ boolean isempty(); Implementera en egen klass, men använd internt en annan list-klass (delegation). Implementera en egen klass med en enklare datastruktur (t ex vektor eller enkellänkad lista). FK (Seminarium 4 Köer och Stackar) HT 06 / PFK (Seminarium 4 Köer och Stackar) HT 06 /
Implementering av stack genom delegation till lista public class MyStack<E> { private LinkedList<E> elements;... public push(e x) { elements.push(x); Implementering av kö Enkellänkad datastruktur Enkellänkad datastruktur för stack: Stacken representeras av referens till första noden. Alla operationer kan då utföras på konstant tid, oberoende av stackens storlek. Behöver extra utrymme för next-referenser. first public E peek() { return elements.peek();... Enkellänkad datastruktur för kö: Kön representeras av referenser till första och sista noden. Alla operationer kan då utföras på konstant tid, oberoende av köns längd. Behöver extra utrymme för next-referenser. first FK (Seminarium 4 Köer och Stackar) HT 06 / PFK (Seminarium 4 Köer och Stackar) HT 06 4 / Enkellänkad implementering av stack Enkellänkad implementering av kö s = new MyStack<Integer>(); first = null s.push(); first q = new MyQueue<Integer>(); first = = null q.offer(); first s.push(); first q.offer(); first s.push(); int i = s.pop() // i får värdet first first q.offer(); int i = q.poll() // i får värdet first first FK (Seminarium 4 Köer och Stackar) HT 06 5 / PFK (Seminarium 4 Köer och Stackar) HT 06 6 /
Implementering av stack Jämförelse mellan alternativ och Vektorimplementering av stack Föregående alternativ (delegering till LinkedList): Många metodanrop. Om vi anropar push i Stack, så anropas också push i LinkedList,... Datastrukturen i LinkedList är vald så att operationerna på listan ska bli effektiva. (I java.util med en dubbellänkad lista). Implementering med enklare datastruktur: Det blir färre metodanrop. T ex utför då push sin uppgift utan att delegera vidare till annan metod. En enkellänkad struktur kan ge bättre effektivitet. Vektorimplementering av stack: Stacken representeras av vektor och index för nästa insättning (initialt 0). Ger konstant tid för operationerna så länge vektorns storlek räcker. Om man dubblar vektorns storlek varje gång den inte räcker till, kan man visa att operationerna fortfarande i medeltal går att utföra på konstant tid. Efter dubblering är bara halva utrymmet i vektorn utnyttjat. FK (Seminarium 4 Köer och Stackar) HT 06 7 / PFK (Seminarium 4 Köer och Stackar) HT 06 8 / Vektorimplementering av stack Vektorimplementering av kö s = new MyStack<Integer>(); size = 0 s.push(); s.push(); s.push() int i = s.pop() // i får värdet size = size = Vektorimplementering av kö: Vektorn används cirkulärt; första platsen i vektorn anses vara efterföljare till sista platsen. Kön representeras av vektorn + index för första ( äldsta ) elementet + index för sista ( yngsta ) elementet + antalet element. Även här kan vi behöva skapa större vektor när antalet element blivit för stort. size = s.push(4); 4 size = FK (Seminarium 4 Köer och Stackar) HT 06 9 / PFK (Seminarium 4 Köer och Stackar) HT 06 0 /
Vektorimplementering av kö Interface Queue i java.util q = new MyQueue<Integer>(); q.offer(); q.offer(); q.offer(); q.offer(4); q.offer(5); int i = q.poll() // i får värdet q.offer(6); front = 0, rear = 4, size = 0 front = 0, rear = 0, size = 4 5 front = 0, rear = 4, size = 5 4 5 front =, rear = 4, size = 4 6 4 5 front =, rear = 0, size = 5 Innehåller allt som en kö kräver Innehåller dessutom bl.a. boolean add(e x) E element() E remove() <<Interface>> Collection <<Interface>> Queue Genererar exception Returnerar speciellt värde Sätta in boolean add(e e) boolean offer(e e) Ta bort E remove() E poll() Ta reda på E element() E peek() FK (Seminarium 4 Köer och Stackar) HT 06 / Implementeringar av Interface Queue i java.util PFK (Seminarium 4 Köer och Stackar) HT 06 / Det finns flera implementeringar av interfacet Queue i Java, två av dem stöter vi på i den här kursen. LinkedList FIFO - kö add(e e) och offer(e e) lägger till element sist i listan remove() och poll() tar bort och returnerar första elementet i listan element() och peek() tittar på första elementet i listan PriorityQueue Elementen plockas ut i prioritetsordning Mer om detta längre fram i kursen LinkedList <<Interface>> Queue PriorityQueue FK (Seminarium 4 Köer och Stackar) HT 06 /