Introduktion til datastrukturer Philip Bille
Plan Datastrukturer Stakke og køer Hægtede lister Dynamiske tabeller
Datastrukturer
Datastrukturer Datastruktur: Metode til at organise data så det kan søges i/tilgås/ manipuleres effektivt. Mål: kompakt og hurtig. Dynamisk vs. statisk datastruktur. Abstrakt vs. konkret datastruktur.
Stakke og køer
Stak Vedligehold en dynamisk sekvens X af elementer under følgende operationer. Push(x): tilføj et nyt element x til X Pop(): fjern og returner det seneste tilføjede element i X. isempty(): returner sand hvis X ikke indeholder nogle elementer.
Implementation med tabel Implementer en stak med maksimalt N elementer. Datastruktur: Tabel X[1..N] Position top i X. Operationer: Push(x): Tilføj x på X[top+1], sæt top = top + 1 Pop(): returner X[top], sæt top = top - 1 isempty(): returner sand hvis og kun hvis top = 1. Tjek for overløb og underløb i Push og Pop.
Analyse Hvor hurtigt kører Push, Pop, isempty? Push, Pop, isempty bruger Θ(1) tid. Hvor meget plads bruger vi? Θ(N) Den dårlige nyhed: Vi skal kende den maksimale størrelse af stakken fra start. Vi spilder plads når antal elementer i stakken er < N.
Kø Vedligehold en dynamisk sekvens X af elementer under følgende operationer. Enqueue(x): tilføj et nyt element x til X Dequeue(): fjern og returner det tidligst tilføjede element i X. isempty(): returner sand hvis X ikke indeholder nogle elementer.
Implementation med tabel Implementer en kø med maksimalt N elementer. Datastruktur: Tabel X[1..N] Positioner head (tidligst indsatte element) og tail (næste ledige element) i X og tæller count (antal elementer i kø). Operationer: Enqueue(x): Tilføj x på X[tail], opdater count og tail cyclisk. Dequeue(): returner X[head], opdater count og head cyclisk. isempty(): returner sand hvis og kun hvis count = 0. Tjek for overløb og underløb i Dequeue og Enqueue.
count=4 count=3 count=2 14 2 3 7 dequeue() 14 2 3 7 dequeue() 14 2 3 7 head tail head tail head tail count=3 count=4 count=3 enqueue(4) 14 2 3 7 4 enqueue(9) 9 2 3 7 4 dequeue() 9 2 3 7 4 tail head tail head tail head
Analyse Hvor hurtigt kører Dequeue, Enqueue, isempty? Dequeue, Enqueue, isempty bruger Θ(1) tid. Hvor meget plads bruger vi? Θ(N) Den dårlige nyhed: Vi skal kende den maksimale størrelse af køen fra start. Vi spilder plads når antal elementer i køen er < N.
Stakke og køer Stak implementeret med tabel Køretid: Push, Pop, isempty i Θ(1) tid. Pladsforbrug: Θ(N) Kø implementeret med tabel Køretid: Enqueue, Dequeue, isempty i Θ(1) tid. Pladsforbrug: Θ(N) Kan vi komme ned på lineær plads med samme tid?
Hægtede lister
Hægtede lister Datastruktur til at vedligeholde en sekvens af elementer i lineær plads. Rækkefølge af elementer bestemt af referencer/pegere kaldet hægter. Effektiv at indsætte og fjerne elementer eller delsekvenser af elementer. Dobbelt-hægtede eller enkelt-hægtede.
head 7 42 18 23 5 null head null 7 42 18 23 5 null
Dobbelt-hægtede lister i Java Hvordan implementerer man dobbelt-hægtede lister i Java?
class Node { int key; Node next; Node prev; } Node head = new Node(); Node b = new Node(); Node c = new Node();! head.key = 7; b.key = 42; c.key = 18; head null 7 null b null 42 null c null 18 null head.prev = null; head.next = b; b.prev = head; b.next = c; c.prev = b; c.next = null; head null 7 b 42 c 18 null
Node Search(Node head, int value) { Node x = head; while (x!= null) { if (x.key == value) return x; x = x.next; } return null; } Node Insert(Node head, Node x) { x.prev = null; x.next = head; head.prev = x; return x; } Node Delete(Node head, Node x) { if (x.prev!= null) x.prev.next = x.next; else head = x.next; if (x.next!= null) x.next.prev = x.prev; return head; }
Analyse Hvor hurtigt kører Search, Insert og Delete på liste af længde n? Θ(n) for Search Θ(1) for Insert og Delete Hvor meget plads bruger en hægtet liste af størrelse n? Θ(n)
Stak og kø implementation med hægtede lister Hvordan kan man implementere stakke og køer med hægtede lister? Stak Push Pop isempty Kø Enqueue Dequeue isempty
Stakke og køer Stak implementeret med hægtet liste Køretid: Push, Pop, isempty i Θ(1) tid. Pladsforbrug: Θ(n) Kø implementeret med hægtet liste Køretid: Enqueue, Dequeue, isempty i Θ(1) tid. Pladsforbrug: Θ(n)
Hægtede lister Fleksibel datastruktur til at vedligeholde en sekvens af elementer i lineær plads. Eksempel på hægtet datastruktur. Findes også cykliske lister, træer, grafer,
root null 23 18 42 null 7 20 57 null null null null null null 5 null
Dynamiske tabeller
Stak med dynamisk tabel Kan vi implementere en stak effektivt med tabel(ler)? Behøver vi fastsætte en øvre grænse på antallet af elementer? Kan vi komme ned på lineær plads og konstant tid?
Første forsøg Mål: Vi vil kun bruge Θ(n) plads for stak med n elementer Ignorer Pop og isempty indtil videre. Datastruktur: Tabel X[1..n] Operationer: Push(x): Opret ny tabel af størrelse n+1. Flyt alle elementer til ny tabel. Slet gammel tabel.
Analyse Hvor hurtigt kører det? n Push-operationer tager 1 + 2 + 3 + + n = Θ(n 2 ) tid. Plads: Θ(n) plads.
Andet forsøg Ide: Undgå at bygge en tabel og flytte elementer for ofte. Fordobling: Start med tabel af størrelse 1. Hvis tabel er fuld (antallet af elementer i stak er lig tabellens størrelse). Opret ny tabel af dobbelt størrelse. Flyt elementer over i ny tabel. Slet gammel tabel.
Analyse Hvor hurtigt kører det? n Push-operationer tager 1 + 2 + 4 + 8 + + n/2 + n < 2n = Θ(n) tid. Plads: Θ(n) plads.
Stak Stak implementeret med dynamisk tabel Køretid: n Push operationer tager Θ(n) tid. Pladsforbrug: Θ(n) Muligt at opnå n Push, pop og isempty operationer i Θ(n) tid. Tilsvarende resultat for køer Køretiden er amortiseret Θ(1) per operation. Med snedige tricks: Muligt at deamortisere løsning og opnå Θ(1) værstefaldskøretid per operation.
Opsummering Datastrukturer Stakke og køer Hægtede lister Dynamiske tabeller