• No results found

Föreläsning 3-4 Innehåll

N/A
N/A
Protected

Academic year: 2022

Share "Föreläsning 3-4 Innehåll"

Copied!
76
0
0

Loading.... (view fulltext now)

Full text

(1)

Föreläsning 3-4

Innehåll

Listor, stackar, köer

Abstrakta datatypen lista

listklasser i Java, egen implementering

Datastrukturen enkellänkad lista

Jämföra element – metoden equals, interfacet Comparable Abstrakta datatyperna stack och kö

Undervisningsmoment:

föreläsning 3-4, övningsuppgifter 4-5 och laboration 2 Avsnitt i läroboken:

2.2–2.4, 2.5–2.8, 2.10, 4.1–4.3, 4.5–4.8. Läs gärna även kap 3 (om testning).

(2)

Abstrakta datatypen lista

Definition

En lista är en följd av element.

Det finns en före-efter-relation mellan elementen.

Begrepp som ”första elementet i listan”, ”efterföljaren till visst element i listan” är meningsfulla. Det finns alltså ett positionsbegrepp.

Definitionen innebär inte att elementen är sorterade på något visst sätt t.ex. i storleksordning.

1:a elementet 2:a elementet 3:e elementet 4:e elementet

(3)

Abstrakt datatypen lista

Abstrakt datatyp

En abstrakt modell tillsammans med de operationer man kan utföra på den.

Abstrakt modell: lista

Operationer på modellen:

Lägga in element i listan (först, sist ...) Ta bort ett element ur listan

Undersöka om ett visst element finns i listan

Ta reda på ett elementet i listan (första, sista ...) Undersöka om listan tom

...

En ADT kan beskrivas av en specifikation av en klass eller av ett interface (t.ex. List i paketet java.util)

(4)

Abstrakta modellen lista

Abstrakt modell Verkliga problem

Bokregister

Kö av människor

Lista

Schema

Inköpslista

(5)

Implementering av listor

En vektor kan användas för att hålla reda på listans element.

0 1 2 3

Ett annat sätt är att utnyttja länkad datastruktur.

I en länkad struktur består listan av noder som har en referens till efterföljaren (och ev. till föregångaren).

(6)

Listklasser i java.util

Det finns två konkreta generiska klasser i Javas API för listhantering. Båda implementerar interfacet List.

ArrayList<E>, som implementerats med vektor

LinkedList<E>, som implementerats med en dubbel-länkad cirkulär struktur

<<Interface>>

Collection

ArrayList

<<Interface>>

List

LinkedList

<<Interface>>

Iterable

(7)

Användning av ArrayList/LinkedList

Traversering

List<Person> list = new ArrayList<Person>();

list.add(new Person("Kili", 1));

list.add(new Person("Balin", 2));

list.add(new Person("Dori", 3));

// skriv ut alla personerna for (Person p: list) {

System.out.println(p);

}

// samma sak med explicit iterator

Iterator<Person> itr = list.iterator();

while (itr.hasNext()) {

System.out.println(itr.next());

}

(8)

Skugga toString

Inuti println(p) anropas metoden toString på p. Metoden toString finns i superklassen Object.

Skugga (omdefiniera) metoden toString för att bestämma hur utskriften av objektet ska se ut:

public class Person { private String name;

private int id;

public Person (String name, int id) { this.name = name;

this.id = id;

}

public String toString() { return name + " " + id;

} }

(9)

Interfacet ListIterator

Interfacet List i java.util föreskriver att det för listor även ska finnas metoder:

/** Returnerar en listiterator som startar i pos i. */

public ListIterator listIterator(int i);

/** Returnerar en listiterator som startar i pos 0. */

public ListIterator listIterator();

ListIterator<E> är ett interface som ärver Iterator<E> och där man lagt till metoder för att röra sig även bakåt i listor samt för att sätta in element.

(10)

Interfacet ListIterator

<<Interface>>

Iterator

<<Interface>>

ListIterator

public interface ListIterator<E> extends Iterator<E> { boolean hasPrevious();

E previous();

void add(E x);

...

}

(11)

Diskutera

Följande klass beskriver en person:

public class Person {

private String name;

private int;

public Person (String name, int id) { this.name = name;

this.id = id;

} }

