Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg



Relevanta dokument
Lösningsförslag till tentamen i EDA690 Algoritmer och Datastrukturer, Helsingborg

Lösningsförslag till tentamen i EDAA01 programmeringsteknik fördjupningkurs

Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

13 Prioritetsköer, heapar

Tentamen, EDAA20/EDA501 Programmering

Hitta k största bland n element. Föreläsning 13 Innehåll. Histogramproblemet

Föreläsning 9 Innehåll

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista

Programmering för Språkteknologer II. Innehåll. Associativa datastrukturer. Associativa datastrukturer. Binär sökning.

Föreläsning Datastrukturer (DAT036)

Föreläsning 14 Innehåll

Föreläsning 7. Träd och binära sökträd

Föreläsning 10 Innehåll. Prioritetsköer och heapar. ADT Prioritetskö. Interface för Prioritetskö. Exempel på vad du ska kunna

Mera om generik. Innehåll. Generik och arv Wildcards Vektorer och generik Generiska metoder. EDA690 (Mera om generik) HT / 24

ADT Prioritetskö. Föreläsning 13 Innehåll. Prioritetskö vs FIFO-kö. Prioritetskö Exempel på användning. Prioritetsköer och heapar

Dugga Datastrukturer (DAT036)

Föreläsning 4 Innehåll. Abstrakta datatypen lista. Implementering av listor. Abstrakt datatypen lista. Abstrakt datatyp

Föreläsning 9 Datastrukturer (DAT037)

Tentamen Datastrukturer D DAT 036/DIT960

Föreläsning 4 Innehåll

ADT Prioritetskö. Föreläsning 12 Innehåll. Prioritetskö. Interface för Prioritetskö. Prioritetsköer och heapar

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista Läsanvisningar och uppgifter

Seminarium 13 Innehåll

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

ADT Kö. Seminarium 4 Köer och Stackar Innehåll. Operationer. ADT Stack. Definition. Definition

Föreläsning 13 Innehåll

Tentamen i Objektorienterad programmering

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Tentamen i Programmering grundkurs och Programmering C

Tentamen, EDA501 Programmering M L TM W K V

Abstrakt datatyp. -Algoritmer och Datastrukturer- För utveckling av verksamhet, produkter och livskvalitet.

Föreläsning 6: Introduktion av listor

Idag: Dataabstraktion

ANVÄND NAVIGATIONEN I CAPITEX SÄLJSTÖD

Föreläsning 13 och 14: Binära träd

Du ska nu skapa ett litet program som skriver ut Hello World.

Tentamen, Algoritmer och datastrukturer

Datastrukturer. föreläsning 3. Stacks 1

Programmering för språkteknologer II, HT2014. Rum

Interfacen Set och Map, hashtabeller

Föreläsning 4 Datastrukturer (DAT037)

Lathund, procent med bråk, åk 8

4-3 Vinklar Namn: Inledning. Vad är en vinkel?

Tentamen Datastrukturer, DAT037 (DAT036)

konstanterna a och b så att ekvationssystemet x 2y = 1 2x + ay = b 2 a b

Seminarium 2 Introduktion till Java Collections Framework Innehåll. Generik Bakgrund. Exempel på en generisk klass java.util.arraylist.

Lösningsförslag till tentamen i EDA011/EDA017 Programmeringsteknik för F, E, I, π och N 27 maj 2008

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

Seminarium 3 Introduktion till Java Collections Framework Innehåll. Generik Bakgrund. Exempel på en generisk klass java.util.arraylist.

Klasser och objekt i C#

Lite skoj - typ. 5DV085 - Programspråk. Jan Erik Moström, Department of Computing Science, Umeå University - jem@cs.umu.se

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

Föreläsning 2. Länkad lista och iterator

Lösningsförslag till tentamen Datastrukturer, DAT037,

Gissa det hemliga talet

Objektsamlingar i Java

