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++; * 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 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) { 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 { private boolean ispartiallyordered(node<e> n) { if (n.left == null && n.right == null) { 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; 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.