Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista • • • Abstrakt stack Abstrakt kö Länkade listor Abstrakta datatyper Det är ofta praktiskt att beskriva vilka operationer man vill kunna göra på sina data utan att behöva tänka på hur operationerna ska implementeras (dvs hur programkoden ska se ut). En datastruktur som beskrivs på detta sätt kallas för en abstrakt datatyp. En abstrakt datatyp • • Anger inte lagringssättet Specificerar operationer för åtkomst och ändring Stack En stack fungerar som en trave tallrikar - det man lägger överst på stacken är det som kommer att tas bort först. För en abstrakt stack finns följande operationer: push(x) x=pop() IsEmpty() Lägg x överst på stacken. Hämta det som ligger överst på stacken. Undersök om stacken är tom. Den som använder datatypen behöver inte (och får inte heller) bry sig om hur den representeras. I Java definierar man lämpligen först ett gränssnitt (interface) för den abstrakta datatypen. Implementationen blir sedan en klass som implementerar gränssnittet och där alla instansvariabler är privata. Så här skulle ett gränssnitt för en stack kunna se ut: interface Stack { void push(Object x); Object pop(); boolean isEmpty(); } Skriv programmet LadiesFirst.java som läser en fil av typen med personnummer och namn och först skriver ut alla kvinnor och sedan alla män i filen. 120203-1114 Albus Dumbledore 330401-6402 Minerva McGonagall 920731-3131 Harry Potter 2D1320 Alexander Baltatzis Männen måste tillfälligt läggas i ett förvaringsutrymme medan filen läses igenom. Man skulle kunna använda en vektor String[] om man visste att det fanns högst hundra män, men vi ska i stället använda en abstrakt stack. Man lägger en textrad på stacken med anropet stack.push("En textrad") och man hämtar en textrad från stacken med raden=stack.pop(). Med koden if (stack.isEmpty()) ... ska man kunna kolla om stacken är tom. import java.io.*; class LadiesFirst { public static void main(String[] args) { String filnamn = args[0]; String personrad; BufferedInputStream infil = Mio.openRead(filnamn); Stack stack = new TildaStack(); while (!Mio.eof(infil)) { personrad = Mio.getLine(infil); int nästSistaSiffran = personrad.charAt(9) – ’0’; if (nästSistaSiffran % 2 == 0) System.out.println("Kvinna: " + personrad); else stack.push(personrad); } while (!stack.isEmpty()) { personrad = (String) stack.pop(); System.out.println("Man: " + personrad); } }//main() }//Ladiesfirst Här har vi programmerat abstrakt, som om push och pop vore fungerande metoder. Stackimplementationen kommer lite senare! Kö En kö fungerar som man förväntar sig, dvs det man stoppar in först är det som tas ut först. För en abstrakt kö finns följande operationer: enqueue(x) X=dequeue() IsEmpty() Stoppa in x sist i kön. Hämta det som står först i kön. Undersök om kön är tom. En kö kan t ex användas för att hantera skrivarköer. Den som skrev ut först ska också få ut sin utskrift först. I labb 2 ska ni använda en kö för att förbereda en kortkonst! Länkade listor En länkad lista består av ett antal objekt, noder som är sammanlänkade genom att varje nod refererar till nästa nod. Dessa referenser kallas ofta next-pekare. Klassen Node skulle kunna användas för att skapa en länkad lista med heltal. 2D1320 Alexander Baltatzis class Node{ int info; Node next; }//Node Stack Här kommer nu klassen TildaStack, en stack implementerad med en länkad lista. Stacken kan också implementeras på andra sätt, t ex med en array (Javas Stack är implementerad med en Vector). class TildaStack implements Stack { private Node top; // Konstruktor public TildaStack(){ top = null; }//TildaStack() public void push(int n){ Node nynod = new Node(); nynod.info = n; nynod.next = top; top = nynod; }//push() public int pop(){ int n = top.info; top = top.next; return n; }//pop() public boolean isEmpty(){ if (top == null) return true; else return false; }//isEmpty() }//TildaStack Datadelen info skulle kunna vara String men en generellare stack får man genom att använda Object. Ersätt int med Object överallt. Det kan vara praktiskt med en konstruktor i Node också och då blir det så här. class Node{ Object info; Node next; // Konstruktor public Node(Object info){ this.info = info; this.next = null; } } 2D1320 Alexander Baltatzis class TildaStack implements Stack {//stack som lagrar objekt private Node top; // Konstruktor public TildaStack(){ top = null; } public void push(Object info){ Node nynod = new Node(info); nynod.next = top; top = nynod; } public Object pop(){ Object info = top.info; top = top.next; return info; } public boolean isEmpty(){ if (top == null) return true; else return false; } }//TildaStack Kö En kö kan implementeras som länkad lista med samma noder men med en pekare även på sista noden. Där ska nämligen nya noder stoppas in. class Queue {//kö som lagrar objekt private Node head, tail; // Konstruktor public Queue(){ head = null; tail = null; } public void enqueue(Object info){ Node nynod = new Node(info); if (isEmpty()) head = nynod; else tail.next = nynod; tail = nynod; } public Object dequeue() {/* samma som pop för en stack*/} public boolean isEmpty() {/* samma som för en stack */} } 2D1320 Alexander Baltatzis class LadiesFirst { public static void main(String[] args) { String filnamn = args[0]; String personrad; BufferedInputStream infil = Mio.openRead(filnamn); Stack stack = new TildaStack(); while (!Mio.EOF(infil)) { personrad = Mio.getLine(infil); int nästSistaSiffran = personrad.charAt(9) – ’0’; if (nästSistaSiffran % 2 == 0) System.out.println("Kvinna: " + personrad); else stack.push(personrad); } while (!stack.isEmpty()) { personrad = (String) stack.pop(); System.out.println("Man: " + personrad); } } } interface Stack { void push(Object x); Object pop(); boolean isEmpty(); } class TildaStack implements Stack { private Node top; // Konstruktor public TildaStack(){ top = null; }//TildaStack() public void push(int n){ Node nynod = new Node(); nynod.info = n; nynod.next = top; top = nynod; }//push() public int pop(){ int n = top.info; top = top.next; return n; }//pop() public boolean isEmpty(){ if (top == null) return true; else return false; }//isEmpty() } 2D1320 Alexander Baltatzis