LUNDS TEKNISKA HÖGSKOLA 1(4) Institutionen för datavetenskap Tentamen, EDAA01 Programmeringsteknik fördjupningskurs 2015 01 12, 14.00 19.00 Anvisningar: Denna tentamen består av 5 uppgifter. Preliminärt ger uppgifterna 1. 1 + 1 + 1 + 1 + 1 = 5 p 2. 2 + 1 + 1 = 4 p 3. 10 p 4. 6 p 5. 2 + 1 + 5 + 3 = 11 p Tillåtet hjälpmedel: Java snabbreferens. För full poäng ska dina lösningar inte vara onödigt ineffektiva. I slutet av tentamen finns 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/edaa01). 1. Ange om följande påståenden är sanna eller falska. För poäng ska dina svar motiveras ordentligt. a) Betrakta följande algoritm: long sum = 0; for (int i = 0; i <= n; i++) { int prod = 1; for (int j = 0; j < i; j++) { prod = prod * x; sum = sum + prod; Antag att det då n = 100000 tar ca 3 sekunder att exekvera algoritmen på en viss dator. Att exekvera algoritmen för n = 500000 på samma dator tar då ca 15 sekunder. b) Man kan effektivt implementera en stack med hjälp av en vektor. c) Binärsökning passar bra vid sökning efter ett godtyckligt element i en sorterad enkellänkad lista. d) Det passar bra att använda en heap för att implementera den abstrakta datatypen mängd (eng. Set). e) En heap (minheap) implementeras ofta med en vektor. Elementen i denna vektor är alltid sorterade i stigande ordning. 2. a) Både mergesort och quicksort är rekursiva algoritmer av typen söndra och härska. Beskriv kort, men begripligt, i ord och i pseudokod hur mergesort fungerar. Den rekursiva metodens parametrar, basfall och det rekursiva steget (uppdelningen i enklare delproblem) ska framgå i pseudokoden. Gå för övrigt inte för djupt in på några detaljer. b) Quicksort påminner en hel del om mergesort, men uppdelning i enklare delproblem skiljer sig åt. På vilket sätt?
2(4) c) Nämn någon fördel Mergesort har jämfört med Quicksort. Nämn också någon fördel Quicksort har jämfört med Mergesort. 3. Antag att vi i någon tillämpning behöver lagra en mängd med heltal. I den aktuella tillämpningen är det vanligt att flera tal i följd lagras; till exempel kan en mängd innehålla talen 1 4, 18 23, 25, 28 57. Detta ska man utnyttja för att spara minnesutrymme. Interfacet IntSet beskriver en sådan mängd: public interface IntSet { /** Tar reda på om nbr finns i mängden. */ boolean contains(int nbr); /** Sätter in nbr i mängden om det inte redan finns. Returnerar true om nbr kan sättas in i mängden, i annat fall false. */ boolean insert(int nbr); /* Tar reda på antal tal i mängden. */ public int size() Din uppgift är att skriva en klass som implementerar interfacet IntSet enligt följande anvisningar: Mängden ska implementeras med en enkellänkad lista. Elementen i listan ska vara objekt av en statisk nästlad klass Node: private static class Node { private int min; private int max; private Node next; private Node(int min, int max) { this.min = min; this.max = max; next = null; Attributen min anger det minsta talet i en följd och max anger det största talet. Elementen ska vara sorterade i växande ordning. Först i listan ska det finnas ett element där min = max = Integer.MIN_VALUE, sist i listan ett element med min = max = Integer.MAX_VALUE. Dessa element underlättar eftersom varje element i listan kommer att ha en föregångare och en efterföljare. Listan i ett tomt IntSet innehåller båda dessa element. Exempel: MIN_VALUE MIN_VALUE 1 4 18 23 25 25 28 57 MAX_VALUE MAX_VALUE null Figur 1: Lista som beskriver mängden 1 4, 18 23, 25, 28 57 Flera fall kan inträffa när man lägger in ett tal i mängden. Exemplen från listan i figur 1: insert(20): talet finns redan, ingenting ska inträffa. insert(24): två element slås ihop till ett. insert(17): min-värdet i ett existerande element ska ändras. insert(5): max-värdet i ett existerande element ska ändras. insert(10): ett nytt element ska läggas in på rätt plats i listan.
3(4) 4. Ett binärt aritmetiskt uttryck kan representeras av ett strikt binärt träd. Se figur 2. + * 7 5-9 2 Figur 2: Binärt träd som representerar ett aritmetiskt uttryck. Följande klasser representerar ett binärt uttrycksträd. För enkelhets skull har vi i den här uppgiften låtit både operatorer och heltal representeras av en teckensträng. public class ExprTree { private ExprNode root; // refererar till roten i trädet // konstruktor och övriga metoder som inte är intressanta i den här uppgiften /** Returnerar värdet av det aritmetiska uttryck som trädet representerar. Om trädet är tomt ska 0 returneras. */ public int value() {... private static class ExprNode { private String element; private ExprNode left; private ExprNode right; // nodens innehåll // refererar till vänster barn // refererar till höger barn private ExprNode(String element) { this.element = element; left = null; right = null; Implementera metoden value med rekursiv teknik. Ledning och anvisningar: Gå igenom trädet i postorder vid beräkningen av värdet. Exempel: Det aritmetiska uttrycket i figur 2 har värdet 42. Det är tillåtet (och lämpligt) att lägga till en privat metod antingen i klassen ExprTree eller i klassen ExprNode. För omvandling från typen String till int kan man använda följande metod i klassen Integer: static int parseint(string s) 5. a) Man kan använda en öppen hashtabell (eng. separate chaining) för att implementera den abstrakta datatypen lexikon (eng. Map). Förklara vad som menas med en öppen hashtabell och vad som skiljer den från en sluten hashtabell. b) Föreslå någon annan datastruktur som kan användas för att på ett effektivt sätt implementera den abstrakta datatypen lexikon (eng. Map). Motivera ditt val. c) Ett lexikon (eng. Map) kan användas för att lösa följande problem:
4(4) En chokladask innehåller olika slags praliner. Tillverkaren funderar på att byta ut några av pralinerna mot nya och har därför genomfört en omröstning för att avgöra hur populära de olika pralinerna är. Rösterna är strängar och finns i en lista av typen List<String>: [Trillingnöt, Trillingnöt, Gräddnougat, Romrussin,..., Körsbär i likör, Gräddnougat] Det resultat som ska presenteras är antalet röster de olika pralinerna fått. [Trillingnöt 28, Romrussin 2, Gräddnougat 31,..., Körsbär i likör 5] Här är programkod som löser problemet: List<String> list = new ArrayList<String>(); // Här är programrader för att läsa in och lagra de olika rösterna (pralinnamn) i list Map<String, Integer> resultmap = VoteCounter.result(list); System.out.println(resultMap); Skriv färdigt klassen VoteCounter med den statiska metoden result som kan användas i problemet ovan. Metoden result ska vara generisk så att den ska kunna användas för att räkna annat än strängar. public class VoteCounter { /** Räknar antal olika slags element i listan votes och returnerar resultatet i en map med par av element och dess antal förekomster. */ public static <E> Map<E, Integer> result(list<e> votes) {... d) I deluppgift c anropas metoden result med en lista av typen List<String> som argument. Antag att list istället har typen List<Praline> och innehåller Praline-objekt istället för strängar. Klassen Praline set ur så här: public class Praline { private String name; private int mancost; // tillverkningskostnad (öre) public Praline(String name, int mancost) { this.name = name; this.mancost = mancost; public String getname() { return name; public int getmancost() { return mancost; public String tostring() { return name; Utskriften blir då inte längre den förväntade. Förklara varför. Gör det tillägg som krävs för att anropet av result med en lista av typen List<Praline> som argument ska fungera.
java.lang Interface Iterable<T> Type Parameters: T - the type of elements returned by the iterator Iterator<T> iterator() Returns an iterator over a set of elements of type T. java.util Interface Iterator<E> Type Parameters: E - the type of elements returned by this iterator Methods boolean hasnext() Returns true if the iteration has more elements. E next() Returns the next element in the iteration. void remove() Removes from the underlying collection the last element returned by this iterator (optional operation). java.lang Interface Comparable<T> Type Parameters: T - the type of objects that this object may be compared to int compareto(t o) Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. java.lang Interface Comparator<T> Type Parameters: T - the type of objects that may be compared by this comparator int compare(t o1, T o2) Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
java.util!interface Map<K,V> Type Parameters: K - the type of keys maintained by this map V - the type of mapped values All Known Implementing Classes: AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. Method Summary void clear() Removes all of the mappings from this map (optional operation). boolean containskey(object key) Returns true if this map contains a mapping for the specified key. boolean containsvalue(object value) Returns true if this map maps one or more keys to the specified value. Set<Map.Entry<K,V>> entryset() Returns a Set view of the mappings contained in this map. boolean equals(object o) Compares the specified object with this map for equality. V get(object key) Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. int hashcode() Returns the hash code value for this map. boolean isempty() Returns true if this map contains no key-value mappings. Set<K> keyset() Returns a Set view of the keys contained in this map. V put(k key, V value) Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value. void putall(map<? extends K,? extends V> m) Copies all of the mappings from the specified map to this map (optional operation). V remove(object key) Removes the mapping for a key from this map if it is present (optional operation). Returns the value to which this map previously associated the key, or null if the map contained no mapping for the key. int size() Returns the number of key-value mappings in this map. java.util Class HashMap<K,V> Hash table based implementation of the Map interface. Constructor Summary HashMap() Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75). HashMap(int initialcapacity) Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75). HashMap(int initialcapacity, float loadfactor) Constructs an empty HashMap with the specified initial capacity and load factor. HashMap(Map<? extends K,? extends V> m) Constructs a new HashMap with the same mappings as the specified Map. java.util Class TreeMap<K,V> A Red-Black tree. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used. Constructor Summary TreeMap() Constructs a new, empty tree map, using the natural ordering of its keys. TreeMap(Comparator<? super K> comparator) Constructs a new, empty tree map, ordered according to the given comparator. TreeMap(Map<? extends K,? extends V> m) Constructs a new tree map containing the same mappings as the given map, ordered according to the natural ordering of its keys. TreeMap(SortedMap<K,? extends V> m) Constructs a new tree map containing the same mappings and using the same ordering as the specified sorted map. java.util!interface Map.Entry<K,V> A map entry (key-value pair). Method Summary boolean equals(object o) Compares the specified object with this entry for equality. K getkey() Returns the key corresponding to this entry. V getvalue() Returns the value corresponding to this entry. int hashcode() Returns the hash code value for this map entry.