So far... For recursive and iterative programs. Bubble, insertion, selection, quick, merge, counting

Relevanta dokument
Listor. Koffman & Wolfgang kapitel 2, avsnitt , och 2.9

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista

ADT Kö. Seminarium 4 Köer och Stackar Innehåll. Operationer. ADT Stack. Definition. Definition

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista Läsanvisningar och uppgifter

Föreläsning 4 Innehåll. Abstrakta datatypen lista. Implementering av listor. Abstrakt datatypen lista. Abstrakt datatyp

Föreläsning 4 Innehåll

Länkade strukturer. (del 2)

Datastrukturer. föreläsning 3. Stacks 1

Abstrakt datatyp. -Algoritmer och Datastrukturer- För utveckling av verksamhet, produkter och livskvalitet.

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

Föreläsning 2. Länkad lista och iterator

Föreläsning 2. Länkad lista och iterator

Föreläsning Datastrukturer (DAT036)

Datastrukturer. Arrayer. Arrayer. Arrayer. Array av arrayer. Array av arrayer

Föreläsning 3. Stack

Föreläsning 3. Stack

Stackar, köer, iteratorer och paket

Föreläsning 2 Datastrukturer (DAT037)

Föreläsning 3 Datastrukturer (DAT037)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

ADS : STACK ADT: STACK. Stack och Kö -Implementering - Tilllämpningar. Oftast förekommande metoder i Stack. TopOfStack

Föreläsning 4. Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö

Föreläsning 3 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT036)

Länkade strukturer, parametriserade typer och undantag

Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 5 Erik Nilsson, Institutionen för Datavetenskap, LiU

Föreläsning 4 Datastrukturer (DAT037)

TDDC30 Programmering i Java, Datastrukturer och Algoritmer Lektion 2. Länkade listor Stackar Köer MyList Iteratorer Lab 2 Exceptions Paket

Lösningsförslag till tentamen i EDAA01 programmeringsteknik fördjupningkurs

