1(5)
Institutionen för datavetenskap
LUNDS TEKNISKA HÖGSKOLA
Tentamen, EDAA01 Programmeringsteknik –
fördjupningskurs
2015–03–17, 14.00–19.00
Anvisningar: Denna tentamen består av 4 uppgifter. Preliminärt ger uppgifterna
1.
2.
3.
4.
2+1+1+2+2=8
5 + 4 + 1 = 10 p
2+2+5=9p
1+1+1+6=9p
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.
a) Beskriv likheter och skillnader mellan ett interface och en abstract klass.
b) Ett binärt träd (ej sökträd) innehåller sju noder med heltalen 1-7. De tre olika rekursiva sätten
att traversera trädet ger resultatet nedan. Rita trädet!
Preorder: 1 2 4 3 5 7 6
Inorder: 2 4 1 5 7 3 6
Postorder: 4 2 7 5 6 3 1
c) Förklara vad som menas med en kollision i en hashtabell.
d) Antag att vi har har deklarerat och skapat följande map:
Map<Player, Integer> map = new HashMap<Player, Integer>();
Vad ställer det för speciella krav på klassen Player? Motivera ditt svar.
e) Antag att en vektor innehåller ett antal sorterade tal. Lägg till några få osorterade tal efter
de redan sorterade talen. Sortera sedan hela vektorn på nytt. Vad får denna sortering för
tidskomplexitet om man använder insättningssortering respektive mergeSort. Motivera ditt
svar.
2(5)
2.
a) Antag att vi har specificerat den abstrakta datatypen Stack i följande interface:
public interface Stack<E> {
/**
* Pushes an element onto this stack.
* @param e the element to push
*/
void push(E e);
/**
* Removes and returns the element on the top of this stack.
* @return the element at the top of this stack or null if this stack is empty
*/
E pop();
/**
* Retrieves, but does not remove, the element on the top of this stack.
* @return the element at the top of this stack or null if this stack is empty
*/
E peek();
/**
* Returns true if this stack contains no elements.
* @return true if this stack contains no elements
*/
boolean isEmpty();
}
Skriv en klass som implementerar interfacet Stack. Elementen i stacken ska lagras i en enkellänkad lista. Noderna i denna lista ska representeras av följande nästlade klass.
/* Nested class. Represents a node which contains an element of type E. */
static class ListNode<E> {
private E element;
private ListNode<E> next;
/* Creates a listnode which contains e. */
private ListNode(E e) {
element = e;
next = null;
}
}
För full poäng får ingen av metoderna ha högre tidskomplexitet än O(1).
b) Skriv en subklass till den stackklass du skrev i deluppgift a. Klassen ska innehålla en metod som tar bort de n översta värdena på stacken och returnerar dem i en lista. Metodens
returtyp ska vara List<E>. (List är interfacet java.util.List). Om antal element i stacken är
mindre än n ska alla element tas bort. Om n är mindre än ett ska IllegalArgumentException
genereras.
c) Ange någon annan datastruktur som kan användas för att effektivt implementera en stack.
Beskriv hur datastrukturen ska användas så att alla metoder får tidskomplexitet O(1).
3(5)
3.
a) För att representera ett binärt sökträd (ej balanserat) kan följande klasser användas:
public class BinarySearchTree<E extends Comparable<E>> {
private Node<E> root;
/** Skapar ett tomt binärt träd. */
public BinarySearchTree() {
root = null;
}
... metoder ...
private static class Node<E> {
private E element;
private Node<E> left;
private Node<E> right;
private Node(E element) {
this.element = element;
left = null;
right = null;
}
}
}
Antag att följande metoder lagts till i klassen BinarySearchTree<E>. Programkoden innehåller
en felaktighet eller olämplighet. Förklara vad som är fel/olämpligt. Rätta också till programkoden.
/** Beräknar trädets höjd. */
public int height() {
return height(root);
}
private int height(Node<E> n) {
if (n == null) {
return 0;
} else if (height(n.left) > height(n.right)) {
return 1 + height(n.left);
} else {
return 1 + height(n.right);
}
}
b) Antag att följande metoder lagts till i klassen BinarySearchTree<E>. Programkoden innehåller
en felaktighet eller olämplighet. Förklara vad som är fel/olämpligt. Rätta också till programkoden.
/** Lägger till x längst ned till vänster i trädet. */
public void addLeft(E x) {
addLeft(root, x);
}
private void addLeft(Node<E> n, E x) {
if (n == null) {
n = new Node<E>(x);
} else {
addLeft(n.left, x);
}
}
4(5)
c) Vi fortsätter med rekursion men nu handlar det om binära tal. Ett decimalt heltal n i (tal
i basen 10) kan omvandlas till binär representation (samma tal i talbasen 2) med hjälp av
följande observationer:
• Den binära representationen av det decimala talet 0 är 0.
• När n är större än 0 består dess binära representation av den binära representationen för
n/2 följt av siffran n%2 d.v.s. resten vid heltalsdivision med 2.
Exempel: Talet 9 har den binära representationen 1001, vilket består av 100 som är den
binära representationen av 4 (9/2) följt av siffran 1 (9%2).
Implementera med hjälp av detta en rekursiv metod
public static String binary(int n);
som returnerar en sträng innehållande den binära representationen av ett positivt decimalt
heltal.
Ledningar och anvisningar:
• Strängen får inte innehålla onödiga tecken. Speciellt får det inte finnas någon inledande
nolla när metoden anropas för n > 0.
• Det är (naturligtvis) tillåtet att lägga till en privat hjälpmetod.
• Låt metoden generera IllegalArgumentException om parametern är ett negativt tal.
4. När man ska samsortera k sorterade vektorer kan man använda en generalisering av merge-steget
i Mergesort. Man sätter in det första elementet från var och en av vektorerna i någon datastruktur.
I varje steg tar man sedan ut det minsta elementet ur denna struktur, lägger detta i resultatvektorn
och sätter i datastrukturen i stället in nästa element ur den vektor varifrån det minsta elementet
kom.
En heap är då ett lämpligt val av datastruktur för att hålla reda på de k element från vilka
minimum skall utväljas. Antag att man har 6 vektorer v1,...,v6 innehållande heltal enligt följande:
v1
v2
v3
v4
v5
v6
=
=
=
=
=
=
{4,
{1,
{5,
{7,
{2,
{3,
6,
2,
7,
9,
3,
4,
...}
...}
...}
...}
...}
...}
a) Visa hur heapen ser ut när man satt in det första elementet från var och en av de sex vektorerna.
Utgå ifrån att man sätter in dem i den ordning som vektorerna är uppräknade ovan. Visa steg
för steg hur heapen ser ut efter insättning av vart och ett av elementen.
b) Visa hur heapen ser ut när man plockat bort det minsta elementet ur den heap som byggts i
a samt satt in det andra elementet från den vektor från vilken det minsta elementet kom. Visa
detta i två steg, d.v.s. först heapens utseende efter borttagningen och därefter efter insättningen.
c) Man brukar implementera en heap med hjälp av en vektor. Förklara varför. Visa också hur en
vektor motsvarande heapen efter sista steget i b ser ut.
d) I den här uppgiften ska du implementera en metod som samsorterar ett antal vektorer med
den metod som beskrivs ovan. Metoden ska ha följande rubrik:
public static <T extends Comparable<T>> void mergeArrays(List<T[]> arrays)
Ledningar och anvisningar:
• Listan arrays innehåller vektorerna som ska samsorteras. Metoden mergeArrays ska skriva ut det samsorterade resultatet på System.out med ett element per rad.
• Klassen PriorityQueue<E> är implementerad med hjälp av en heap och ska användas för
att lösa uppgiften.
5(5)
• När man hämtat det minsta elementet från heapen ska man hämta nästa vektorelement
från den vektor detta element kom ifrån. Det räcker alltså inte med att lagra elementen
av typen T i heapen. Man måste också hålla reda på elementets ursprungsvektor. Därför
behövs en klass ArrayContainer<T> som håller reda på en vektor samt aktuell position i
vektorn. Klassen ArrayContainer<T> ser ut så här:
public class ArrayContainer<T extends Comparable<T>>
implements Comparable<ArrayContainer<T>> {
private T[] a;
private int index;
/** Skapar ett objekt som håller reda på en vektor samt aktuell position
i vektorn (0 från början). */
public ArrayContainer(T[] a) {
this.a = a;
index = 0;
}
/** Returnerar true om det finns fler element att hämta från vektorn. */
public boolean moreElements() {
return index < a.length;
}
/** Returnerar aktuellt element i vektorn och flyttar fram aktuell
position ett steg. */
public T getNextElement() {
return a[index++];
}
/** Jämför aktuellt element i denna vektor med aktuellt element i other. */
public int compareTo(ArrayContainer<T> other) {
return a[index].compareTo(other.a[other.index]);
}
}
java.lang
Interface Iterable<T>
Type Parameters: T - the type of elements returned by the iterator
Modifier and Type Method and Description
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
Modifier and Type
boolean
E
void
Method and Description
hasNext()
Returns true if the iteration has more elements.
next()
Returns the next element in the iteration.
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
Modifier and Type Method and Description
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
Modifier and Type
int
Method and Description
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
Class PriorityQueue<E>
Type Parameters:
E - the type of elements held in this collection
Constructor Summary
PriorityQueue()
Creates a PriorityQueue with the default initial capacity (11) that orders its elements
according to their natural ordering.
PriorityQueue(Collection<? extends E> c)
Creates a PriorityQueue containing the elements in the specified collection.
PriorityQueue(int initialCapacity)
Creates a PriorityQueue with the specified initial capacity that orders its elements
according to their natural ordering.
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
Creates a PriorityQueue with the specified initial capacity that orders its elements
according to the specified comparator.
Method Summary
boolean
add(E e)
Inserts the specified element into this priority queue.
void
clear()
Removes all of the elements from this priority queue.
Comparator<?
super E>
boolean
comparator()
Returns the comparator used to order the elements in this queue, or null if
this queue is sorted according to the natural ordering of its elements.
contains(Object o)
Returns true if this queue contains the specified element. More formally,
returns true if and only if this queue contains at least one element e such that
Iterator<E>
o.equals(e).
iterator()
boolean
offer(E e)
Returns an iterator over the elements in this queue.
Inserts the specified element into this priority queue.
E
peek()
Retrieves, but does not remove, the head of this queue, or returns null if
this queue is empty.
E
poll()
Retrieves and removes the head of this queue, or returns null if this queue
is empty.
boolean
remove(Object o)
Removes a single instance of the specified element from this queue, if it is
present. More formally, removes an element e such that o.equals(e), if this queue
contains one or more such elements. Returns true if and only if this queue
contained the specified element (or equivalently, if this queue changed as a
result of the call).
int
size()
Returns the number of elements in this collection.
boolean
isEmpty()
Object[]
toArray()
Returns true if this collection contains no elements.
Returns an array containing all of the elements in this queue.
<T> T[]
toArray(T[] a)
Returns an array containing all of the elements in this queue; the runtime
type of the returned array is that of the specified array.