Vad skrivs ut när följande rader exekveras? Förklara varför?

ArrayList<Person> list = new ArrayList<Person>();

list.add(new Person("Fili", 1));

list.add(new Person("Balin", 2));

System.out.println(list.contains(new Person("Balin", 2)));

(12)

Jämföra likhet

Metoden equals

Inuti ArrayList används metoden equals för att jämföra om två objekt är lika:

if (p1.equals(p2)) {...}

Metoden equals finns i superklassen Object. Den returnerar true om och endast om de jämförda objekten är identiska. Den testar referenslikhet och fungerar alltså som == i Java.

Om vi istället vill att innehållet inuti objekten ska jämföras (här id-numren) måste vi skugga equals klassen Person.

Skiss, ej färdig equals-metod:

public boolean equals(Object obj) { return id == ((Person) obj).id;

}

(13)

Jämföra likhet

Skillnad Java - Scala

I Java är == en operator som jämför referenser. Exempel: p1 == p2 ger true om p1 och p2 refererar till samma objekt.

I klassen Object finns metoden equals som fungerar som ==. Den måste skuggas om man vill få ett annat beteende i egna klasser.

I Scala är == en metod som anropar equals. Skugga equals om annat beteende önskas.

Metoden eq testar referenslikhet och p1.eq(p2) ger true om p1 och p2 refererar till samma objekt.

(14)

Användning av ArrayList/LinkedList

Söka efter objekt i en lista

List<Person> list = new ArrayList<Person>();

list.add(new Person("Kili", 1));

list.add(new Person("Balin", 2));

list.add(new Person("Dori", 3));

// sök efter platsen för elementet med id-nummer 2 int index = list.indexOf(new Person(null, 2));

// tag reda på om det finns ett element med id-nummer 2 i listan boolean found = list.contains(new Person(null, 2));

// tag bort elementet med id-nummer 2 ur listan

boolean removed = list.remove(new Person(null, 2));

(15)

Skugga equals – att tänka på

Parametern till equals måste vara av typ Object, annars blir det inte skuggning och den ursprungliga metoden i klassen Object kommer att användas.

De attribut som används i jämförelsen inuti equals bör inte gå att ändra. Deklarera dem final:

