Föreläsning 11 ADT:er och datastrukturer ADT:er och datastrukturer • Dessa två begrepp är kopplade till varandra men de står för olika saker. • En ADT (abstrakt datatyp) är just abstrakt och är inte kopplad till något programmeringsspråk eller till implementering. • En datastruktur är konkret och till de flesta programmeringsspråk finns en eller flera inbyggda datastrukturer. 2 ADT (abstrakt datatyp) • En ADT är en programspråksoberoende beskrivning av en mängd data och operationer på denna data för att lagra, komma åt och manipulera den. • I objektorienterade programmeringsspråk (som Java) implementeras ADT:er med klasser. • Med hjälp av gränssnitt kan man säkerställa att man får med alla de metoder som anges i ADT:n. • Exempel på vanliga abstrakta datatyper är: - mängd - sekvens (lista, kö, stack) 3 ADT:n Mängd • Exempel på egenskaper: - En oordnad samling av unika element. - Kan innehålla ett obegränsat antal element. • Exempel på operationer: Beskrivning: Skapar en tom mängd. Pre: sant Post: en ny tom mängd har skapats Mängd() Beskrivning: Kollar om ett element finns i mängden. Pre: sant Post: resultat = sant om elementet i mängden, annars falskt contains(in: element, ut: boolskt värde) Beskrivning: Lägger till ett element i mängden. Pre: !contains(element) Post: element är lagt till mängden add(in: element) Beskrivning: Tar bort ett element ur mängden. Pre: contains(element) Post: element är borttaget ur mängden remove(in: element) Beskrivning: Kollar om mängden är tom. Pre: sant Post: resultat = sant om mängden är tom, annars falskt isEmpty(ut: boolskt värde) Beskrivning: Bestämmer mängdens storlek. Pre: sant Post: resultat = mängdens storlek size(ut: heltal) 4 Gränssnitt • De operationer som finns till en ADT kan samlas i ett gränssnitt som en implementering av ADT:n kan implementera. • Exempel på Javagränssnitt för ADT:n Mängd: public interface SetADT<E> { public boolean contains(E element); public void add(E element); public void remove(E element); public boolean isEmpty(); public int size(); } 5 ADT:n Lista • Exempel på egenskaper: - En ordnad sekvens av element. - Kan innehålla ett obegränsat antal element. • Exempel på operationer: Beskrivning: Skapar en tom lista. Pre: sant Post: en ny tom lista har skapats Lista() Beskrivning: Tar bort ett element på en viss plats ur listan. Pre: 0 <= index < size() Post: element på plats index är borttaget ur listan Beskrivning: Kollar om ett element finns remove(in: index (heltal)) i listan. Pre: sant Beskrivning: Kollar om listan är tom. Post: resultat = sant om elementet i Pre: sant listan, annars falskt Post: resultat = sant om listan är tom, contains(in: element, ut: boolskt värde) annars falskt isEmpty(ut: boolskt värde) Beskrivning: Lägger till ett element på viss plats i listan. Beskrivning: Bestämmer listans storlek. Pre: 0 <= index <= size() Pre: sant Post: element är lagt till listan på plats Post: resultat = listans storlek index size(ut: heltal) 6 add(in: element, index (heltal)) ADT:n Kö • Exempel på egenskaper: - En ordnad sekvens av element. - Kan innehålla ett obegränsat antal element. - FIFO (first in first out). • Exempel på operationer: Beskrivning: Skapar en tom kö. Pre: sant Post: en ny tom kö har skapats Kö() Beskrivning: Lägger till ett element i kön. Pre: sant Post: element är lagt sist i kön enqueue(in: element) Beskrivning: Tar bort elementet först i kön. Pre: !isEmpty() Post: elementet först i kön är borttaget och returnerat dequeue(ut: element) Beskrivning: Kollar om kön är tom. Pre: sant Post: resultat = sant om kön är tom, annars falskt isEmpty(ut: boolskt värde) 7 ADT:n Stack • Exempel på egenskaper: - En ordnad sekvens av element. - Kan innehålla ett obegränsat antal element. - LIFO (last in first out). • Exempel på operationer: Beskrivning: Skapar en tom stack. Pre: sant Post: en ny tom stack har skapats Stack() Beskrivning: Lägger till ett element på stacken. Pre: sant Post: element är lagt överst på stacken push(in: element) Beskrivning: Tar bort elementet överst på stacken. Pre: !isEmpty() Post: elementet överst på stacken är borttaget och returnerat pop(ut: element) Beskrivning: Kollar om stacken är tom. Pre: sant Post: resultat = sant om stacken är tom, annars falskt isEmpty(ut: boolskt värde) 8 Gränssnitt • Exempel på Javagränssnitt för ADT:erna Kö och Stack: public interface QueueADT<E> { public void enqueue(E element); public E dequeue(); public boolean isEmpty(); } public interface StackADT<E> { public void push(E element); public E pop(); public boolean isEmpty(); } 9 Implementationer av ADT:er • En ADT kan implementeras på många sätt. Hur man implementerar en ADT spelar inte någon större roll så länge man får med de egenskaper och operationer som angetts i ADT:n. • Exempelvis kan ADT:n Stack implementeras med hjälp av en lista, array eller noder. 10 Listimplementation av ADT:n Stack • En Javalistklass (DefaultListModel) används för att spara elementen i stacken. • DefaultListModel kan användas tillsammans med JList för att visa elementen i ett GUI. • Toppen på stacken har valts till index=0. • Tips: Denna implementation kan till vissa delar användas till lab 4. 11 Arrayimplementation av ADT:n Stack • Storleken på arrayen har valts till 20. Stacken har alltså en övre gräns. • Förvillkoret till operationen push blir då att stacken inte är full. Detta måste kontrolleras i PushButtonklassen. • Klassen ärver AbstractListModel och implementerar gränssnittet ListModel för att den ska kunna användas tillsammans med JList. • Botten till stacken har valts till index 0 för att slippa omflyttningar av element. 0 12 Nodimplementation av ADT:n Stack • Elementen i stacken lagras som länkade noder. • Insättning och borttagning görs i början av kedjan av effektivitetsskäl. Den blir då toppen av stacken. • Vi får skapa en Node-klass för noderna där man kan spara ett stackelement och en “pil” till nästa nod (länk). • Klassen ärver AbstractListModel och implementerar gränssnittet ListModel av samma skäl som i arrayimplementationen. 13 Stackapplikationer • Reverse: Vända på strängar. • Exempel: Vänd på “Kalle” med hjälp av en stack. “Kalle” “alle” “lle” e l l a K l a K a K K “” “le” “e” “el” “ell” l l a K l a K a K “ella” K “e” “” l l a K e l l a K “ellaK” 14 Stackapplikationer • IsPalindrom: Kollar om en sträng är likadan oavsett om man läser den fram- eller baklänges. • Exempel: “anna”, “nitalarbralatin”, “olaSalo” “olaSalo” “alo” =? a l o “laSalo” “aSalo” o l o “lo” “o” =? “Salo” a l o =? l o o 15 Stackapplikationer • IsBalanced: Kollar om ett programs parenteser är balanserade. Parenteserna är (, ), [, ], {, }. • Exempel: “([]{})”, “public class Test { public Test(){}}” • Lösningsförslag: - gå igenom strängen (programmet) från vänster till höger, - om tecknet är en vänsterparentes, lägg parentesen på stacken, - om tecknet är en högerparentes poppa stacken och jämför parenteserna, - andra tecken ignoreras, - om alla parentesjämförelser “gått igenom” och stacken är tom i slutet är programmet balanserat 16