Övning vecka 6. public void method2() { //code block C method3(); //code block D }//method2

Programmering för språkteknologer II, HT2014. Rum

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

Samlingar Collection classes

Grafer, traversering. Koffman & Wolfgang kapitel 10, avsnitt 4

Tentamen i Algoritmer & Datastrukturer i Java

Namn: (Ifylles av student) Personnummer: (Ifylles av student) Tentamensdatum: Tid: Hjälpmedel: Inga hjälpmedel

Tommy Färnqvist, IDA, Linköpings universitet

Rekursion. Koffman & Wolfgang kapitel 5

2. Palindrom. Exempel: 1,2,3,2,1 är ett palindrom, och även 0, men inte 1,2,3,1,2,3.

Avbildningar och hashtabeller. Koffman & Wolfgang kapitel 7, mestadels avsnitt 2 4

TDDC30 Programmering i Java, Datastrukturer och Algoritmer Lektion 2. Laboration 2 Datastrukturer En liten uppgift Frågor

Föreläsning 1. Abstrakta datatyper, listor och effektivitet

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

Tentamen i Algoritmer & Datastrukturer i Java

DAT043 - föreläsning 8

Föreläsning 3-4 Innehåll

Lösningsförslag till tentamen i EDA690 Algoritmer och Datastrukturer, Helsingborg

Tentamen Datastrukturer (DAT036)

Kurskod D0010E Datum Skrivtid 5tim

Föreläsning Datastrukturer (DAT036)

Föreläsning 11. ADT:er och datastrukturer

Tentamen Datastrukturer D DAT 036/DIT960

Tentamen Programmering fortsättningskurs DIT950

Lösningsförslag till exempeltenta 2

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

LULEÅ TEKNISKA UNIVERSITET

Quicksort. Koffman & Wolfgang kapitel 8, avsnitt 9

Isometries of the plane

Föreläsning 2 Datastrukturer (DAT037)

Datastrukturer och algoritmer. Föreläsning 4 Test, Stack och Kö

Föreläsning 12. Länkade listor

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Graphs (chapter 14) 1

Föreläsning 8: Exempel och problemlösning

Preschool Kindergarten

Seminarium 3 Introduktion till Java Collections Framework Innehåll. Generik Bakgrund. Exempel på en generisk klass java.util.arraylist.

! Skall den vara generisk? ! Skall den vara självexpanderande? ! Skall vi ha en speciell klass för listnoder? ! osv

Föreläsning 3 Innehåll. Generiska klasser. Icke-generisk lista ArrayList, skiss av implementering. Icke-generisk lista Risk för fel

Objektsamlingar i Java

Intro till standardbiblioteket. Eric Elfving

Tentamen Datastrukturer (DAT036)

Lösningsförslag till tentamen Datastrukturer, DAT037,

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Tentamen i Algoritmer & Datastrukturer i Java

Lösningsförslag till exempeltenta 1

Objektorienterad Programkonstruktion. Föreläsning 9 30 nov 2016

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 5

Objektorienterad Programmering (TDDC77)

Dugga Datastrukturer (DAT036)

Vad kännetecknar en god klass. Vad kännetecknar en god klass. F12 Nested & Inner Classes

Föreläsning 14 Innehåll

Om oss DET PERFEKTA KOMPLEMENTET THE PERFECT COMPLETION 04 EN BINZ ÄR PRECIS SÅ BRA SOM DU FÖRVÄNTAR DIG A BINZ IS JUST AS GOOD AS YOU THINK 05

Schenker Privpak AB Telefon VAT Nr. SE Schenker ABs ansvarsbestämmelser, identiska med Box 905 Faxnr Säte: Borås

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

Övning 1 - Abstrakta datatyper

Outline. Objektorienterad Programmering (TDDC77) Abstrakta klasser. Abstrakta metoder. Abstrakta klasser. Gränssnitt. Uppräkningar (enum) Ahmed Rezine

Föreläsning Datastrukturer (DAT037)

Grafisk teknik IMCDP IMCDP IMCDP. IMCDP(filter) Sasan Gooran (HT 2006) Assumptions:

Övning vecka 5. Denna vecka ska vi titta pa samlingar, generics och designmönstren Decorator, Singleton och Iterator.

/* * * Lösningsförslag tentamen DIT950 * Datum * */ /* * -1 - */ För samtliga gäller,se föreläsningsanteckningar.

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

Exempeltenta GruDat 2002/2003

Java Collections Framework. Föreläsning 2 Innehåll. Java Collections Framework interface hierarki. Java Collections Framework interface hierarki

Självbalanserande träd AVL-träd. Koffman & Wolfgang kapitel 9, avsnitt 1 2

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

Seminarium 2 Introduktion till Java Collections Framework Innehåll. Generik Bakgrund. Exempel på en generisk klass java.util.arraylist.

Transkript:

So far... Complexity analysis For recursive and iterative programs Sorting algorithms Bubble, insertion, selection, quick, merge, counting Binary search, dynamic arrays Rest of course: lots of data structures!

Abstract data types and the Java collections framework (first half of chapter 6)

Abstract data type Separate the interface of a data structure from the implementation E.g., a set should support insertion, deletion and membership testing: interface Set<E> { void add(e element); void remove(e element); bool contains(e element); }

Abstract data type An ADT can have several implementations. For Set<E>, there is A dynamic array: O(1) insert, O(n) delete, O(n) contains A sorted dynamic array: O(n) insert, O(n) delete, O(log n) contains A balanced binary search tree (later): all operations O(log n) By using an ADT, you can easily switch to a different implementation.

Advantages of ADTs Can program to an interface and choose or change the implementation later Don't need to worry about implementation details: what index should I insert this new element in? Just use the methods the ADT defines.

Java collections framework The Java collections framework is a large library of data structures implementing abstract data types Collection List ArrayList, LinkedList,... Set HashSet, TreeSet,... Map HashMap, TreeMap, ConcurrentHashMap, Found under java.util.*

Collection<E> A collection of stuff in unspecified order, e.g. a list, a set,. Most Java data structures implement Collection<E>. interface Collection<E> { boolean isempty(); int size(); boolean contains(e x); An iterator Iterator<E> iterator(); // Optional boolean add(e x); boolean remove(e x); void clear(); }

Iterators An Iterator<E> lets us iterate over a collection: interface Iterator<E> { // Are there any objects left? boolean hasnext(); // Move to the next object. E next(); }

Using an iterator If coll has type Collection<E>, then for (E x: coll) { } which means the same as Iterator<E> it = coll.iterator(); while (it.hasnext()) { E x = it.next(); }

Iterators class ArrayList<E> implements Collection<E> { E[] array; int size; Compare with for-loop: for (int i = 0; Iterator<E> iterator() { final E[] array = this.array; i < size; final int size = this.size; i++) { return new Iterator<E>() { int i = 0; boolean hasnext() { } return i < size; } E next() { return array[i++]; } void clear() { throw new UnsupportedOperationException(); } } } }

Collection and Iterator Collection<E>: unordered collection of stuff Operations: add, remove, check for membership, iterate Iterator<E>: allows you to loop through a collection Built-in for-each syntax in Java The two most important ADTs in the Java collections framework most data structures extend Collection<E>

Linked lists (chapters 6.5, 17)

Enkellänkade listor Att lägga till och ta bort element inuti en ArrayList tar linjär tid O(n) vilket är oändligt långsamt i vissa applikationer En länkad lista kan lägga till och ta bort varsomhelt i en lista i konstant tid, O(1) å andra sidan tar det linjär tid O(n) att gå till en specifik position i en länkad lista, vilket är konstant i en ArrayList 1 5 I en länkad lista så är varje element ( nod ) länkad till det efterföljande elementet

En enkellänkad listnod innehåller noddata, och en länk till efterföljaren private static class Node<E> { private E data; private Node<E> next; } 1 6

Länkad representation av listan { Tom, Dick, Harry, Sam } 1 7

Operations on linked lists // Insert item at front of list void addfirst(e item) // Insert item after another item void addafter(node<e> node, E item) // Remove first item void removefirst() // Remove item after another item void removeafter(node<e> node)

Exempellista SLList<String> head = 1 9 Node<String> Node<String> next = data = "Tom" next = null data = "Dick"

Metoden addfirst(e item) SLList<String> head = Node<String> Node<String> next = data = "Tom" next = null data = "Dick" Node<String> next = data = "Ann" item.next = head; head = item; item 2 0

addafter(node<e> node, E item) SLList<String> head = Node<String> Node<String> next = data = "Tom" next = data = "Dick" node item.next = node.next; node.next = item; 2 1 Node<String> next = data = "Ann" item

removefirst() SLList<String> head = Node<String> Node<String> next = data = "Tom" next = data = "Dick" noden som tas bort 2 2 head = head.next;

removeafter(node<e> node) noden som tas bort SLList<String> Node<String> Node<String> next = data = "Tom" head = next = data = "Dick" node Node<String> node.next = node.next.next; 2 3 next = data = "Ann"

A problem It's annoying to have two versions of every operation: addfirst/addafter, removefirst/removeafter Why do we need addfirst/removefirst? We cannot use addafter/removeafter, because the first node is not after any other node Idea: add a header node, a fake node that sits at the front of the list but does not contain any data Instead of addfirst(x), you can do addafter(head, x)

List with header node (17.1.1) SLList<String> head = Node<String> Node<String> Node<String> next = data = next = data = "Tom" next = null data = "Dick" Here is the header node it does not contain any data 2 5

Doubly-linked lists With singly-linked lists you can only go forwards through the list Doubly-linked list: each node has a link to the next and the previous node You can in O(1) time: go forwards and backwards through the list insert a node before or after the current one modify or delete the current node The best data structure for sequential access!

Dubbellänkade listor 2 7

Operations on doubly-linked lists Similar to on singly-linked lists, but you have to update the prev pointer too. Deleting a node: node.next.prev = node.prev; node.prev.next = node.next; But this will CRASH if we try to delete the first node, since then node.prev == null! Same for the last node! We need lots of special cases in all our operations to work around this. if (node == head) else if (node == tail) else...

Operations on doubly-linked lists How can we get rid of all the special cases? Idea (see book): use a header node like for singlylinked lists, and also a footer node. head and tail will point at the header and footer node. Since you never delete the header or footer node, there are no special cases Problem: allocates two extra nodes per list Cute solution: circularly-linked list with header node

Circularly-linked list with header node LinkedList <String> Node<String> next = prev = data = "Tom" head = Node<String> next = prev = data = "Dick" next = prev = data = Node<String> Here is the header node ( prev links not shown) 3 0 Node<String> next = prev = data = "Harry"

Circularly-linked lists with header head.next is the first element in the list, and head.prev is the last element No special cases, since node.next and node.prev are never null, and you never need to delete head Quite simple to implement! Also possible to do it without a header node then you sometimes have to update head, so there are some special cases But we only need a pointer to the first element, not the last, so there are fewer special cases (the last node is head.prev)

Linked lists vs dynamic arrays Dynamic arrays: have O(1) random access (get and set) have amortised (average) O(1) insertion at end have O(n) insertion and deletion in middle Linked lists: have O(n) random access have O(1) sequential access have O(1) insertion in an arbitrary place Complement each other! Both implement the List interface.

List A List is a Collection that supports random and sequential access: interface List<E> extends Collection<E> { // get or set index idx E get(int idx); E set(int idx, E x); // add or remove at index idx boolean add(int idx, E x); void remove(int idx); ListIterator<E> listiterator(int idx); }

ListIterator A ListIterator is like an iterator, but you can go backwards, and you can add and remove elements at the current position: interface ListIterator<E> extends Iterator<E> { // go back boolean hasprevious(); E previous(); // add or remove an element void add(e x); void set(e x); void remove(); // actually in Iterator } A ListIterator points at a space between two elements! When you call add, the new element will go in this space. See the documentation for details.

What's the problem with this? int sum(linkedlist<integer> list) { int total = 0; for (int i = 0; i < list.size(); i++) total += list.get(i); return total; } list.get is O(n) so the whole thing is 2 O(n )!

Better! int sum(linkedlist<integer> list) { int total = 0; for (int i: list) total += i; return total; } Remember linked lists are for sequential access only

Linked lists summary Efficient data structure for sequential access to a list Singly-linked can only go forwards Doubly-linked can go forwards or backwards Many variations header nodes, circular lists but they all implement the same ADT Can insert or delete or modify a node in O(1) time But unlike arrays, random access is O(n) LinkedList<E> class in Java

Stacks and queues (chapters 6.6, 16)

Stackar Det översta elementet är det senaste LIFO = Last-In-First-Out Stackar används överallt i datorer t.ex. vid funktions-/metodanrop (run-time stack, call stack) 4 0

Balanserade parenteser Vi behöver en stack för att kontrollera ifall ett uttryck har balanserade parenteser: speciellt om uttrycket kan innehålla olika sorters parenteser (a+b*[c/{d e}])+{d/e} Algoritmidé: när vi läser (, [ eller { så lägger vi den på stacken när vi läser ), ] eller } så poppar vi stacken och kontrollerar att parenteserna stämmer 4 1

Balanserade parenteser, iterativt private static final String PARENS = "()[]{}"; public static void parseparensiterative(string str) throws ParseException { Stack<Integer> parenstack = new Stack<Integer>(); for (int i = 0; i < str.length(); i++) { char c = str.charat(i); int paren = PARENS.indexOf(c); vi behöver en stack för if (paren >= 0) { att hålla reda på if (paren % 2 == 0) { parenteserna parenstack.push(paren); detta } else { förutsätter att if (parenstack.empty()) ([{ ligger på throw new ParseException("Too many close parentheses", i); jämna index int openparen = parenstack.pop(); i PARENS if (paren!= openparen + 1) throw new ParseException("Unbalanced parentheses", i); } detta förutsätter att ( och ) ligger } efter varandra i PARENS } if (!parenstack.empty()) throw new ParseException("Too many open parentheses", str.length()); } 4 2

Implementera en stack Vi kan implementera stacken som ett fält: vi måste kunna omallokera fältet det blir väldigt likt en ArrayList Vi kan implementera stacken som en länkad lista: det blir väldigt likt en LinkedList Vi kan också använda intern privat lista: t.ex. ArrayList eller LinkedList stackmetoderna (t.ex. push(e)) kommer då att anropa den interna listans metoder (t.ex. add(e)) det kallas delegering 4 4

En stack som en länkad lista När listan är tom så är denna null Vi lägger till och tar bort element i början av listan 4 5

A stack as a linked list Really easy! LinkedList<E> list = new void push(e x) { list.addfirst(x); } E pop() { return list.removefirst(); } E peek() { return list.getfirst(); }

Do we need a separate stack ADT? Since it's so easy to implement a stack as a linked list, why do we want a separate Stack<E> interface? Using Stack<E> allows us to switch to a different implementation (like an array) We also get only the operations that we need But in Java Stack<E> is a class extending Vector<E>! This is a mistake. Use Deque<E> (later) instead

Komplexitet för stackmetoder Den stora fördelen med stackar är att de är väldigt effektiva: alla operationer har konstant tidskomplexitet, O(1) dvs, push(e), pop(), peek() och empty() 4 8

Köer Översta elementet är det som har väntat längst FIFO = First-In-First-Out Köer är ett vanligt alternativ till stackar: används i operativsystem för att hålla koll på processer som väntar på en resurs, t.ex. en skrivarkö flera algoritmer använder köer för att implementera bredden-först-sökning 4 9

LinkedList är en Queue Java har ett gränssnitt för köer: java.util.queue är en utökning av java.util.collection java.util.linkedlist implementerar java.util.queue För att skapa en kö i Java: Queue<String> names = new LinkedList<String>(); detta skapar en LinkedList, men eftersom variabeln är deklarerad som en Queue så kan vi bara använda kömetoderna Java har inget gränssnitt för stackar: java.util.stack är en klass, inte ett gränssnitt DÅLIG design! 5 1

Att implementera en kö Vi kan implementera kön som en dubbellänkad lista: det är så det är gjort i Java, eftersom LinkedList är en dubbellänkad lista Men det är egentligen onödigt det går precis lika bra med en enkellänkad lista: vi måste ha en pekare till huvudet och en pekare till svansen vi stoppar in element i svansen och tar ut dem i huvudet Det funkar också att implementera som ett cirkulärt fält: vi måste ha två heltalsvariabler som säger var början resp. slutet av kön är precis som en ArrayList måste vi kunna omallokera fältet när kön blir för stor 5 2

En kö som en enkellänkad lista Insättningar görs sist i listan: Jones är alltså det senast tillagda elementet vi behöver peka om rear.next och sedan rear till den nya noden Element tas bort från början av listan: Thome är alltså det element som har väntat längst vi behöver peka om front till front.next 5 3

En kö som ett fält Vi kan implementera en kö som ett fält. Antingen med översta elementet först: insättning i slutet = O(1) borttagning i början = O(n) Eller med översta elementet sist: insättning i början = O(n) borttagning i slutet = O(1) Dvs, alldeles för ineffektivt. Lösningen är att använda ett cirkulärt fält. 5 4

En kö som ett cirkulärt fält Queue contains everything between front and rear: & * + / - 5 5

Ett cirkulärt fält Here, front comes after rear! Array is circular: queue contains * + / - A 5 6

Exempel front ArrayQueue q = new ArrayQueue(5); 0 1 2 3 rear 4 size = 0 capacity = 5 5 7 public ArrayQueue(int initcapacity) { capacity = initcapacity; thedata = (E[]) new Object[capacity]; front = 0; rear = capacity 1; size = 0; }

Exempel front rear 0 1 2 3 4 size = 1 capacity = 5 5 8 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public boolean offer(e item) { if (size == capacity) reallocate(); size++; rear = (rear + 1) % capacity; thedata[rear] = item; return true; }

Exempel front 0 rear 1 + 2 3 4 size = 2 capacity = 5 5 9 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public boolean offer(e item) { if (size == capacity) reallocate(); size++; rear = (rear + 1) % capacity; thedata[rear] = item; return true; }

Exempel front rear 0 1 + 2 / 3 4 size = 3 capacity = 5 6 0 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public boolean offer(e item) { if (size == capacity) reallocate(); size++; rear = (rear + 1) % capacity; thedata[rear] = item; return true; }

Exempel front rear 0 1 + 2 / 3 4 size = 4 capacity = 5 6 1 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public boolean offer(e item) { if (size == capacity) reallocate(); size++; rear = (rear + 1) % capacity; thedata[rear] = item; return true; }

Exempel front rear 0 1 + 2 / 3 4 A size = 5 capacity = 5 6 2 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public boolean offer(e item) { if (size == capacity) reallocate(); size++; rear = (rear + 1) % capacity; thedata[rear] = item; return true; }

Exempel 0 front rear 2 + / 3 4 A 1 size = 4 capacity = 5 6 3 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public E poll() { if (size == 0) return null; E result = thedata[front]; front = (front + 1) % capacity; size--; return result; }

Exempel 0 1 front rear 2 / 3 4 A size = 3 capacity = 5 6 4 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public E poll() { if (size == 0) return null; E result = thedata[front]; front = (front + 1) % capacity; size--; return result; }

Exempel rear 0 B 1 front 2 / 3 4 A size = 4 capacity = 5 6 5 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public E poll() { if (size == 0) return null; E result = thedata[front]; front = (front + 1) % capacity; size--; return result; }

Exempel 0 B rear 1 C front 2 / 3 4 A size = 4 capacity = 5 6 6 ArrayQueue q = new ArrayQueue(5); q.offer( ); q.offer( + ); q.offer( / ); q.offer( ); q.offer( A ); next = q.poll(); next = q.poll(); q.offer( B ); q.offer( C ); q.offer( D ); public E poll() { if (size == 0) return null; E result = thedata[front]; front = (front + 1) % capacity; size--; return result; }

Exempel front 0 / 1-2 3 rear 4 5 6 7 8 9 6 7 A B C Reallocate 0 B rear 1 C front 2 / 3 4 A j

Deque (double-ended queue) En deque är både en stack och en kö, samtidigt: addfirst(e), addlast(e) pollfirst(), polllast() java.util.deque är ett gränssnitt; det finns två färdiga implementeringar: java.util.arraydeque<e> java.util.linkedlist<e> 6 8

addfirst(e item) java.util.deque addlast(e item) 6 9

Exempel på deque-metoder: 7 0

Functional stacks type Stack a =??? push :: a Stack a Stack a pop :: Stack a Stack a peek :: Stack a a empty :: Stack a Bool

Really easy! type Stack a = [a] push :: a Stack a Stack a push x xs = x:xs pop :: Stack a Stack a pop (x:xs) = xs peek :: Stack a a peek (x:xs) = x empty :: Stack a Bool empty [] = True empty (x:xs) = False

Functional queues type Queue a =??? enqueue :: a Queue a Queue a dequeue :: Queue a (a, Queue a) empty :: Queue a Bool

One implementation... type Queue a = [a] enqueue :: a Queue a Queue a enqueue x xs = xs ++ [x] dequeue :: Queue a (a, Queue a) dequeue (x:xs) = (x, xs) empty :: Queue a Bool empty [] = True empty (x:xs) = False But enqueue takes O(n) time!

Solution... Represent a queue by a pair of lists (xs, ys) xs: elements that we can dequeue ys: elements that we have enqueued, in reverse order For example, ([1,2,3],[6,5,4]) would represent the queue 1 2 3 4 5 6 Enqueue adds an element to ys, dequeue removes an element from xs But this cannot possibly work how do elements get from ys to xs?

Solution... If we dequeue ([], [6,5,4]), there is no element to remove from xs, but the queue is supposed to contain 4 5 6! If xs is empty when we dequeue, reverse ys and replace xs with it... ([4,5,6], [])...then perform the dequeue as normal: ([5,6], [])

The implementation type Queue a = ([a], [a]) enqueue :: a Queue a Queue a enqueue x (xs, ys) = (xs, x:ys) dequeue dequeue dequeue where :: Queue a (a, Queue a) (x:xs, ys) = (x, (xs, ys)) ([], ys) = (x, (xs, [])) x:xs = reverse ys empty :: Queue a Bool empty ([],[]) = True empty _ = False

The complexity? Imagine the lifecycle of an element. It starts by being enqueued (O(1) time). Eventually it is dequeued (O(1) time). In the middle it must be moved from the second list to the first list. This takes O(n) time if the second list has n elements O(1) time per element. We can say that dequeue is amortised O(1) time some dequeues may take longer, if we have to reverse the list, but n operations take O(n) time.

Stacks and queues summary Both widely used and can be implemented efficiently Both easy to implement in an imperative language with linked lists or dynamic arrays Stacks easy to implement in a functional language, queues a bit harder and with O(1) amortised complexity a bit less efficient Both special cases of a deque: Stack: insert at beginning, remove from beginning Queue: insert at beginning, remove from end