760 likes | 889 Views
Fundamentale datastrukturer. Plan. Definitioner : abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer, hægtede lister, træer, hashtabeller, prioritetskøer • Collections.
E N D
Plan • Definitioner:abstrakt datatype, datastruktur • Elementære datastrukturer og abstrakte datatyper:arrays, stakke, køer, hægtede lister, træer, hashtabeller, prioritetskøer • • Collections
En datatype er en type tilknyttet en mængde af operationer på typen. Eks. inter en datatype. Addition er et eksempel på en tilknyttet operation. En abstrakt datatype er en datatype, der udelukkende er specificeret ved hjælp af typen og de tilknyttede operationer. Definitioner • En type er en samling af værdier. • Eks. intbetegner i Java den type, der udgøres af heltallene fra -2147483648 til 2147483647. Kun operationernes input/output-relationer er specificeret - ikke deres konkrete realisering. Hverken datarepræsentation eller algoritmer må medtages i specifikationen. En abstrakt datatype (ADT) specificerer “hvad”, men ikke “hvordan”.
Abstrakte datatyper En ADT skjuler den konkrete implementation fra anvenderen (klienten). Fordele: (1) Det er lettere at bruge noget, hvis det ikke kræver internt kendskab til virkemåden. Tænk f.eks. på en radio eller en vaskemaskine (2) Den konkrete implementation kan ændres, uden at klienten behøver at få det at vide. Realisering i Java: En ADT kan realiseres som en klasse, hvor data er private. Specificeres ofte ved hjælp af en grænseflade.
Datastrukturer • En datastruktur er en samling variable, muligvis af forskellig type, der er indbyrdes forbundet. • Realisering i Java: ved simple variable, arrays og objekter
celle array Arrays(to perspektiver) • (1) Datastruktur: • Et array er en sammenhængende blok af lagerceller, hvor hver lagercelle indeholder et dataelement af en fast længde.
(2) Abstrakt datatype: Et array er en samling af dataelementer af samme type, hvor hvert dataelement kan identificeres med et heltal, kaldet indeks. Med dette perspektiv kan et array implementeres på mange måder.
Datastrukturen array • Realisering i Java: • Oprettelse: • int[] a = new int[100]; • eller • int a[] = new int[100]; • opretter et array med 100 elementer af typen int: • a[0], a[1], ..., a[99] Tilgang til et element: a[27] Aflæsning af arrayets længde: a.length (= 100)
6: a[6] 5: a[5] 4: a[4] 3: a[3] 2: a[2] 1: a[1] adresse(a[0]) 0: a[0] adresse(a[i]) = adresse(a[0]) + i*længde(type) Vigtig egenskab • Tilgangstiden til ethvert element er konstant.
2-dimensionale arrays • Realisering i Java: • Oprettelse: • int[][] a = new int[5][4]; • opretter et array med 5*4 = 20 heltallige elementer: • a[0][0] a[0][1] a[0][2] a[0][3] • a[1][0] a[1][1] a[1][2] a[1][3] • a[2][0] a[2][1] a[2][2] a[2][3] • a[3][0] a[3][1] a[3][2] a[3][3] • a[4][0] a[4][1] a[4][2] a[4][3] Tilgang til et element: a[3][2] Aflæsning af antal rækker: a.length (= 5) Aflæsning af antal søjler: f.eks. a[0].length (= 4)
first S A L I T Hægtede lister • En hægtet liste er en mængde at dataelementer, der er organiseret sekventielt, således at hvert element (kaldet en knude) indeholder en peger (kaldet en hægte) til det næste element. Bemærk: enhver knude indeholder en hægte, også listens sidste.
X first A S I L T X first A I L S T Operationer på hægtede lister • (1) Indsættelse Tidsforbrug: Konstant. Kun 2 hægter skal ændres (uafhængigt af listens længde) (2) Sletning Tidsforbrug: Konstant. Kun 1 hægte skal ændres (uafhængigt af listens længde)
class ListNode { ListNode next; Object element; } ListNode ListNode Object Object Implementering af hægtede lister i Java
this t t.next Implementering af indsættelse og sletning • class ListNode { ListNode next; Object element; void insertAfter(ListNode t) { • next = t.next; • t.next = this; } • void deleteAfter(ListNode t) { • t.next = next; } }
ListNode current = firstNode; • while (current != null) { • process(current.element); • current = current.next; • } eller • for (ListNode current = firstNode; • current != null; • current = current.next) • process(current.element); Gennemløb af hægtet liste(idiom)
class ListNode { ListNode prev, next; Object element; } ListNode ListNode Object Object Dobbelthægtede lister • Problemer med enkelthægtede lister: • En knude kan ikke fjernes effektivt fra en liste, med mindre forgængerknuden er kendt. • Listen kan kun gennemløbes i én retning. • Løses med en dobbelthægtet liste.
Arrays og hægtede lister(pro et contra) • • Visse operationer er mere effektive for en liste end for et array, f.eks. indsættelse og sletning (flytning undgås). Men visse operationer er mere effektive for et array, f.eks. bestemmelse af det i´te element. • • En array-repræsentation fylder mindre (der spares plads til hægterne).
push pop Kun stakkens øverste element (top) er tilgængeligt Stak En stak(LIFO = LastInFirstOut) • En stak er en sekvens af dataelementer af samme type, som muliggør følgende to operationer: • push(x):Læg dataelementet x øverst på stakken • pop:Fjern det øverste element på stakken
public interface Stack { void push(Object x); void pop(); Object top(); Object topAndPop(); boolean isEmpty(); } En stak er en abstrakt datatype
Et simpelt testprogram • public class TestStack { • public static void main(String[] args) { • Stack s = new ArrayStack(); • for(int i = 0; i < 5; i++) • s.push(new Integer(i)); • while (!s.isEmpty()) • System.out.print(s.topAndPop() + " "); • } • }
Anvendelser af en stak En stak kan bl.a. bruges til • at vende om på en given rækkefølge (at gøre noget baglæns) • at gemme mellemresultater f.eks. ved beregning af udtrykket 3*4 + 5*6 +7 • at behandle parentetiske strukturer f.eks. ved kontrol af, om parenteserne stemmer i sekvensen { [ ( { } ( ) ] ) }
En kø(FIFO = FirstInFirstOut) En kø er en sekvens af dataelementer af samme type, som muliggør følgende to operationer: enqueue(x): Sæt dataelementet x bagest i køen dequeue: Fjern det forreste element fra køen dequeue enqueue Kø
public interface Queue { • void enqueue(Object x); • Object dequeue(); • Object getFront(); • boolean isEmpty(); • } En kø er en abstrakt datatype
public class TestQueue { • public static void main(String[] args) { • Queue q = new ArrayQueue(); • for(int i = 0; i < 5; i++) • q.enqueue(new Integer(i)); • while (!q.isEmpty()) • System.out.print(q.dequeue() + " "); • } • } Et simpelt testprogram
Træer • Et træ er en samling af knuder og kanter, (V, E), som opfylder visse krav: • En knude, v, er et simpelt dataobjekt, der kan have et navn og en tilknyttet information. En af knuderne er udpeget som rod i træet. • En kant, (v1,v2), er en forbindelse imellem to knuder, v1 og v2. • En vej er en liste af knuder, (v1,v2, ... ,vk), hvor alle successive knuder, vi og vi+1, er indbyrdes forbundne (dvs. tilhører E). • For at udgøre et træ skal der mellem roden og enhver anden knude findes præcis én vej.
Rod R S Indre knude T X U W V Y Z Blad Terminologi Rod: R Blade: Y, Z, U, V, W Indre knuder : R, S, T, X X er far til Y Y er søn til X (Y er barn af X) U, V og W er børn af T S er bedstefar til Z S er forgænger til Y (S er over Y) Y er efterkommer af S (Y er under S)
Eksempel på anvendelse af træer (et filsystem) • Et filsystem kan beskrives ved et træ: • Knuderne repræsenterer kataloger og filer. • Træets blade indeholder filer (eller tomme kataloger). Andre eksempler: stamtræ, indholdsfortegnelse, organisationsstruktur
Terminologi(fortsat) Et tomt træ er et træ uden kanter og knuder. Enhver knude i et træ er rod for et undertræ bestående af knuden selv og alle knuder under den. Et træ kaldes ordnet, hvis rækkefølgen af sønnerne for enhver knude er specificeret.
Et binært træ er et ordnet træ, hvor hver knude har højst 2 sønner. Rekursiv definition: Et binært træ er enten et tomt træ, eller en knude, som har et venstre og et højre binært undertræ. Binære træer
P L N E S R X A T B V Eksempel på binært træ N er P’s venstre søn L er P’s højre søn
Repræsentation af binære træer • class BinaryNode { • BinaryNode left, right; • Object element; • } En null-reference angiver et tomt (under)træ
* + A F * + * B C E D Eksempel på anvendelse af binære træer (et udtrykstræ) operator (i indre knude) operand (i blad) Træ for udtrykket A * ( ( ( B + C ) * ( D * E ) ) + F)
I P E S M A G X N L R B F H Binære søgetræer(muliggør søgning i logaritmisk tid) • Et binært søgetræ, er et binært træ, hvor der for hver knude gælder, at alle knuder i dets venstre undertræ er mindre end knuden, og alle knuder i dets højre undertræ er større end knuden.
Binære søgetræer public interface BinarySearchTree { void insert(Comparable x); Comparable find(Comparable x); Comparable findMin(); Comparable findMax(); void remove(Comparable x); void removeMin(); void removeMax(); boolean isEmpty(); }
public interface HashTable { void put(Object key, Object value); Object get(Object key); boolean containsKey(Object key); boolean isEmpty(); } Hashtabeller(muliggør søgning i konstant tid)
Et simpelt testprogram • public class TestHashTable { • public static void main(String[] args) { • HashTable h = new QuadraticProbingTable(); • h.put("Hansen", "351348"); • h.put("Jensen", "421927"); • Object result = h.get("Hansen"); • if (result != null) • System.out.println("Found " + result); • else • System.out.println("Hansen not found"); • } • }
Prioritetskøer(muliggør behandling af elementer i prioriteret rækkefølge) public interface PriorityQueue { Position insert(Comparable x); Comparable findMin(); Comparable deleteMin(); boolean isEmpty(); void decreaseKey(Position p, Comparable newVal);public interface Position { Comparable getValue(); } }
Et simpelt testprogram • public class TestPriorityQueue { • public static void main(String[] args) { • PriorityQueue pq = new BinaryHeap(); • pq.insert(new Integer(4)); • pq.insert(new Integer(2)); • pq.insert(new Integer(1)); • pq.insert(new Integer(3)); • pq.insert(new Integer(0)); • while (!pq.isEmpty()) • System.out.print(pq.deleteMin() + " "); • } • }
Kollektioner En kollektion er en samling af objekter. Javas collections er et sæt af grænseflader og klasser, der understøtter lagring og genfinding af objekter i kollektioner. Kollektionerne kan være baseret på forskellige datastrukturer og algoritmer (og dermed have forskellige tids- og pladskompleksitet). En kollektion er et objekt, der fungerer som en beholder for andre objekter. Disse kaldes for kollektionens elementer.
Abstrakte kollektioner En mængde (Set) er en uordnet kollektion, som ikke må indeholde dubletter. En liste (List) er en ordnet kollektion, som gerne må indeholde dubletter. Ethvert element har en position. En afbildning (Map) er en uordnet kollektion af nøgle-værdi-par. Nøglerne skal være unikke.
Collection Map SortedMap Set List SortedSet Grænseflader for kollektioner java.util.*
Vector implements List JDK 1.0 Hashtable implements Map Konkrete kollektioner HashSet implements Set : O(1)TreeSet implements SortedSet : O(log N) ArrayList implements List LinkedList implements List HashMap implements Map TreeMap implements SortedMap
interface Collection boolean add(Object o) boolean addAll(Collection c) void clear() boolean contains(Object o) boolean containsAll(Collection c) boolean isEmpty() Iterator iterator() boolean remove(Object o) boolean removeAll(Collection c) boolean retainAll(Collection c) int size() For primitive typer benyttes svøbeklasser
interface Set extends Collection Ingen nye metoder, men kontrakterne for boolean add(Object o) boolean addAll(Collection c) er ændret, således at et objekt kun tilføjes, hvis der ikke findes en dublet (dette afgøres med equals).
Eksempel på anvendelse af Set Set set = new HashSet(); set.add("cat"); set.add("dog"); int n = set.size(); System.out.println("The set contains " + n + " elements"); if (set.contains("dog")) System.out.println("dog is in the set");
interface List extends Collection Nye metoder: void add(int i, Object o) Object get(int i) int indexOf(Object o) int lastIndexOf(Object o) ListIterator listIterator() ListIterator listIterator(int i) Object remove(int i) Object set(int i, Object o) List subList(int i, int j) Ændrede kontrakter for add(o), addAll(c) og remove(o).
interface Map Object put(Object k, Object v) Object get(Object k) Object remove(Object k) void clear() boolean containsKey(Object k) boolean containsValue(Object v) Set entrySet() boolean isEmpty() Set keySet() void putAll(Map m) int size() Collection values()
Eksempel på anvendelse af Map (indholdsadresserbar tabel) Map map = new HashMap(); map.put("cat", "kat"); map.put("dog", "hund"); Object val = map.get("dog"); // val is "hund" map.remove("cat"); map.put("dog", "køter"); val = map.get("dog"); // val is "køter"