Träning i bevisföring

Sätt att skriva ut binärträd

Ekvationssystem, Matriser och Eliminationsmetoden

Föreläsning 12 Innehåll

Föreläsning 10 Datastrukturer (DAT037)

729G04 - Hemuppgift, Diskret matematik

Länkade strukturer. (del 2)

Partnerskapsförord. giftorättsgods görs till enskild egendom 1, 2. Parter 3. Partnerskapsförordets innehåll: 4

TIMREDOVISNINGSSYSTEM

Föreläsning Datastrukturer (DAT036)

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

Föreläsning 11 Innehåll

Listor. TDDD73 Funktionell och imperativ programmering i Python Föreläsning 7. Peter Dalenius Institutionen för datavetenskap

Föreläsning 3. Stack

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

Träd, binära träd och sökträd. Koffman & Wolfgang kapitel 6, avsnitt 1 4

a n = A2 n + B4 n. { 2 = A + B 6 = 2A + 4B, S(5, 2) = S(4, 1) + 2S(4, 2) = 1 + 2(S(3, 1) + 2S(3, 2)) = 3 + 4(S(2, 1) + 2S(2, 2)) = = 15.

Programmering fortsättningskurs

OOP Objekt-orienterad programmering

Föreläsning 10 Innehåll. Diskutera. Inordertraversering av binära sökträd. Binära sökträd Definition

Snabbslumpade uppgifter från flera moment.

Tentamen i Algoritmer & Datastrukturer i Java

Skriva B gammalt nationellt prov

Föreläsning 5: Rekursion

Lösningsförslag till tentamen Datastrukturer, DAT037,

BST implementering, huvudstruktur

Föreläsning 10 Innehåll

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

Föreläsning 11 Innehåll. Diskutera. Binära sökträd Definition. Inordertraversering av binära sökträd

Föreläsning 7. Träd och binära sökträd

Objektorienterad programmering D2

Föreläsning 3 Datastrukturer (DAT037)

Skapa en rapport med snygg formatering, rubriker, sidnummer och innehållsförteckning

Programexempel: tärningsspel

Rekursion: varför? Problem delas upp i mindre bitar algoritm för att lösa problemet erhålls från problemformuleringen

4-6 Trianglar Namn:..

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

Algoritmer och datastrukturer

Försättsblad till skriftlig tentamen vid Linköpings Universitet

Sortering. Föreläsning 12 Innehåll. Sortering i Java. Sortering i Java Exempel. Sortering

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Kontrollskrivning i Linjär algebra ,

Transkript:

LUNDS TEKNISKA HÖGSKOLA 1(5) Institutionen för datavetenskap Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg 2013 12 19, 8.00 13.00 Anvisningar: Denna tentamen består av 4 uppgifter. Preliminärt ger uppgifterna 1. 1 + 1 + 1 + 1 = 4 p 2. 2 + 1 +1 + 1 = 5 p 3. 8 + 1 = 9 p 4. 7 + 1 + 1 = 9 p 5. 7 + 2 = 9 p För full poäng ska dina lösningar inte vara onödigt ineffektiva. Bifogat tentamen finns Java snabbreferens samt dokumentation av någon/några klasser och interface i Java Collections Framework. När rättningen är klar meddelas detta på kursens hemsida (cs.lth.se/eda690). 1. Förklara följande begrepp: a) Stack b) Kollision i en hashtabell c) Balanserat binärt träd d) Partitionering i samband med Quicksort 2. Studera följande klass public class ListHandler { Tar bort alla dubbletter i listan list. public static <T> void deleteduplicates(list<t> list) { LinkedList<T> temp = new LinkedList<T>(); for (T element : list) { if (! temp.contains(element)) { temp.add(element); list = temp; a) Metoden deleteduplicates fungerar inte som avsett. Förklara varför och rätta till koden. Det är inte tillåtet att ändra metodens signatur. b) Vad får metoden för tidskomplexitet i värsta fall? Motivera ditt svar. c) Det finns effektivare sätt att ta bort dubbletter. Beskriv hur man kan göra istället. d) Vilken tidskomplexitet får din nya lösning? Motivera ditt svar.

