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!)