public class Person { private String name;

private final int id;

...

Annars kan det bli svårt att hitta objektet när det satts in i en lista eller annan samling.

När man skuggar equals bör man också skugga metoden hashCode.

Metoderna equals och hashCode används när objekt sätts in i en hashtabell. (Behandlas senare i kursen).

(16)

Skugga equals

Specifikation

public boolean equals(Object obj);

Ur equals specifikation:

x.equals(x) ska returnera true (reflexivitet).

Om x.equals(y) returnerar true så ska y.equals(x) returnera true (symmetri).

Om x.equals(y) returnerar true och y.equals(z) returnerar true så ska x.equals(z) returnera true (transitivitet).

Upprepade anrop av x.equals(y) ska ge samma resultat (konsistens).

x.equals(null) ska returnera false.

(17)

Omdefiniera equals – med instanceof

public boolean equals(Object obj) { if (obj instanceof Person) {

return idNbr == ((Person) obj).idNbr;

} else {

return false;

} }

Observera att parametern till equals måste vara av typ Object,

annars blir det inte skuggning. Därför måste också typomvandling till Person ske när man ska använda obj:s idNbr.

Uttrycket obj instanceof Person returnerar true om obj:s typ är Person eller någon subklass till Person.

Uttrycket obj instanceof Person returnerar false om obj har värdet null.

(18)

Skugga (skugga) equals – med instanceof

Fördelar och nackdelar

Denna lösningen tillåter att subklasser ärver equals-metoden.

Man kan därför använda equals i en arvshieariki och jämföra

”subklassobjekt” och ”superklassobjekt”.

Kan leda till att equals inte uppfyller kraven i specifikationen om man skuggar equals i subklassen.

Därför är det lämpligt att deklarera metoden equals final:

public final boolean equals(Object obj) { ...

Nu kan inte equals skuggas i någon subklass till Person.

Detta undviks om man bara tillåter jämförelser mellan objekt av samma typ. Se nästa bild.

(19)

Skugga equals – med getClass

public boolean equals(Object obj) { if (obj == this) {

return true;

}

if (obj == null) { return false;

}

if (this.getClass() != obj.getClass()) { return false;

}

return id == ((Person) obj).id;

}

Metoden getClass returnerar typen för det objekt obj refererar till under exekveringen.

Bara metoder av exakt samma klass kan anses vara lika.

(20)

Skugga equals – med extra metod canEqual

Ibland blir lösningen på förra bilden för sträng. Det kan man lösa genom att lägga till en extra metod i klassen:

public boolean equals(Object obj) { if (obj instanceof Person) {

Person other = (Person) obj;

return other.canEqual(this) && this.id == other.id;

} else {

return false;

} }

public boolean canEqual(Object other) { return (other instanceof Person);

}

Bägge metoderna ska skuggas i subklasser. För detaljer läs mer här:

www.artima.com/lejava/articles/equality.html

(21)

Diskutera

Sortera objekt

Klassen Person beskriver en person. Vad händer när följande rader exekveras? Förklara varför?

Person[] persons = new Person[4];

persons[0] = new Person("Kili", 1);

persons[1] = new Person("Balin", 2);

persons[2] = new Person("Dori", 4);

persons[3] = new Person("Fili", 3);

Arrays.sort(persons);

for(Person p : persons) { System.out.println(p);

}

(22)

Interfacet Comparable

Specifikation

I Java finns ett generiskt interface, Comparable<T>:

public interface Comparable<T> { /**

* Compares this object with the specified object for order.

* Returns a negative integer, zero, or a positive integer as

* this object is less than, equal to, or greater than the

* specified object.

*/

public int compareTo(T x);

}

Objekt av klasser som implementerar detta interface går att jämföra med varandra och kan t.ex. sorteras.

Inuti metoden sort används Comparable som typ för de element som ska sorteras.

(23)

Implementering av interfacet Comparable

Exempel

public class Person implements Comparable<Person> { private String name;

private int id;

...

public int compareTo(Person obj) {

return Integer.compare(id, obj.id); } public boolean equals(Object obj) {

if (obj instanceof Person) {

return compareTo((Person) obj) == 0;

} else {

return false;

} }

(24)

Jämföra likhet

Metoderna compareTo och equals

Interfacet Comparable innehåller bara metoden compareTo.

Men för klasser som implementerar interfacet Comparable finns det två sätt att jämföra avseende likhet:

Person p1 = ...;

Person p2 = ;...

if (p1.compareTo(p2) == 0) {...}

if (p1.equals(p2)) {...}

Båda sätten att jämföra bör ge konsistenta resultat.

Därför bör metoden equals skuggas i klasser som implementerar Comparable.

(25)

Typparametrar med begränsningar

Ibland behöver man ange begränsning på typparmetern:

public class ASortedCollection<E extends Comparable<E>>

<E extends T> betyder:

E måste vara subklass till T om T är en klass. Det är också tillåtet att E

= T.

E måste implementera interfacet T om T är ett interface.

I exemplet ovan anger vi alltså att E måste vara en typ som

implementerar interfacet Comparable<E>. Vi kan därmed använda metoden compareTo på objekt av typen E i implementeringen av ASortedCollection.

(26)

Egen implementering av listor från grunden

Vektor

objekt som satts in i vektorn

0 1 2 3

a

4 5 6 7

3 size

8 9

(27)

Egen implementering av listor från grunden

Enkellänkad lista

first next null

element

objekt som satts in i listan next

element next

element

(28)

Enkellänkad lista

Implementering

public class SingleLinkedList<E> {

private ListNode<E> first; // referens till första noden // null om listan är tom

..metoder..

/* Statiskt nästlad klass. Representerar en nod som innehåller ett element av typ E. */

private static class ListNode<E> {

private E element; // data som lagras

private ListNode<E> next; // refererar till nästa nod private ListNode(E e) {

element = e;

next = null;

} }

}

(29)

Nästlade klasser i Java

Klasser kan deklareras inuti andra klasser (nästlade klasser).

Används oftast när den nästlade klassen bara är meningsfull för den omgivande klassen.

Användare behöver oftast inte känna till existensen av den nästlade klassen.

En nästlad klass kan deklareras private om den bara ska användas i den omgivande klassen. Även konstruktorn kan då vara private.

I den omgivande klassen har man tillgång till allt i den nästlade klassen (även det som är private).

Det finns två typer av nästlade klasser:

statiskt nästlade klasser

inre klasser (eng: inner classes).

(30)

Statiskt nästlade klasser

public class OuterClass { ...

public void p() {

NestedClass x = new NestedClass();

...

}

private static class NestedClass { private NestedClass() {...}

...

} }

En statisk nästlad klass kan bara komma åt statiska attribut och statiska metoder i den omgivande klassen.

(31)

Inre klasser

public class OuterClass { private int i;

public void p() {

InnerClass x = new InnerClass();

...

}

private class InnerClass {

private InnerClass() {...}

private void q() {

int b = i; ...; // Här används i från OuterClass!

} }

}

Ett objekt av en inre klass kan komma åt allt i det objekt av den

(32)

Att skapa objekt av nästlade klasser

Görs oftast bara i den omgivande klassen.

Då blir det samma syntax som vanligt.

Exempel finns på föregående bilder.

Man kan skapa objekt av nästlade klasser även utanför den omgivande klassen.

Kräver dock att den nästlade klassen och dess konstruktor är public.

Detaljer på nästa bild.

(33)

Att skapa objekt av nästlade klasser

Statiska nästlade klasser

Om den nästlade klassen är statisk:

public class OuterClass { ...

public static class NestedClass { public NestedClass() {...}

...

} }

så skapas en instans av den nästlade klassen med följande syntax:

OuterClass.NestedClass x = new OuterClass.NestedClass(...);

(34)

Att skapa objekt av nästlade klasser

Inre klasser

Om den nästlade klassen är en inre klass:

public class OuterClass { ...

public class InnerClass {

public InnerClass(...) {...}

...

} }

så kan instanser av den inre klassen bara skapas genom ett objekt av den yttre klassen:

OuterClass a = new OuterClass();

OuterClass.InnerClass b = a.new InnerClass();

(35)

Åter till implementeringen av listor ...

På följande bilder visas implementeringar av några metoder i klassen SingeLinkedList. (Ytterligare exempel finns i övningsuppgifter 4.)

public class SingleLinkedList<E> { private ListNode<E> first;

...

private static class ListNode<E> {

private E element; // data som lagras

private ListNode<E> next; // refererar till nästa nod ...

} }

(36)

Exempel på metoder i en enkellänkad lista

Insättning och borttagning först i listan

Länka in en ny nod innehållande elementet x först i listan:

public void addFirst(E x) {

ListNode<E> n = new ListNode<E>(x);

n.next = first;

first = n;

}

Tag bort första noden i listan, returnera dess innehåll:

public E removeFirst() { if (first == null) {

throw new NoSuchElementException();

}

ListNode<E> temp = first;

first = first.next;

return temp.element;

}

(37)

Exempel på metoder i en enkellänkad lista

Traversering av elementen i listan

Returnera en sträng som representerar listan:

public String toString() {

StringBuilder sb = new StringBuilder();

sb.append(’[’);

ListNode<E> p = first;

while (p != null) {

sb.append(p.element.toString());

if (p.next != null) { sb.append(", ");

}

p = p.next;

}

sb.append(’]’);

return sb.toString();

}

(38)

Diskutera

Antag att vi ska skriva metoder addLast och removeLast för att sätta in och ta bort sist listan.

Hur ska vi lösa de problemen?

Vilka specialfall finns?

(39)

Exempel på metoder i en enkellänkad lista

Insättning sist i listan

Länka in en ny nod innehållande elementet x sist i listan:

public void addLast(E x) {

ListNode<E> n = new ListNode<E>(x);

if (first == null) { first = n;

} else {

ListNode<E> p = first;

while(p.next != null) { p = p.next;

}

p.next = n;

} }

(40)

Exempel på metoder i en enkellänkad lista

Borttagning sist i listan

public E removeLast() {

if (first == null) { // tom lista throw new NoSuchElementException();

}

if (first.next == null) { // ett element ListNode<E> temp = first;

first = null;

return temp.element;

}

ListNode<E> p = first; // minst två element ListNode<E> pre = null;

while (p.next != null) { pre = p;

p = p.next;

}

pre.next = null;

return p.element;

}

(41)

Diskutera

Två av metoderna vi implementerat, addlast och removeLast, är långsammare än motsvarande metoder för att sätta in och ta bort i början av listan. Både addlast och removeLast innehåller en loop.

Ge förslag på hur man kan implementera listklassen så att dessa loopar kan tas bort.

(42)

Implementering med länkad struktur

Kommentarer

Exemplen visar att det är viktigt att tänka på specialfall.

Vissa operationer blir krångliga i den enkellänkade implementeringen.

Dessa kan förenklas om man i varje nod också har en referens till föregångaren. Detta kallas dubbellänkade listor.

first last

Man kan förenkla implementeringar av vissa operationer ytterligare genom att ha ett speciellt element ("huvud") i början av listan.

(43)

Traversering av listor – iteratorer

Användare av en listklass behöver möjlighet att gå igenom elementen i listan. Låt därför SingleLinkedList implementera interfacet Iterable:

public class SingleLinkedList<E> implements Iterable<E> { ...

Lägg till metoden

Iterator<E> iterator()

i klassen SingleLinkedList. Metoden iterator ska skapa och returnera ett iterator-objekt.

Skriv en (inre) klass som implementerar interfacet Iterator enligt mönstret:

private class MyListIterator implements Iterator<E> {...}

(44)

Interfacet Iterator

metoder

/** Returns true if the iteration has more elements. */

boolean hasNext();

/** Returns the next element in the iteration. */

E next();

/** Removes from the underlying collection the last element returned by the iterator (optional). */

default void remove();

Metoder deklarerade default är redan implementerade. Default-metoden remove genererar UnsupportedOperationException.

(45)

Iteratorklass

Inre klassen MyListIterator

private class MyListIterator implements Iterator<E> { private ListNode<E> pos;

private MyListIterator() {pos = first;}

public boolean hasNext() {return pos != null;}

public E next() { if (hasNext()) {

ListNode<E> temp = pos;

pos = pos.next;

return temp.element;

} else {

throw new NoSuchElementException();

} }

...

(46)

Metoden iterator()

Klassen SingleListIterator

public class SingleLinkedList<E> implements Iterable<E> { private ListNode<E> first;

...

public Iterator<E> iterator() { return new MyListIterator();

}

private class MyListIterator implements Iterator<E> {...}

...

}

(47)

Användning av iterator

Exempel

Nu kan vi iterera genom vår lista:

SingleLinkedList<String> list = new SingleLinkedList<String>();

// sätt in några String-objekt i listan ...

Iterator<String> itr = list.iterator();

while (itr.hasNext()) { String s = itr.next();

...

}

Eftersom vår klass SingleLinkedList implementerar interfacet Iterable kan vi också använda ”foreach”-satsen:

for (String s : list) { ...

}

(48)

Diskutera

Nu när vi implementerat en egen list-klass kan vi jämföra olika list-implementationer:

ArrayList implementeras med hjälp av en vektor:

0 1 2 3 4 5 6 7 8 9

Inuti LinkedList används en cirkulär, dubbellänkad struktur:

Fördelar, nackdelar?

(49)

ArrayList vs LinkedList

ArrayList

De indexerade metoderna get(int idx) och set(int idx, E element) är effektiva i ArrayList.

Däremot är insättningar och borttagningar (utom sist i listan) långsamma eftersom element måste flyttas.

LinkedList

De indexerade metoderna är långsamma eftersom listan måste stegas igenom tills önskat element nås.

När man väl hittat rätt plats i listan är insättningar och borttagningar snabba.

Nod-objekten kräver extra minne och hantering.

(50)

ADT Stack

Definition

En stack är en följd av element där borttagning av ett element alltid aer det element som senast satts in.

Kallas även LIFO-lista, Last In First Out

(51)

ADT Stack

En stack beskrivs oftast lodrätt orienterad.

Operationer sker på toppen av stacken.

push pop

(52)

ADT Stack i java.util

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.

Interfacet Deque i java.util innehåller bl. a. de 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()

Exempel på klasser som implementerar interfacet Deque är ArrayDeque och LinkedList.

(53)

Diskutera

Klasserna på föregående bild innehåller för många metoder och inte bara de vanliga stack-operationerna.

Varför är det ett problem?

Hur kan man lösa detta?

(54)

Interface Stack – som det borde se ut

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();

/** Returnerar översta elementet på stacken. */

E peek();

/** Undersöker om stacken är tom. */

boolean isEmpty();

}

(55)

Exempel på användning av stack

En stack kan också användas till att

Kontrollera att parenteser matchar:

Om vänsterparentes push(parentes) Om högerparentes

pop()

Vända på elementen i en lista:

För varje element e i listan push(e)

Så länge stacken ej är tom pop()

(56)

Exempel på användning av stack

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.

Operatorn placeras efter sina två operander: 10 12 –

Ex: 3 10 12 – * i postfix notation motsvarar uttrycket 3 * (10 – 12) 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.

(57)

Exempel på användning av stack

Algoritm

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 t1 och t2 // 2 st. pop från stacken

res = resultatet av operatorn använd på t2 och t1

lägg res på stacken // push

Nu ska stacken bara innehålla ett värde – resultatet.

(58)

Exempel på användning av stack

Evaluering av uttrycket: 3 10 12 – *

Läst: inget 3 10 12 - *

12

10 10 -2

Stack: tom 3 3 3 3 -6

Om uttrycket är korrekt så ligger till sist resultatet som enda element på stacken.

(59)

Diskutera

Antag att vi behöver en stack i ett program.

Ska vi använda en färdig klass?

Eller ska vi implementera en egen klass? Hur i så fall?

Vilka för- och nackdelar har de olika alternativen?

(60)

Implementering av stack – använd färdig klass

Alternativ 1

Gör inte någon ny implementering utan använd en redan färdig klass t.ex. ArrayDeque eller LinkedList i java.util. Använd bara de

operationer som är tillåtna för stack.

+ Enkelt

– Övriga icke-stack-metoder finns tillgängliga. Risk för att anropa fel metod.

(61)

Implementering av stack - delegera till annan klass

Alternativ 2

Implementera en egen klass, men använd internt en annan klass.

Exempel:

public class Stack<E> {

private LinkedList<E> elements; // eller ArrayDeque<E>

...

public push(E x) {

elements.push(x);

}

public E peek() {

return elements.peek();

} ...

}

(62)

Delegera till annan klass, forts

Alternativ 2

+ Slipper risken att anropa fel metoder

– Många metodanrop. Om vi anropar push i Stack, så anropas också push i LinkedList, ...

– Onödigt komplicerad datastruktur som ev. är vald för att andra metoder ska bli effektiva.

Exempel: Datastrukturen i LinkedList är vald så att operationerna på listan ska bli effektiva. Det ät onödigt med dubbellänkad lista för att implementera en stack.

(63)

Implementering av stack - egen klass med enklare datastruktur

Alternativ 3

Implementera en egen klass med enklare datastruktur, t.ex. vektor eller enkellänkad lista.

+ Slipper risken att anropa fel metoder

+ Färre metodanrop än alternativ 2. T.ex. utför då push sin uppgift utan att delegera vidare till annan metod.

+ En enklare datastruktur kan ge bättre effektivitet.

– Mer kod att implementera än i alternativ 1 och 2.

(64)

Implementering av stack

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

(65)

Enkellänkad implementering av stack

first 3 2 1

first 2 1

first 1

first = null s = new MyStack<Integer>();

s.push(1);

s.push(2);

s.push(3);

first 2 1

int i = s.pop() // i får värdet 3

(66)

Vektorimplementering av stack

Vektorimplementering av stack:

Stacken representeras av vektor och index för nästa insättning (initialt 0).

Ger konstant tid för metoderna så länge vektorns storlek räcker.

Om man dubblar vektorns storlek varje gång den inte räcker till, kan man visa att metoderna fortfarande i medeltal går att utföra på

konstant tid.

Efter dubblering är bara halva utrymmet i vektorn utnyttjat.

(67)

Vektorimplementering av stack

s = new MyStack<Integer>();

s.push(1);

s.push(2); s.push(3)

int i = s.pop() // i får värdet 3

size = 0

size = 1

size = 3

size = 2

size = 3 s.push(4);

1

1

1

1

2

2

2

3

4 3

(68)

ADT Kö

Definition

En kö (FIFO-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.

First In First Out

offer poll

(69)

Interface Queue – minimalt

public interface Queue<E> {

/** Sätter in x sist i kön. */

boolean offer(E e);

/** Tar reda på första elementet i kön. */

E peek();

/** Tar reda på och tar bort första elementet i kön. */

E poll();

/** Undersöker om kön är tom. */

boolean isEmpty();

}

(70)

Interface Queue i java.util

<<Interface>>

Collection

ArrayDequeu

<<Interface>>

Queue

LinkedList

<<Interface>>

Iterable

Genererar exception vid problem

Returnerar false/null vid problem

Sätta in boolean add(E x) boolean offer(E x)

Ta bort E remove() E poll()

Ta reda på E element() E peek()

(71)

Implementering av kö

Enkellänkad datastruktur

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 last

(72)

Enkellänkad implementering av kö

first 1 2 3

first 1

first = last = null q = new MyQueue<Integer>();

q.offer(1);

q.offer(2);

q.offer(3);

first 1 2

int i = q.poll() // i får värdet 1

last

last

last

first 2 3

last

(73)

Vektorimplementering av kö

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 samt

index för första (äldsta) elementet – front index för sista (yngsta) elementet– rear antalet element – size

Även här kan vi behöva skapa större vektor när antalet element blivit för stort.

(74)

Vektorimplementering av kö

q = new MyQueue<Integer>();

q.offer(1);

q.offer(2); q.offer(3);

q.offer(4); q.offer(5);

int i = q.poll() // i får värdet 1

front = 0, rear = -1, size = 0

front = 0, rear = 0, size = 1

front = 0, rear = 4, size = 5

front = 1, rear = 4, size = 4

front = 1, rear = 0, size = 5 q.offer(6);

1

1

1

6

2

2

2

3

3

3 4 5

4 5

4 5

(75)

Listor, stackar och köer

Exempel på vad du ska kunna

Förklara vad de abstrakta datatyperna lista, stack och kö är och vilka operationer man förväntas kunna utföra på dem.

Implementera en lista, stack eller kö effektivt med hjälp av vektor respektive länkade struktur.

Förklara vad nästlade och inre klasser är för något samt kunna implementera sådana.

Använda klasser och interface från Java Collections Framework: List, Queue, Deque, ArrayList, LinkedList, ArrayDeque, Iterator,

ListIterator och Iterable

Skugga metoden equals och implementera interfacet Comparable Man ska naturligtvis inte lära sig utantill exakt vilka metoder som finns i klasser i Javas bibliotek. Det är däremot viktigt att förstå t.ex. begreppet

(76)

Datorlaboration 2

Enkellänkad lista

Implementera en egen generisk klass som beskriver en FIFO-kö.

Inuti mängdklassen ska du använda en cirkulär, enkellänkad lista för att hålla reda på elementen i kön.

Utifrån sett ser kön ut så här:

2

1 3

Inuti klassen är den uppbyggd så här:

last next

element

1

size 3 next

element

2

next element

3

Tips! Rita för att förstå vad som händer i programmet!

Innehåll: kö, enkellänkad lista, iterator, testning med JUnit.

References

Related documents

Personer med autism har många gånger ord men inte förmågan att använda dem, svårigheter när det går för fort.. Konkreta i sitt tänkande- använd ord som

- Jag tror att de vinnande anbudsgivarna kommer lyckas bra med att utforma området i och kring Gläntan till ett attraktivt och levande bostadsområde på ett sätt som värnar om

De pekar på Östergötland och menar att de lyckades korta köerna när man införde vårdval 2013, men att hörselvården blivit betydligt sämre!. Bland annat pekar man på att

• En specifikation beskriver hur en klass används (hur man skapar objekt, vilka metoder som finns och hur de används). Detta beskrivs typiskt i dokumentation

För att kunna använda ett objekt från en existerande klass måste man först skapa objektet (dvs skapa en instans av klassen som beskriver objektet).. Detta görs genom att man

• klassvariabler (statiska variabler statiska variabler), dvs de variabler som det endast finns en gemensam kopia av för alla objekt i klassen (kan vara publika eller privata).

Flytta om elementen så att element ≤ pivot hamnar till vänster och element ≥ pivot hamnar till höger. Kallas partitionering

En instans av en klass som implementerar interfacet Iterator används för att iterera över alla element i en samling. public interface