2(5) 3. Antag att vi har en mängd element som tilldelas prioritet i form av ett heltal i ett intervall 1..k, där k är ett litet tal. 1 anger högsta prioritet och k lägsta. Vi kan då implementera en prioritetsköklass där alla operationer har en tidkomplexitet O(1) och där dessutom prioritetskön är stabil. Med stabil menas att bland element med lika prioritet tas det element som väntat längst ut först. Lös problemet genom att bilda k köer, en för varje prioritet. Nya element sätts in i den kö som deras prioritetstal anger. För att representera köerna ska cirkulära enkellänkade listor användas. I det sista elementet är inte referensen till efterföljaren (next) null utan i stället refererar den till det äldsta (första) elementet i listan. Se figur 1. referens till kön referens till kön Cirkulär lista att använda för att implementera en kö. next-referenser och referenser till insatta element är utritade. Noden längst till vänster innehåller det äldsta elementet i kön. Noden längst till höger innehåller det senast insatta elementet. Kö med ett enda element Figur 1: Kö som representeras av cirkulär enkellänkad lista. Eftersom elementen ska placeras in i rätt kö efter prioritet ställer vi kravet att de objekt som ska sättas in i kön är av en klass som implementerar ett interface Priority: public interface Priority { * Returns the element s priority * @return the element s priority int priority(); * Sets the element s priority to prio * @param prio the new priority void setpriority(int prio); a) Implementera klassen SimplePriorityQueue enligt ovanstående anvisningar. public class SimplePriorityQueue<E extends Priority> extends AbstractQueue<E> implements Queue<E> { private Node<E>[] queue; private int size; * Creates an empty priorityqueue. The allowed priorities are in the interval [1..k] * @param k the highest allowed priority public SimplePriorityQueue(int k) { queue = (Node<E>[]) new Node[k + 1]; // plats 0 används ej size = 0;

3(5) /* Nested class. Represents a node which contains an element of type E. private static class Node<E> { private E element; private Node<E> next; private Node(E x) { element = x; next = null; * Inserts the specified element into this priority queue. * @param e the element to add * @return true * @throws NullPointerException if the specified element is null * @throws IllegalArgumentException if the elements prio is outside * the allowed interval public boolean offer(e e) {... * Retrieves, but does not remove, the smallest element in this queue, or * returns null if this queue is empty. * @return the smallest element in this queue, or null if this queue is empty public E peek() {... * Retrieves and removes the smallest element in this queue, or returns null * if this queue is empty. * @return the smallest element in this queue, or null if this queue is empty public E poll() {... * Returns the number of elements in this queue. public int size() {... Anm. Egentligen måste man också implementera metoden iterator() i klassen SimplePriorityQueue men vi bortser från det i uppgiften. b) Felrapporteringssystem används inom många mjukvaruprojekt. När fel upptäcks av användare till ett program rapporteras felen in i systemet, som sedan hjälper programutvecklarna att hålla reda på och följa upp fel så att de blir åtgärdade. En felrapport (eng. ticket) beskrivs av klassen Ticket. Vi vill kunna ge en felrapport en prioritet i form av ett heltal samt kunna lagra felrapporter i en kö av typen SimplePriorityQueue. Gör de ändringar som behövs i klassen Ticket för att detta ska fungera. public class Ticket { private int id; private String title; // Felrapportens unika id-nr // Felrapportens titel public Ticket(int id, String title) { this.id = id; this.title = title;

4(5) public int getid() { return id; public String gettitle() { return title; 4. a) Följande klass beskriver ett binärt träd. public class BinaryTree<E extends Comparable<? super E>> { private Node<E> root;... operationer... private static class Node<E> { private E element; private Node<E> left; private Node<E> right;... operationer... Ett träd är heapordnat (eller partiellt ordnat) om det för varje nod gäller att dess element är mindre än eller lika med barnens element. Lägg till en metod i klassen BinaryTree<E> som returnerar true om trädet är heapordnat. Ledning och anvisningar: För full poäng får din lösning inte bygga på att du inför nya attribut i klasserna. Däremot är det tillåtet (och lämpligt) att lägga till en privat metod. Ett tomt träd ska betraktas som heapordnat. b) Att ett binärt träd är partiellt ordnat är ett krav för att trädet ska utgöra en heap. Det finns ytterligare ett villkor. Vilket? Bara namn på villkoret räcker inte för poäng. Beskriv också vad som menas med villkoret. c) En heap implementeras ofta på ett annat sätt än med ett binärt träd. Beskriv hur. I din beskrivning ska det ingå en figur med ett exempel. 5. a) I handelsresandeproblemet gäller det för en handelsresande att besöka ett antal städer. Varje stad ska besökas exakt en gång. Handelsresanden vill att den totala resvägen ska bli så kort som möjligt. Att lösa detta problem exakt är tidsödande, eftersom man måste beräkna alla möjliga resvägar för att finna den kortaste vägen. Vi nöjer oss därför i denna uppgift med att hitta en approximation till den bästa lösningen genom att i varje steg besöka den stad som ligger närmast den senast besökta staden. Kartan med alla städer beskrivs av en map av typen Map<String, List<TownDistance>>. Nyckeln är en teckensträng med stadens namn och värdet är en lista med TownDistanceobjekt. Klassen TownDistance beskriver avståndet till en annan stad (se nedan). Listorna med TownDistance-objekten är sorterade efter växande avstånd. Det finns uppgifter om avstånd för alla par av städer. public class TownDistance { private String destination; private int distance; // stadens namn // avstånd till staden (km) public TownDistance(String destination, int distance) { this.destination = destination; this.distance = distance; public String getdestination() {

5(5) return destination; public int getdistance() { return distance; Här är början på ett exempel som visar hur en karta med 6 städer skapas: Map<String, List<TownDistance>> map = new HashMap<String, List<TownDistance>>(); List<TownDistance> list = new LinkedList<TownDistance>(); list.add(new TownDistance("Lund", 21)); list.add(new TownDistance("Helsingborg",64 )); list.add(new TownDistance("Göteborg", 273 )); list.add(new TownDistance("Norrköping", 455)); list.add(new TownDistance("Stockholm", 613 )); map.put("malmö", list); list = new LinkedList<TownDistance>(); list.add(new TownDistance("Malmö", 21)); list.add(new TownDistance("Helsingborg", 55)); list.add(new TownDistance("Göteborg", 264)); list.add(new TownDistance("Norrköping", 445)); list.add(new TownDistance("Stockholm", 604 )); map.put("lund", list);... Din uppgift är att implementera metoden PrintTour i klassen RoadMap: public class RoadMap_list { private Map<String, List<TownDistance>> map; Skapar ett objekt som håller reda på en vägkarta. public RoadMap_list(Map<String, List<TownDistance>> map) { this.map = map; Skriver ut namnet på de städer som besöks, i tur och ordning, när man påbörjar en resa i staden med namnet starttown. Det förutsätts att det finns en stad med det namnet. Allra sist skrivs den totala resvägen (antal km) ut. public void printtour(string starttown) { // fyll i egen kod här Ledning och anvisningar: Använd följande algoritm: Använd en mängd, dvs. en klass som implementerar java.util.set för att hålla reda på de redan besökta städerna. Skriv ut startstadens namn, markera den som besökt (genom att lägga den i mängden för redan besökta städer). Leta upp närmaste stad som inte är besökt, skriv ut dess namn, markera den som besökt. Osv. b) Det finns algoritmer för att beräkna kortaste vägen mellan två städer. Då behöver man kunna lägga in objekt av typen TownDistance från förra uppgiften i en prioritetskö av typen java.util.priorityqueue. Man vill kunna hämta TownDistance-objektet med minsta avstånd. Gör de ändringar som krävs i klassen TownDistance för att den ska kunna läggas in i en sådan prioritetskö.

LUNDS TEKNISKA HÖGSKOLA 1(5) Institutionen för datavetenskap Lösningsförslag till tentamen i EDA690 Algoritmer och Datastrukturer, Helsingborg 2013 12 19 1. a) En samling element där insättning och borttagning sker överst på stacken. D.vs. det element som satts in senast är det element som först tas bort. b) Med kollision menas att hashfunktionen för ett element ger ett värde som motsvarar en redan upptagen plats i tabellen. c) I ett binärt träd har varje nod 0,1 eller 2 barn. I ett balanserat binärt sökträd gäller dessutom för varje nod att höjdskillnaden mellan dess båda subträd är högst 1. d) Den vektor som ska sorteras delas upp i två halvor genom att man först väljer ett av elementen (kallas pivot-element). Sedan flyttas elementen så att element pivot hamnar till vänster och element > pivot hamnar till höger om pivot-elementet. 2. a) När metoden deleteduplicates anropas kopieras en referens till den lista som ska ändras till parametern list. Men inuti metoden får list ett nytt värde och refererar nu till den nya temp-listan. Denna lista har fyllts på med unika värden, men den ursprungliga listan ändras ej. Sista raden i metoden ändras till: list.clear(); for (T element : temp) { list.add(element); b) O(n 2 ). Antag att listan innehåller n st. element. För vart och ett av elementen gör man en sökning bland de element som hittills lagts in i listan (som innehåller < n element). De n sökningarna kostar O(n n). Överflyttningen av de unika elementen till list kostar O(n). Totalt blir tidskomplexiteten alltså O(n 2 ). c) Man kan låta temp vara en mängd istället för en lista. Vid insättning sätts då ej dubbletter in. Mängden kan t.ex. implementeras med hjälp av en hashtabell eller ett binärt sökträd. d) Tidskomplexiteten beror på hur mängden implementeras. Om vi antar att vi använder en hashtabell kostar en insättning O(1) (i medelfall). Insättningen av de n elementen i mängden kostar då O(n 1). Överflyttningen av de unika elementen till list kostar O(n). Totalt blir tidskomplexiteten alltså O(n). Anm. Om vi istället använder ett binärt sökträd som mängd kostar en insättning O(logn) och den totala tidskomplexiteten blir O(nlogn). En annan lösning är att sortera elementen i listan (kostar O(nlogn). Dubbletter hamnar då intill varandra och vid genomgång av de sorterade elementen är det lätt att undvika att ta med dubbletterna. 3. a) public class SimplePriorityQueue<E extends Priority> extends AbstractQueue<E> implements Queue<E> { private Node<E>[] queue; private int size; * Creates an empty priorityqueue. The allowed priorities are in the interval [1..k] * @param k the highest allowed priority

2(5) public SimplePriorityQueue(int k) { queue = (Node<E>[]) new Node[k + 1]; // plats 0 används ej size = 0; /* Nested class. Represents a node which contains an element of type E. private static class Node<E> { private E element; private Node<E> next; private Node(E x) { element = x; next = null; * Inserts the specified element into this priority queue. * @param e the element to add * @return true * @throws NullPointerException if the specified element is null * @throws IllegalArgumentException if the elements prio is outside * the allowed interval public boolean offer(e e) { if (e == null) { throw new NullPointerException(); int prio = e.priority(); if (prio <= 0 prio >= queue.length) { throw new IllegalArgumentException(); Node<E> n = new Node<E>(e); if (queue[prio] == null) { queue[prio] = n; queue[prio].next = queue[prio]; else { Node<E> first = queue[prio].next; queue[prio].next = n; n.next = first; queue[prio] = queue[prio].next; size++; return true; * Retrieves, but does not remove, the smallest element in this queue, or * returns null if this queue is empty. * @return the smallest element in this queue, or null if this queue is empty public E peek() { int index = firstnonemptyindex(); if (index == -1) { return null; return queue[index].next.element;

3(5) * Retrieves and removes the smallest element in this queue, or returns null * if this queue is empty. * @return the smallest element in this queue, or null if this queue is empty public E poll() { int index = firstnonemptyindex(); if (index == -1) { return null; E e = queue[index].next.element; if (queue[index] == queue[index].next) { queue[index] = queue[index].next; queue[index] = null; else { queue[index].next = queue[index].next.next; size--; return e; /* * Returns the index for the first non empty list, or returns -1 if all lists * are empty. private int firstnonemptyindex() { for (int i = 1; i < list.length; i++) { if (list[i]!= null) { return i; return -1; * Returns the number of elements in this queue. public int size() { return size; Anm. Egentligen måste man också implementera metoden iterator() i klassen SimplePriorityQueue men vi bortser från det i uppgiften. b) public class Ticket implements Priority { private int id; // Felrapportens unika id-nr private String title; // Felrapportens titel private int prio = 5; public Ticket(int id, String title) { this.id = id; this.title = title; public int getid() { return id; public String gettitle() { return title;

4(5) public int priority() { return prio; public void setpriority(int prio) { this.prio = prio; 4. a) Returnerar true om trädet är partiellt ordnat, annars false. public boolean ispartiallyordered() { if (root!= null) { return ispartiallyordered(root); else { return true; private boolean ispartiallyordered(node<e> n) { if (n.left == null && n.right == null) { return true; if (n.left == null) { if (n.data.compareto(n.right.data) > 0) { return false; else { return ispartiallyordered(n.right); if (n.right == null) { if (n.data.compareto(n.left.data) > 0) { return false; else { return ispartiallyordered(n.left); return n.data.compareto(n.left.data) <= 0 && n.data.compareto(n.right.data) <= 0 && ispartiallyordered(n.left) && ispartiallyordered(n.right); b) Trädet är komplett, dvs.alla nivåer utom den högsta är fyllda med noder och om noderna på den högsta nivån är samlade längst till vänster : c) Man brukar implementera en heap med en vektor. Roten lagras på plats 0. Barnen till en nod vars element lagras på plats k i vektorn lagras på platserna 2k+1 och 2k+2. Exempel: 2 5 3 7 6 2 3 6 5 7 0 1 2 3 4

5(5) 5. a) public void printtour(string starttown) { Set<String> visitedtowns = new HashSet<String>(); visitedtowns.add(starttown); System.out.println(startTown); int totaldistance = 0; while (visitedtowns.size() < map.size()) { TownDistance nexttown = nearestunvisited(starttown, visitedtowns); System.out.println(nextTown.getDestination()); totaldistance += nexttown.getdistance(); visitedtowns.add(nexttown.getdestination()); starttown = nexttown.getdestination(); System.out.println("Total resväg " + totaldistance + (" km") ); TownDistance nearestunvisited(string starttown, Set<String> visitedtowns) { Iterator<TownDistance> itr = map.get(starttown).iterator(); while (itr.hasnext()) { TownDistance town = itr.next(); if (! visitedtowns.contains(town.getdestination())) { return town; return null; b) public class TownDistance implements Comparable<TownDistance> {... public int compareto(towndistance other) { return distance - other.distance; Anm. Här har vi valt att inte skugga equals vilket annars är brukligt när man implementerar Comparable. Metoden CompareTo ska användas specifikt i inuti prioritetskön och inte för att jämföra distans-objekt i allmänhet.