Övningsuppgifter, EDAA30 Programmering i Java - fortsättningskurs



Relevanta dokument
public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

1 Repetition av viktiga begrepp inom objektorienterad programmering

Repetition av viktiga begrepp inom objektorienterad programmering

Övningsuppgifter, EDAA01 Programmeringsteknik fördjupningskurs

Övningar, Algoritmer och datastrukturer (EDA690)

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

Föreläsning 13 Innehåll

Föreläsning 4 Innehåll

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

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

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

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

Klasser och objekt i C#

Föreläsning 5-6 Innehåll

Vi skall skriva uppsats

Tentamen, EDAA20/EDA501 Programmering

EDAA20 Föreläsning Klassen ArrayList. Viktiga operationer på ArrayList. Generisk klass

Tentamen, EDAA01 Programmeringsteknik fördjupningskurs

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

Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg

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

Begreppet subtyp/supertyp i Java. Mera om generik. Generik och arv. Generik och arv. Innehåll

Föreläsning 9 Innehåll

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

Föreläsning REPETITION & EXTENTA

1 Repetition av viktiga begrepp inom objektorienterad programmering

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

Föreläsning 3 Innehåll. Generiska klasser. Icke-generisk lista ArrayList, skiss av implementering. Icke-generisk lista Risk för fel

Objektorienterad programmering i Java

Mål Förklaring av termer

Länkade strukturer. (del 2)

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

Föreläsning 6: Introduktion av listor

Mål Förklaring av termer

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Föreläsning 10. ADT:er och datastrukturer

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

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

Repetition av OOP- och Javabegrepp

Objektsamlingar i Java

Repetition av OOP- och Javabegrepp

Java Collections Framework. Föreläsning 2 Innehåll. Java Collections Framework interface hierarki. Java Collections Framework interface hierarki

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

Grundläggande programmering med C# 7,5 högskolepoäng

Gissa det hemliga talet

Datastrukturer. Arrayer. Arrayer. Arrayer. Array av arrayer. Array av arrayer

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

Programexempel: tärningsspel

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

Lathund, procent med bråk, åk 8

Tentamen i Objektorienterad programmering

TDDC30 Programmering i Java, Datastrukturer och Algoritmer Lektion 2. Länkade listor Stackar Köer MyList Iteratorer Lab 2 Exceptions Paket

Tentamen OOP

Erfarenheter från ett pilotprojekt med barn i åldrarna 1 5 år och deras lärare

DAT043 Objektorienterad programmering för D, DIT011 Objektorienterad programvaruutveckling för GU

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

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

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

Dugga Datastrukturer (DAT036)

Subklasser och arv Inledning till grafik (JFrame och JPanel). Något om interface. Objektorienterad programvaruutveckling GU (DIT011) Subklasser

OOP Objekt-orienterad programmering

Föreläsning Innehåll. Checklista. Några metoder i klassen ArrayList<E> Exempel på vad du ska kunna

Snabbslumpade uppgifter från flera moment.

Tentamen för kursen Objektorienterad programvaruutveckling GU (DIT010)

Föreläsning 5: Rekursion

Kapitel 6. f(x) = sin x. Figur 6.1: Funktionen sin x. 1 Oinas-Kukkonen m.fl. Kurs 6 kapitel 1

Objekt-orientering. Java är ett objekt-orienterat programmeringsspråk

Tentamen i Programmering grundkurs och Programmering C

Objektorienterad programmering D2

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

TDDC30 Programmering i Java, Datastrukturer och Algoritmer Lektion 2. Laboration 2 Datastrukturer En liten uppgift Frågor

Datorövning 2 Statistik med Excel (Office 2007, svenska)

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

4-6 Trianglar Namn:..

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

DAT043 Objektorienterad Programmering

Föreläsning 2 Innehåll. Generiska klasser. Generik i Java. Varför generiska klasser Bakgrund

Föreläsning 3-4 Innehåll

Föreläsning 2 Datastrukturer (DAT037)

Sätt att skriva ut binärträd

OOP Objekt-orienterad programmering

Objektorienterad programmering (OOP) Föreläsning 15 & 16. Klasser för olika slags fordon. Klasser och objekt

Föreläsning 9: Arv och UML

Föreläsning 2 Innehåll

Föreläsning 5 Innehåll

Datastrukturer. föreläsning 3. Stacks 1

Tommy Färnqvist, IDA, Linköpings universitet

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Tentamen Datastrukturer D DAT 036/DIT960

2. Betrakta följande program, där fyra heltal läses från tangentbordet och några (ointressanta) beräkningar görs:

Transkript:

LUNDS TEKNISKA HÖGSKOLA EDAA30 Programmering i Java - fortsättningskurs Institutionen för datavetenskap HT 2016 Övningsuppgifter, EDAA30 Programmering i Java - fortsättningskurs Övningsuppgifternas syfte är att ge en fördjupad förståelse för de begrepp som tas upp under kursen. De ger också träning i att lösa problem med hjälp av olika algoritmer och datastrukturer. De obligatoriska datorlaborationerna ger viktig träning men täcker inte allt i kursen. Därför är det viktigt att du också löser övningsuppgifterna. Uppgifterna består av en blandning av teorifrågor och av uppgifter där du ska skriva programkod. Om du vill lösa vissa av uppgifterna på dator går det därför bra. På kursens hemsida finns en del färdiga filer att hämta. Där finns också lösningsförslag till övningsuppgifterna. Tanken är att du arbetar med övningsuppgifterna dels på de schemalagda övningstillfällena och dels på egen hand utanför schemalagd tid. I kursens lärobok finns också övningsuppgifter, dels kortare uppgifter ( Self check ) och dels längre uppgifter ( Programming ) som med fördel kan lösas på dator. Innehåll 1 Repetition av viktiga begrepp inom objektorienterad programmering....... 3 2 Polymorfism, skuggning och överlagring av metoder................. 9 3 Interface, exceptions, generik, iteratorer......................... 13 4 Listor............................................. 16 5 Stackar och köer....................................... 20 6 Algoritmers effektivitet, tidskomplexitet......................... 22 7 Rekursion.......................................... 25 8 Träd, binära träd...................................... 30 9 Binära sökträd........................................ 33 10 Hashtabeller......................................... 35 11 Mängder och mappar................................... 36 12 Prioritetsköer, heapar.................................... 39 13 Sortering........................................... 43 1

Repetition av viktiga begrepp inom objektorienterad programmering 3 1 Repetition av viktiga begrepp inom objektorienterad programmering Tema: Arv, parameteröverföring, statiska attribut och metoder. Litteratur: I uppgifterna behandlas begrepp som ingått i grundkursen. Om du stöter på svårigheter får du repetera relevanta delar i läroboken från grundkursen. Arv behandlas också i läroboken avsnitt 1.2. Arv I några av uppgifterna nedan används klasserna Person, Student och FacultyMember. Klasserna har följande utformning: public class Person { protected String name; public Person(String name) { this.name = name; public void setname(string name) { this.name = name; public String tostring() { return name; public class Student extends Person { protected String program; protected int credits; public Student(String name, String program) { super(name); this.program = program; credits = 0; public String tostring() { return name + ", " + program;... public class FacultyMember extends Person { protected String department; public FacultyMember(String name, String department) { super(name); this.department = department; public String tostring() { return name + ", " + department;

4 Repetition av viktiga begrepp inom objektorienterad programmering Person Student FacutlyMember Figur 1: Superklassen Person med subklasserna Student och FacultyMember. U 1. Antag att vi har gjort följande deklarationer: Person p; Student s; FacultyMember f; Avgör för var och en av följande satser om de är korrekta eller ej: p = new Person("Lisa Svensson"); p = new Student("Lisa Svensson", "D"); s = new Person("Kalle Karlsson"); s = new Student("Kalle Karlsson","C"); s = new FacultyMember("Per Holm", "Computer Science"); p = s; s = p; f = s; U 2. Antag att vi deklarerat en variabel String info. Ange vilket värde info får i var och en av de satser där den förekommer i en tilldelning i följande programrader: Person p = new Person("Lisa Svensson"); info = p.tostring(); p = new Student("Lisa Svensson","D"); info = p.tostring(); Student s = new Student("Kalle Karlsson","C"); info = s.tostring(); FacultyMember f = new FacultyMember("Per Holm", "Computer Science"); p = f; info = p.tostring(); U 3. Föregående uppgift handlade om polymorfism och metodanrop. Om vi deklarerar att en referensvariabel ref har en viss typ C enligt C ref; så får ref referera till objekt av klassen C eller till objekt av eventuella subklasser till C. Antag att det i både denna subklass och i klassen C finns en metod p(). Problemet som behandlades i föregående uppgift var att avgöra vilken av metoderna p() som exekveras vid ett anrop: ref.p(); Formulera i egna ord hur detta avgörs.

Repetition av viktiga begrepp inom objektorienterad programmering 5 U 4. Betrakta följande klasser: Shape Square Figur 2: Den abstrakta klassen Shape och subklassen Square. public abstract class Shape { protected int x; protected int y; protected Shape(int x, int y) { this.x = x; this.y = y; public void move(int dx, int dy) { x = x + dx; y = y + dy; // övriga metoder public class Square extends Shape { private int side; public Square(int x, int y, int side) { super(x, y); this.side = side; public void draw() { // kod för att rita kvadraten Antag att vi har deklarerat två variabler s och sq: Shape s; Square sq; Vilka av följande tilldelningssatser är korrekta? sq = new Square(100, 100, 50); sq = new Square(50); s = new Shape(100, 100); s = new Square(100, 100, 50);

6 Repetition av viktiga begrepp inom objektorienterad programmering U 5. Antag att vi lägger till ytterligare en subklass Circle. Då kan vi skriva och köra följande exempelprogram (som skapar några figurer och sedan flyttar dem): public class Main { public static void main(string[] args) { Shape[] theshapes = new Shape[5]; theshapes[0] = new Square(100, 300, 100); theshapes[1] = new Square(400, 200, 100); theshapes[2] = new Circle(400, 400, 50); theshapes[3] = new Square(450, 450, 50); theshapes[4] = new Circle(200, 200, 35); for (int i = 0; i < theshapes.length; i++) { theshapes[i].move(10, 10); Om vi ändrar i programmet för att istället rita alla figurerna så fungerar det däremot inte:... for (int i = 0; i < theshapes.length; i++) { theshapes[i].draw();... Förklara varför. Gör den ändring i klassen Shape som behövs för att det nya programmet ska fungera. Statiska attribut och metoder U 6. Antag att vi i klassen Person lägger till ett attribut och två metoder enligt följande: protected static int seniorcitizenage = 67; public static void setseniorage(int i) { seniorcitizenage = i; public static int getseniorage() { return seniorcitizenage; Attributet representerar lagstadgad pensionsålder. a) Motivera vad det innebär att attributet och metoderna deklarerats som static. Förklara också varför man valt att deklarera attributet seniorcitizenage och de båda nya metoderna som static. b) Vilka av metodanropen nedan är korrekta? Person.setSeniorAge(65); Person p = new Person(...); p.setseniorage(65); c) Vad skrivs ut när följande rader exekveras? Person p = new Person(...); Person q = new Person(...); p.setseniorage(65); System.out.println(q.getSeniorAge());

Repetition av viktiga begrepp inom objektorienterad programmering 7 Parameteröverföring U 7. Givet en klass C med en metod incr enligt följande: public class C { public void incr(int i) { i++;... Vad skrivs ut när följande programrader exekveras? int j = 2; C c = new C(); c.incr(j); System.out.println(j); U 8. Antag att vi har en klass C med en metod m enligt följande: public class C { public void m(person p) { p = new Person("Kalle"); Vad skrivs ut när följande programrader exekveras: Person p = new Person("Lisa"); C c = new C(); c.m(p); System.out.println(p); U 9. Antag att metoden m i klassen C i stället har följande utformning: public void m(person p) { p.setname("kalle"); Vad skrivs då ut om samma rader som i föregående uppgift exekveras? U 10. Givet följande metod i någon klass C: public static void changeelement(int[] a, int index, int newvalue) { a[index] = newvalue; Vad skrivs ut när följande rader exekveras? int[] a = {1, 2, 3, 4, 5; C.changeElement(a, 3, 10); System.out.println(a[3]);

8 Repetition av viktiga begrepp inom objektorienterad programmering U 11. Antag att följande (mer eller mindre vettiga) metoder finns i en klass ArrayHandler: public static void r1(int[] a) { int[] temp = new int[a.length]; for (int i = 0; i < a.length; i++) { temp[i] = a[a.length - 1 - i]; a = temp; public static void r2(int[] a) { int[] temp = new int[a.length]; for (int i = 0; i < a.length; i++) { temp[i] = a[a.length - 1 - i]; for (int i = 0; i < a.length; i++) { a[i] = temp[i]; Vad har vektorerna nbrs1 och nbrs2 för värden efter det att följande rader exekverats? int[] nbrs1 = {10, 20, 30, 40, 50; int[] nbrs2 = {10, 20, 30, 40, 50; ArrayHandler.r1(nbrs1); ArrayHandler.r2(nbrs2);

Polymorfism, skuggning och överlagring av metoder 9 2 Polymorfism, skuggning och överlagring av metoder Tema: Du ska fördjupa dina kunskaper om polymorfism, skuggning och överlagring av metoder. Litteratur: Dessa begrepp har inte behandlats i alla grundkurser. Därför ingår det en hel del text att läsa i anslutning till just dessa uppgifter. Avsnitten 1.1 1.4 i läroboken är också relevanta för dessa uppgifter (avsnitt 3.1 3.3 i den gamla upplagan). Begreppen typ, subtyp och supertyp När vi deklarerar variabler anger vi vilken typ de har. Typen anger vilka värden som kan tilldelas variabeln. För referensvariabler används klassnamn (eller interfacenamn) för att ange typen: Person p; Set set; // Person är en klass // Set är ett interface Begreppen supertyp och subtyp är viktiga att känna till. Supertyper till en viss klass C är alla de klasser från vilka C ärver och alla de interface klassen implementerar. Supertyper till ett interface I är alla de interface från vilka I ärver. En klass C eller ett interface I är subtyp till alla sina supertyper. Varje objekt tillhör någon klass, den klass som används när objektet skapades. Om en referensvariabel deklareras ha en viss typ (klass eller interface) så får den referera till objekt av denna typ eller dess subtyper. Om ett interfacenamn har använts i deklarationen innebär detta speciellt att referensvariablen får referera till objekt av någon klass som implementerar detta interface. För variablerna p och s, deklarerade ovan, gäller därför att p kan referera till objekt av klasserna Person, Student och FacultyMember. Referensvariablen set kan referera till objekt av t ex klasserna TreeSet och HashSet som finns i java.util och som båda implementerar interfacet Set. Det är alltså tillåtet att skriva: set = new TreeSet(); set = new HashSet(); U 12. Rita ett klassdiagram i UML och ange alla subtyp supertyp-relationer som gäller när följande deklarationer gjorts: class A {.. interface I {.. class B extends A implements I {.. interface J extends I {.. class C extends B implements J {.. U 13. Antag att följande deklarationer gjorts: interface IA {..; interface IB extends IA {.. class C implements IA {.. Rita ett klassdiagram i UML. Vilka av tilldelningssatserna i följande kod är då korrekta? IA a = new C(); IB b = new C(); a = b;

10 Polymorfism, skuggning och överlagring av metoder b = a; C c = new C(); c = a; c = b; Metodsignaturer och metodanrop Antag att vi har en metod, deklarerad enligt följande mönster: public void m(type 1 param 1, Type 2 param 2,...); där Type i anger en klass eller ett interface. Metodens signatur är dess namn tillsammans med antalet parametrar och deras typer. Två metoder har samma signatur om de har samma namn, samma antal parametrar och om den i:e parametern i den första metoden har samma typ som den i:e parametern i den andra metoden för alla i. För att ett anrop, m(act 1, act 2,..);, ska vara korrekt krävs att varje aktuell parameter act i har en sådan deklarerad typ att tilldelningssatsen param i = act i är korrekt. Detta innebär att den deklarerade typen för act i måste vara Type i eller en subtyp till denna typ. U 14. Ange, för var och en av metodanropen i det följande om de är korrekta eller felaktiga: public class C { public void m(person p, Student s) {..... Person p1 = new Person(...); Student s1 = new Student(...); C c = new C(); c.m(p1, s1); c.m(p1, p1); c.m(s1, p1); c.m(s1, s1); p1 = new Student(...); c.m(p1, p1); Metodanrop, skuggning och överlagring Vi kan inte deklarera två metoder med samma signatur i en klass. Däremot kan det finnas metoder med samma signatur i en klass och i någon av dess superklasser eller subklasser. Det är detta som kallas att skugga metoder (eng: override). Om det i en klass C och i en subklass D till C finns metoder med samma signatur så säger vi att metoden i D skuggar (eng:overrides) metoden i klassen C. Metoder som har samma namn men olika signatur (t. ex olika antal parametrar eller olika typer på sina parametrar) sägs överlagra (eng: overload) varandra. Det är tillåtet att ha flera överlagrade metoder i samma klass. Överlagring inträffar också om en klass har en metod med samma namn men olika signatur som någon metod i en super- eller subklass. Då man gör ett metodanrop x.m(a,b) kommer någon metod med namnet m och med formella parametrar av en sådan typ att anropet är korrekt med hänsyn till typerna hos de aktuella parametrarna a och b att exekveras. I allmänhet är det inte svårt att avgöra vilken metod det blir. Ofta har vi bara en metod med rätt namn och rätt antal parametrar. Vid vissa typer av överlagring kan dock tveksamhet uppstå. Betrakta följande exempel:

Polymorfism, skuggning och överlagring av metoder 11 class BaseClass { public void foo(person p) {... public void foo(student s) {...... BaseClass bc = new BaseClass(); Person p = new Student(...); bc.foo(p); Vilken av foo-metoderna kommer att exekveras? De deklarerade typerna för bc respektive p används av kompilatorn för att avgöra detta. bc är av typen BaseClass och p är av typen Person. Kompilatorn undersöker därför om klassen BaseClass har en metod som heter foo och som har en formell parameter av en sådan typ att den kan anropas med en aktuell parameter av typen Person. Det finns bara en sådan, nämligen den första foo-metoden. bc skulle under exekvering kunna referera till ett objekt av en subklass till BaseClass om sådan finns. Exempel: class DerivedClass extends BaseClass { public void foo(person p) {...... BaseClass bc = new DerivedClass(); Person p = new Student(...); bc.foo(p); Nu blir det metoden foo i klassen DerivedClass som exekveras. Kompilatorn gör samma beslut som i föregående exempel och fastlägger signaturen på metoden till att vara namnet foo och en parameter av typen Person. Under exekvering kommer klassen för det objekt till vilket bc då refererar att utgöra den virtuella maskinens startpunkt för sökandet efter metod med denna signatur. Finns ingen sådan metod där fortsätter sökandet i superklassen etc. I detta fall startar alltså sökandet i DerivedClass där det finns en metod med rätt signatur. Ett ytterligare exempel där överlagrade metoder är definierade i olika klasser i en klasshierarki: class BaseClass { public void foo(person p) {... class DerivedClass extends BaseClass { public void foo(student s) {..... DerivedClass dc = new DerivedClass(); Person p = new Student(...); dc.foo(p); dc har typen DerivedClass som har två överlagrade metoder med namnet foo. Men bara en av dessa, den som är definierad i superklassen BaseClass passar för anropet eftersom dess parameter är av typen Person. Metoden i DerivedClass har ju formell parameter av typen Student och denna kan inte tilldelas en aktuell parameter av typen Person. Det blir alltså metoden foo i BaseClass som exekveras. Sammanfattning Nedan sammanfattas vad som sker vid kompilering respektive exekvering av ett metodanrop x.m(a,b);

12 Polymorfism, skuggning och överlagring av metoder 1. Den deklarerade typen för x används av kompilatorn för att bestämma i vilken klass sökandet efter metoder som har rätt signatur för anropet ska starta. Kalla denna klass C1. 2. I C1 och dess eventuella superklasser lokaliseras alla metoder som matchar metodanropet, dvs. har rätt namn och har sådana typer på sina formella parametrar att de kan tilldelas variabler av respektive aktuell parameters deklarerade typ. Om ingen sådan metod finns, genereras ett kompileringsfel. Om det bara finns en sådan metod, fortsätt med steg 3. I komplicerade fall med många överlagrade metoder kan det finnas flera som passar in. I så fall försöker kompilatorn få fram den metod som är "mest specifik" enligt vissa regler, som vi inte går in på här. Slutar denna process med att det finns mer än en möjlig metod får vi ett kompileringsfel (ambiguous method call). 3. En metod är nu utvald och det är en metod av dess exakta signatur som kommer att exekveras. Vilken det blir beror på klassen för det objekt x refererar till under exekvering. Kalla denna klass C2. Den virtuella maskinen startar sökandet efter metod att exekvera i C2 och fortsätter eventuellt i superklasser tills man hittar en med rätt signatur. I normala fall är det säkert att vi har en metod med rätt signatur någonstans i denna kedja, annars hade kompileringsfel genererats i steg 2 ovan. Bara om vi ändrat någonting som har med inblandade metoder att göra och glömt kompilera om vissa klasser kan sökandet misslyckas. I så fall får man ett exekveringsfel. Anmärkning till punkt 1: Metodanropet kan göras inifrån en annan metod och x kan vara en av de formella parametrarna till denna enligt följande: public void p(someclass x) { x.m(a,b);... Den deklarerade typen för x är då SomeClass. Anmärkningar till punkt 2: Det räcker här inte med att en metod har rätt namn och rätt typ på sina parametrar. Den måste också vara möjlig att anropa med hänsyn till sin skyddsnivå (private, public etc.). Den som vill veta mera om hur det går till att bestämma mest specifika metod när man har flera kandidater kan gå till avsnitt 15.12 i Javas språkdefinition som finns på adressen http://docs.oracle.com/javase/specs/ Anmärkningar till punkt 3: Att man först under exekvering bestämmer exakt vilken metod som exekveras brukar kallas dynamisk bindning (eng: dynamic binding eller late binding). Ibland kan man dock redan under kompileringen bestämma vilken metod som ska exekveras. Metoder som är deklarerade final får inte omdefinieras i subklasser. Om steg 2 slutar med att man hittat en metod och denna är final så vet man alltså att det måste bli denna som ska exekveras. U 15. Vad ingår i en metods signatur? U 16. Vad menas med överskuggning? Ge exempel. U 17. Vad menas med överlagring? Ge exempel.

Interface, exceptions, generik, iteratorer 13 3 Interface, exceptions, generik, iteratorer Tema: Interface, exceptions, generik, introduktion till Java Collection FrameWork, iteratorer. Litteratur: Avsnitt 1.1, 1.5-1.6, 2.1, Appendix A6, A11, A12 (i gamla upplagan: 1.1-1.3, 2.1-2.4, 4.1). Bilderna från föreläsning 1 och 2. Interface U 18. Vad är ett interface och hur ser ett interface ut i stora drag? Vad innebär det att en klass implementerar ett interface? U 19. Beskriv likheter och skillnader mellan ett interface och en abstrakt klass. U 20. a) Antag att följande interface är deklarerat: public interface Resizable { /** * Scales down the object with scalefactor. * @param scalefactor the scale factor which is used to reduce the * size of the object */ void downsize(int scalefactor); Skalfaktorn är nämnare i det bråk som beskriver skalan (1: skalfaktor). Ju större skalfaktor man har desto mindre blir avbildningen. Exempel: i en skala 1:10000 motsvaras 10000 cm i verkligheten av 1 cm på avbildningen. Klassen Rectangle beskriver en kvadrat. Ändra klassen så att den implementerar interfacet Resizable: public class Rectangle { private double height; private double width; public Rectangle(double h, double w) { height = h; width = w;... b) Avgör för var och en av följande satser om de är korrekta eller ej. Rectangle r = new Rectangle(50, 100); Resizable r = new Resizable(50, 100); Resizable r = new Rectangle(50, 100); Exception U 21. a) Ändra metoden downsize från uppgift U 20 så att exception genereras om parametern scalefactor har ett värde som är 0. b) Antag att en variabel r refererar till ett Rectangle-objekt och att en variable n innehåller ett heltal. Anropa downsize och skriv ut en lämplig felutskrift på System.out om exception genereras.

14 Interface, exceptions, generik, iteratorer Implementera en generisk klass U 22. Antag att det i ett klassbibliotek finns det en generisk klass ArrayCollection som representerar en samling element. (Klassen ArrayCollection är en enkel variant av ArrayList.) I implementeringen har man använt en vektor för att representera samlingen enligt följande implementeringsskiss: public class ArrayCollection<E> implements Collection<E> { private E[] thecollection; private int size; /** Constructs an empty list with an initial capacity of ten. */ public ArrayCollection() { thecollection = (E[]) new Object[10]; /** Appends the specified element to the end of this list. Returns true if this collection changed as a result of the call. */ public boolean add(e x) { if (size == thecollection.length) { doublearray(); thecollection[size] = x; size++; return true; /** Returns true if this collection contains the specified element. */ public boolean contains(object x) {... /* Creates an new array that is twice the size of the current array and copies the content of the current array into the new one. */ private void doublearray() {...... Implementera metoderna contains och doublearray. U 23. En användare av klassen har implementerat en klass Person enligt följande: public class Person { private String name;... public boolean equals(person p) { return name.equals(p.name); public String tostring() { return name;

Interface, exceptions, generik, iteratorer 15 Iterator Följande kod exekveras: ArrayCollection<Person> coll = new ArrayCollection<Person>(); coll.add(new Person("Lisa Svensson")); if (coll.contains(new Person("Lisa Svensson")) ){ System.out.println("Lisa Svensson found"); else { System.out.println("Lisa Svensson not found"); Utskriften blir Lisa Svensson not found. Förklara varför. Vad ska vi göra för att Lisa ska hittas? Ledning: Inuti contains anropas en metod för att jämföra två objekt. Vilken? Vid kompileringen fastställs signaturen för de metoder som ska anropas. Vilken signatur får ovan nämnda metod? I vilken klass börjar sökandet efter en metod med denna signatur vid exekveringen? Finns det någon sådan metod i den klassen? Finns det någon sådan metod i någon superklass till den klassen? U 24. I java.util finns interfacen Iterator<E> och Iterable<E>. De har snarlika namn och är därför lätta att blanda ihop. Red ut begreppen genom att diskutera vad de används till och vad de innehåller för metoder. U 25. Klassen ArrayCollection från uppgift U 22 implementerar interfacet Collection<E> som är ett subinterface till interfacet Iterable<E>. Alltså måste klassen ArrayCollection även implementera metoden iterator(). Antag att detta är gjort och att vi har lagt in ett antal personer i samlingen ArrayCollection<Person> coll. a) Skriv programrader som med hjälp av en iterator skriver ut alla personerna i coll. b) Lös samma problem som i deluppgift a men använd en foreach -sats. U 26. Ändra klassen ArrayCollection från uppgift U 22 så att den även implementera metoden iterator(). U 27. Alla interface och klasser som representerar en samling (Collection) i Javas klassbibliotek har en operation iterator() som returnerar ett objekt av en klass som implementerar interfacet Iterator. I interfacet Iterator finns bl.a. metoderna hasnext och next som kan användas för att traversera (iterera över) samlingens element. Varför lägger man inte i stället in metoderna hasnext och next i samlingsklasserna?

16 Listor 4 Listor Tema: Listor, listimplementeringar - enkellänkad lista, sorterad lista, interfacet Comparable. Litteratur: Avsnitt 2.1 2.3, 2.5 2.7, 2.9-2.10 (avsnitt 4.1 4.5, 4.8 i gamla upplagan). Läs också bilderna från föreläsning 3. Använda ArrayList och LinkedList skugga equals U 28. I kursen arbetar vi bland annat med klasser och interface från Java Collections Framework. Ett exempel på sådana är interfacet List samt klasserna ArrayList och LinkedList i paketet java.util. I klasserna ArrayList och LinkedList finns metoder för att hitta ett element i listan, contains(object), indexof(object) och remove(object). Hur avgörs om två element är lika? Vem bestämmer vad som menas med lika (den som implementerat listklassen eller den som använder klassen) och hur gör man det? U 29. Antag att vi ska lagra böcker i en lista av någon av dessa typer. En bok beskrivs av följande klass: public class Book { private String isbn; private String title; private String author; public Book(String isbn, String title, String author) { this.isbn = isbn; this.title = title; this.author = author; public String tostring() { return author + ": " + title; En bok identifieras av sitt ISBN-nummer. Gör de förändringar i klassen Book som behövs för att metoderna contains, indexof och remove ska fungera som förväntat. U 30. Antag att vi har deklarerat följande lista och lagt in ett antal böcker av typen Book i listan: List<Book> list = new ArrayList<Book>() // satser för att lägga in böcker i listan Lägg till sats/er för att ta reda på om boken med ISBN-nummer 9780345917430 finns i listan. Enkellänkad lista I några av uppgifterna används klasserna SingleLinkedList och ListNode: public class SingleLinkedList<E> { private ListNode<E> first; /** Creates an empty list. */ public SingleLinkedList() { first = null;

Listor 17 /** Inserts the specified element at the beginning of this list. */ public void addfirst(e e) { ListNode<E> n = new ListNode<E>(e); n.next = first; first = n;... /* Nested class. Represents a node which contains an element of type E. */ private 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; U 31. Skriv programrader som skapar ett lista av typen SingleLinkedList för att lagra heltal samt ser till att listan innehåller talen 1, 2, 3. U 32. a) Lägg till följande metod i klassen SingleLinkedList: /** Returns the first element in this list. Throws NoSuchElementException if this list is empty. */ E getfirst(); b) Lägg till följande metod i klassen SingleLinkedList: /** Returns the last element from this list. Throws NoSuchElementException if this list is empty. */ E getlast(); U 33. Lägg till följande metod i klassen SingleLinkedList: /** Returns true if this collection contains the specified element. */ public boolean contains(object x); U 34. Lägg till följande metod i klassen SingleLinkedList: /** Removes the first occurrence of the specified element from this list, if it is present. If this list does not contain the element, it is unchanged. Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call). */ boolean remove(object e); Ledning: Utgå från din lösning på uppgift U 33. Tänk på att du för att kunna ta bort ett element måste ha en referens till föregående element i listan. Håll därför reda både på aktuellt element och dess föregångare när du går framåt i listan under sökningen. Tänk på specialfallen (tom lista, det är första elementet som ska tas bort...).

18 Listor Implementering genom delegation U 35. I läroboken, kapitel 2, finns en implementering av en klass OrderedList som representerar en följd av element, sorterad i växande ordning. Klassen har följande utformning: public class OrderedList<E extends Comparable<E>> implements Iterable<E> { private LinkedList<E> thelist; public OrderedList() { thelist = new LinkedList<E>(); public void add(e obj) { ListIterator<E> itr = thelist.listiterator(); while (itr.hasnext()) { if (obj.compareto(itr.next()) < 0) { itr.previous(); itr.add(obj); return; itr.add(obj); public E get(int index) { return thelist.get(index); public Iterator<E> iterator() { return thelist.iterator(); public int size() { return thelist.size(); I metoden add ser man till att listan blir sorterad i storleksordning genom att leta upp rätt position för objektet obj. Övriga metoder utför sin uppgift genom att delegera till motsvarande operation i klassen LinkedList (som visas i koden ovan för metoderna get, iterator och size). Varför implementerar man inte OrderedList genom att ärva från klassen LindkedList<E> enligt följande mönster? public class OrderedList<E extends Comparable<E>> extends LinkedList<E> U 36. Lägg till metoden remove i klassen OrderedList. Tänk på utnyttja att listan är sorterad så att du inte undersöker onödigt många element. /** Removes the first occurrence of the specified element from this list, if it is present. If this list does not contain the element, it is unchanged. Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call). */ boolean remove(e obj);

Listor 19 U 37. I OrderedList finns det en metod iterator som returnerar en Iterator för listan. Varför finns det inte också en metod listiterator som returnerar en ListIterator? Implementera interfacet Comparable U 38. I klassen OrderedList i uppgift U 35 anges typparametern på följande sätt: <E extends Comparable<E>> Vad innebär det? Skulle man istället kunna skriva bara <E>? U 39. Antag att vi ska använda klassen OrderedList i uppgift U 35 för att hålla reda på patienter som väntar på en akutmottagning. Varje patient tilldelas en prioritet, som är ett heltal. Ett lågt värde på detta attribut motsvarar hög prioritet. Patienter representeras av följande klass: public class Patient { private String firstname; private String lastname; private int prio; public Patient(String firstname, String lastname, int prio) { this.firstname = firstname; this.lastname = lastname; this.prio = prio;... Se till att klassen implementerar gränssnittet Comparable<T>. Det är prioriteterna som ska jämföras här och inte namnen. Tänk också på att det är en god regel att också omdefiniera metoden boolean equals(object x) som finns i superklassen Object så att dessa båda metoder är ense om när två objekt av klassen är lika. U 40. Hur ska metoden compareto implementeras om man istället för prioritet ska jämföra namnen? Antag att man i första hand ska sortera efter efternamn.

20 Stackar och köer 5 Stackar och köer Tema: Abstrakta datatyperna köer och stackar, implementeringar och användning. Litteratur: Avsnitt 3.1 3.3 och 4.1 4.3 (5.1 5.3 och 6.1 6.3 i gamla upplagan). Läs också bilderna från föreläsning 4. U 41. Beskriv den abstrakta datatypen kö. Vilka är de viktigaste operationerna på en kö. U 42. Beskriv den abstrakta datatypen stack. Vilka är de viktigaste operationerna på en stack. U 43. Beskriv (i ord) hur man kan implementera den abstrakta datatypen stack genom att delegera till LinkedList använda en enkellänkad lista använda en vektor Implementeringen ska inte vara onödigt ineffektiv. U 44. Ett annat sätt att skaffa sig en stack är att helt enkelt skapa ett LinkedList-objekt och använda lämpliga metoder i den klassen. Vilka fördelar/nackdelar finns det med detta? U 45. Givet en kö q. Visa hur man kan använda en stack för att vända kön bak och fram. Gör detta genom att skriva kod. Du kan utgå från följande gränssnitt för kö respektive stack samt anta att det finns en klass MyStack<E> som implementerar Stack<E>. public interface Queue<E> { public E poll(); public E peek(); public void offer(e x); public boolean isempty(); public interface Stack<E> { public E pop(); public E peek(); public void push(e x); public boolean isempty(); // tar bort och returnerar första elementet // returnerar första elementet, utan att ta bort det // lägger in x sist i kön // undersöker om kön är tom // tar bort och returnerar översta elementet // returnerar, men tar inte bort översta elementet // lägger in x överst på stacken // undersöker om stacken är tom U 46. En dequeue (eng: double-ended queue) är en följd av element där det är tillåtet att ta bort första och sista elementet och att lägga in nya element först och sist. Implementera en dequeue med en enkellänkad lista enligt följande: public class Dequeue<E> { private Node<E> first; private Node<E> last; // reference to the first element // reference to the last element /** Creates an empty dequeue. */ public Dequeue() { first = last = null; /** Inserts the specified element at the beginning of this dequeue. */ public void addfirst(e x) {... /** Inserts the specified element at the end of this dequeue. */ public void addlast(e x) {...

Stackar och köer 21 /** Removes and returns the first element in this dequeue. Returns null if this dequeue is empty. */ public E removefirst() {... /** Removes and returns the last element in this dequeue. Returns null if this dequeue is empty. */ public E removelast() {... private static class Node<E> { private E element; private Node<E> next; private Node(E element) { this.element = element; next = null; U 47. I föregående uppgift representeras noderna i kön av en statisk klass Node<E> som är deklarerad i klassen Dequeue. a) Om vi stryker static i deklarationen av nodklassen blir den en s.k. inre klass. (En inre klass är en icke-statisk klass deklarerad i en annan klass). Vad blir skillnaden? b) Kan vi låta nodklassen vara en inre klass? U 48. Tänk ut lämpliga testfall för den klass som implementerades i föregående uppgift. Det räcker att du formulerar dem i ord, men om du vill kan du alternativt formulera dem som testmetoder i JUnit.

22 Algoritmers effektivitet, tidskomplexitet 6 Algoritmers effektivitet, tidskomplexitet Tema: Enkla tekniker för att uppskatta effektiviteten hos algoritmer. Litteratur: Avsnitt 2.4 i läroboken (2.8 i gamla upplagan) och bilderna från föreläsning 5. U 49. Vad är tidskomplexitet? Hur räknar man ut tidskomplexitet? U 50. I de fyra deluppgifterna i denna uppgift ska följande frågor besvaras: hur många gånger kommer satsen SimpleStatement att utföras? vad är tidskomplexiteten (ordo-notation)? a) for (int i = 1; i <= n; i++) { for (int j = 1; j <= 2; j++) { SimpleStatement; b) for (int i = 1; i <= n; i++) { for (int j = 1; j <= n/2; j++) { SimpleStatement; c) for (int i = 1; i <= n; i++) { for (int j = n; j >= i; j--) { SimpleStatement; d) for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j) { SimpleStatement; U 51. En s.k. dequeue (double-ended queue) är en följd av element där man får ta bort första eller sista elementet och sätta in nya element längst fram eller längst bak. a) Vad blir kostnaden för de fyra operationerna om en dequeue representeras av en referens till det första elementet i enkellänkad datastruktur? b) Vad blir kostnaden för operationerna om man använder en enkellänkad struktur och låter en dequeue representeras av en referens till första elementet och en till det sista? c) Finns det någon representation i vilken alla operationer får kostnaden O(1)? U 52. Varför använder man tidskomplexitet istället för att helt enkelt mäta exekveringstiden? Hur förhåller sig den verkliga tidsåtgången till tidskomplexiteten? U 53. Man har analyserat en algoritm med avseende på tidskomplexitet och kommit fram till att den är O(n). Man har också implementerat algoritmen och mätt exekveringstiden. För

Algoritmers effektivitet, tidskomplexitet 23 n = 100 tog det 1 ms. Hur lång tid kommer det att ta för n = 1000 om körningen sker på samma dator? U 54. Man har analyserat en algoritm med avseende på tidskomplexitet och kommit fram till att den är O(2 n ). Man har också implementerat algoritmen och mätt exekveringstiden. För n = 10 tog det 1 ms. Hur stort problem kan man lösa med algoritmen (på samma dator) om man har en sekund på sig? U 55. I Javas klassbibliotek finns två klasser som implementerar interfacet List. Den ena klassen ArrayList använder ett fält (vektor) för att representera listan. Den andra LinkedList använder en dubbellänkad lista med referens till första och sista elementet. a) Vad blir tidskomplexiteten för metoden get(int index) i respektive implementering? b) Vad blir tidskomplexiteten för metoden indexof(object x) i respektive implementering? c) Vad blir tidskomplexiteten för metoden add(int index, E element) i respektive implementering? d) Vad blir tidskomplexiteten för metoden remove(int index) i respektive implementering? e) Betrakta följande kod: int sum = 0; for (int i = 0; i < list.size(); i++) { sum = sum + list.get(i); Vad är tidskomplexiteten om list är av typ ArrayList<Integer> respektive Linked- List<Integer>? f) Finns det något sätt att skriva om koden i föregående deluppgift så att den blir lika effektiv oavsett vilken av de två typerna list har? U 56. I början av en kurs tänker kursansvarig lärare göra ett upprop. Läraren har tillgång till en osorterad lista med anmälda studenter, n st. Det finns n+k studenter i lokalen vid start (flera har nämligen glömt anmäla sig). k är litet i förhållande till n. Läraren väljer nu mellan två tillvägagångssätt: 1. Alla studenterna presenterar sig en efter en. För varje student letar läraren på sin lista. Om studenten finns på listan antecknas närvaro, annars skrivs studenten in sist på listan. 2. Läraren läser upp namnen på sin lista. Studenterna ombeds svara om de är närvarande. Närvaro registreras på listan. När hela listan lästs ombeds de (ungefär k) vars namn inte lästs upp presentera sig och de skrivs in på listan. Vilken algoritm är effektivast? Vad är tidskomplexiteten för algoritmerna i ordo-notation? U 57. Det finns ett problem som brukar kallas kändisproblemet och som går ut på att ta reda på om det finns en kändis i en samling med n personer. För att en person p ska vara kändis i en mängd krävs att alla personer i mängden känner p och att p inte känner någon av de andra i mängden. a) Av definitionen av en kändis följer att det kan finnas högst en kändis i en mängd. Förklara varför!

24 Algoritmers effektivitet, tidskomplexitet b) En algoritm för att ta reda på om det finns en kändis i en mängd är att numrera personerna 1,2,...n och använda en boolesk matris med n rader och n kolumner. Plats (i,j) i matrisen får värdet true om person nummer i uppger att hon/han känner person nummer j, annars false. Matrisen fylls i enligt följande algoritm: for (p = 1; p <= n; p++) { for (q = 1; q <= n; q++) { fråga person nummer p om hon/han känner person nummer q fyll i resultatet på plats (p,q) i matrisen for (row = 1; row <= n, row++) { om alla element i raden row, utom diagonalelementet, är false // i så fall känner person nummer row inte någon (utom sig själv) om alla element i kolumn row är true // i så fall känner alla person nummer row returnera true; returnera false Att vi undantar diagonalelementet på raden i algoritmen ovan beror på att alla (inklusive kändisar) får antas känna sig själva. Vad är kostnaden för denna algoritm? c) En alternativ algoritm bygger på att man ur mängden tar ut två godtyckliga personer p och q. Därefter frågar man p: Känner du q?. Om svaret är ja kan p uteslutas som kändis. Om svaret är nej kan q uteslutas. Den av personerna som inte kunde uteslutas placeras åter i mängden. Sedan fortsätter man på samma sätt tills mängden bara består av en enda person, x. x är den enda kvarvarande kandidaten till att vara kändis. Men det är inte säkert att x är kändis. (Varför?). Till sist frågar man därför x om hon/han känner de andra n-1 personerna och man frågar de andra n-1 personerna om de känner x. Sedan vet man om x var en kändis. Vad är tidskomplexiteten för denna algoritm? U 58. En student har analyserat en sorteringsalgoritm och kommit fram till att dess tidskomplexitet är O(n 2 ). Nu vill studenten kontrollera att detta är rätt genom att implementera algoritmen och mäta exekveringstiden för olika storlek på problemet. Beskriv hur man kan göra detta så att det verifieras att analysen är korrekt.

Rekursion 25 7 Rekursion Tema: Rekursiva algoritmer. Litteratur: Avsnitt 5.1 5.5 (7.1 7.5 i gamla upplagan) samt i bilderna från föreläsning 6. U 59. Man kan definiera potensfunktionen x n (n heltal 0) rekursivt enligt: x 0 = 1 x n = x x n 1 a) Skriv en rekursiv metod public static double power(double x, int n) som beräknar x n enligt denna definition. b) Beräkningen kan göras effektivare om man i stället gör följande definition: x 0 = 1 x n = (x n/2 ) 2 om n>0 och jämnt x n = x (x n/2 ) 2 om n>0 och udda Gör en ny implementering av metoden i a enligt denna definition. (Med n/2 avses här heltalsdivision.) c) Ändra lösningen från uppgift b så att den även klarar negativa värden på n. Ledning: Skriv en metod som kontrollerar om värdet på n är negativt eller ej och sedan anropar den rekursiva metoden från b. Tänk på att x n = 1 x n. U 60. Betrakta följande class: public class MysteryClass { public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); public static void main(string[] args) { MysteryClass.mystery(3); Vad skrivs ut när man kör programmet? U 61. I rekursiva metoder ska det finnas minst ett basfall. Förklara begreppet basfall. Förklara också varför det måste vara med. U 62. En palindrom är ett ord eller en mening som kan läsas på samma sätt både fram- och baklänges. Exempel: DALLASSALLAD, NITALARBRALATIN. Skriv en metod med rubriken public static boolean ispalindrome(string s) som med rekursiv teknik undersöker om en sträng är en palindrom. Ledning: Låt ispalindrome anropa en annan rekursiv metod som förutom strängen har två heltalsparametrar som anger index för första och sista tecken i den delsträng som ska undersökas.

26 Rekursion U 63. Skriv en rekursiv metod som räknar ut hur mycket ett kapital växer med ränta på ränta: static double computecapital(double capital, int years, double interestrate); De data vi har är startkapital i kronor, antal år ( 0) och räntesats (i procent). Exempel: Om startkapitalet är 1000 kr och räntesatsen är 10% så får man 100 kr i ränta under första året och kapitalet har alltså vuxit till 1100 kr. År två får man 110 kr i ränta och kapitalet har vuxit till 1210 kr. Efter tre år har man 1331 kr etc... U 64. Antag att vi vet att en funktion f (x) har ett nollställe i ett visst intervall [x1, x2]. Då kan vi beräkna detta nollställe med en teknik som liknar binärsökning. Vi ska alltså stänga in nollstället genom upprepade halveringar av intervallet [x1, x2] tills intervallet är tillräckligt litet (mindre än eps som t ex kan vara lika med 0.0001). En intervallhalvering går till så att man först beräknar mittpunkten, m, och därefter ersätter x1 eller x2 med m. För att avgöra om det är x1 eller x2 om ska ersättas jämförs tecknen på f (m) med f (x1) och f (x2). Om f (m) har samma tecken som f (x1) ska mittpunkten ersätta x1, annars ska mittpunkten ersätta x2. Exempel: i figuren nedan är f (x1) och f (m) båda negativa och sökningen fortsätter i högra halvan av interfallet. f(x) f(x) x1 m x2 x x1 m x2 x Metoden getzero i klassen Bisection löser problemet ovan: public class Bisection { /** Beräknar nollstället för funktionen f i intervallet [low, high] med precisionen eps. Förutsätter att det finns ett nollställe i intervallet. */ public static double getzero(double low, double high, double eps, Function f) {... Function är ett interface med en metod för att beräkna ett funktionsvärde: public interface Function { double evaluate(double x); a) Implementera metoden getzero med rekursiv teknik. b) Skriv en klass som implementerar interfacet Function och som motsvarar funktionen e x 1 + cos(x). c) Skriv programrad/rader som beräknar nollstället för funktionen e x 1 + cos(x) i intervallet [0, 1.6] med noggrannheten 0.00001.

Rekursion 27 U 65. Vid implementeringen av en listklass har man tänkt använda följande klasser: public class SingleLinkedList<E> { private ListNode<E> first; public SingleLinkedList() { first = null;... private static class ListNode<E> { private E element; private ListNode<E> next; private ListNode(E e) { element = e; next = null; Listan ska alltså implementeras med en enkellänkad struktur. Den första metod som implementeras i listklassen är en metod för insättning. Följande rekursiva utformning föreslås: public void add(e x) { add(first, x); private void add(listnode<e> node, E x) { if (node == null) { node = new ListNode<E>(x); else { add(node.next, x); Vid test visar det sig att detta inte fungerar alls. Förklara varför. Ändra också implementeringen så att den blir korrekt (och fortfarande är rekursiv). Kritisk granskning av rekursiva lösningsförslag I Proceedings of The 7th Annual Conference on Innovation and Technology in Computer Science Education Aarhus, Denmark June 2002 finns en artikel med titeln The Case of Base Cases: Why are They so Difficult to Recognize? Student Difficulties with Recursion av Bruria Haberman och Haim Averbuch. Genom att samla in studenters rekursiva lösningar på olika problem beskrivs hur författarna försökte göra sig en bild av vilka misstag som var vanligast. Inte bara felaktiga lösningar var i detta sammanhang intressanta utan också sådana som är onödigt komplicerade. Låt oss knyta an till detta genom att studera de rekursiva lösningsförslagen (pseudokod) till några problem i uppgifterna U66 67. Försök i första hand för varje lösning avgöra om den är korrekt eller ej. För lösningar som du anser korrekta kan du sedan gå vidare och ge ytterligare synpunkter t ex om de kan förenklas eller göras elegantare.

28 Rekursion U 66. Granska fyra följande förslag för att rekursivt beräkna n!: a) fac(n) om n == 0 return 1 annars return n*fac(n-1) b) fac(n) om n==0 return 1 annars om n == 1 return 1 annars return n*fac(n-1) c) fac(n) om n==1 return 1 annars return n*fac(n-1) d) fac(n) return n*fac(n-1) U 67. Granska följande två förslag till att undersöka om elementet x ingår i en lista. (list.tail() används för att beteckna den lista som består av alla element utom det första i list): a) ismember(x,list) om list är tom return false annars om x == första elementet i list return true annars return ismember(x,list.tail()) b) ismember(x,list) om x == första elementet i list return true annars return ismember(x,list.tail()) Rekursiva algoritmer effektivitet U 68. I denna uppgift behandlas problemet att beräkna största talet i en vektor med n heltal (n 1). Följande implementering föreslås: /** Tag reda på vilket av de n första elementen i v som är störst. */ public static int findmax(int[] v, int n) { if (n == 1) { return v[0]; else if (v[n-1] > findmax(v, n-1)) { return v[n-1]; else { return findmax(v, n-1); Denna algoritm är mycket ineffektiv. Förklara varför. Det går att göra en väsentligt effektivare rekursiv implementering genom en enkel ändring. Utför ändringen och ange sedan tidskomplexiteten.

Rekursion 29 U 69. Vad är dynamisk programmering och vad har man det till. U 70. Följande båda algoritmer (pseudokod) föreslås för att skriva ut elementen i en enkellänkad lista i omvänd ordning. Jämför algoritmerna med avseende på enkelhet (att förstå och implementera) och effektivitet. Algoritm1 : (letar först upp sista elementet, sedan näst sista etc...) leta upp sista noden i listan och låt q referera till denna så länge q!= null skriv ut innehållet i q; om q = första noden i listan, avbryt p = första noden i listan: så länge p.next!= q p = p.next; q = p; Algoritm2 (rekursiv, skriver ut innehållet i den lista som n refererar till i omvänd ordning) public void printreverse(listnode n) om (n!= null) printreverse(n.next); skriv ut innehållet i n;

30 Träd, binära träd 8 Träd, binära träd Tema: Träd, binära träd. Litteratur: Avsnitt 6.1 6.3 (8.1 8.4 i gamla upplagan) samt bilderna från föreläsningarna 8. U 71. Jämför följande två förslag (i pseudokod) att räkna antal noder i ett binärt träd med roten n. Är de korrekta eller ej. Kan de förenklas? a) count(n) om n == null return 0 annars om n.left == null && n.right == null return 1 annars om n.left == null return 1 + count(n.right) annars om n.right == null return 1 + count(n.left) annars return 1 + count(n.left) + count(n.right) b) count(n) om n == null return 0 annars return 1 + count(n.left) + count(n.right) U 72. Antag att vi har följande klass som representerar ett binärt träd: public class BinaryTree<E> { private Node<E> root; // övriga metoder /** Skriver ut trädets noder i inorder. */ public void printinorder() { printinorder(root); private void printinorder(node<e> n) {... private static class Node<E> { private E element; private Node<E> left; private Node<E> right; private Node(E data) { this.element = data; left = right = null; a) Implementera färdigt den privata, rekursiva metoden printinorder. b) Hur förändras lösningen till uppgift a om man istället vill skriva ut elementen i preorder respektive postorder?

Träd, binära träd 31 U 73. a) Lägg till en metod nbrleaves() i klassen BinaryTree som returnerar antal löv i trädet. Låt den publika metoden nbrleaves anropa en privat rekursiv metod nbrleaves(node<e> n) som returnerar antal löv i det träd där n är rot. b) Lös samma uppgift som i deluppgift a men placera den rekursiva metoden i nodklassen. U 74. Ett aritmetiskt uttryck som består av tal och de fyra binära operatorerna +, -, * och / kan representeras av ett binärt träd där löven innehåller talen och övriga noder innehåller operatorer. Exempel: + * 7 5-9 2 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 /** Returnerar en teckensträng som representerar uttrycket. Teckensträngen innehåller parenteser runt alla deluttryck, utom runt talen. */ public String fullparen(); 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 // konstruktor och övriga metoder Implementera metoden fullparen med rekursiv teknik. Om uttrycksträdet ser ut som i exemplet ska följande teckensträng returneras: ((5*(9-2))+7) U 75. Här är ett annat exempel på ett träd. En katalog (eng: directory) är en fil som kan innehålla andra filer och kataloger. Se exempel: ~dt08nn Mail kurser dokument fil progr pfk fil1 fil2 fil3

32 Träd, binära träd Din uppgift är att implementera metoden /** Returnerar en lista med alla vanliga filer i file som är större än size bytes. */ public static List<File> biggerthan(file file, int size) { File är en klass i Java som representerar en fil eller en katalog. Klassen har bland annat följande metoder: /** Returnerar true om filen är en vanlig fil. */ boolean isfile(); /** Returnerar true om filen är en katalog. */ boolean isdirectory(); /** Returnerar längden (i bytes) om aktuell fil är en vanlig fil. I annat fall returneras ett ospecificerat värde. long length(); /** Returnerar en vektor med filer om aktuell fil är en katalog. Om aktuell fil är en vanlig fil returneras null. File[] listfiles(); U 76. Beskriv hur man kan gå tillväga för att behandla noderna i ett binärt träd nivå- för nivå (dvs. först roten, sedan rotens barn, barnbarn...)? Tips! Använd en kö.

Binära sökträd 33 9 Binära sökträd Tema: Binära sökträd, interfacet Comparable. Litteratur: Avsnitt 6.4 och 9.1 9.2 (8.4 och 11.1 11.2 i gamla upplagan) samt bilderna från föreläsning 9. U 77. Visa hur ett binärt sökträd ser ut efter insättning av element med följande nycklar: 2, 5, 1, 7, 9, 6, 3, 0, 8, 4. U 78. I vilken ordning besöks noderna i trädet från uppgift U 77 om man traverserar det preorder, inorder repektive postorder. Vilken traverseringordning ska man använda om man vill behandla noderna i växande ordning? U 79. Vilken är den minsta möjliga resp. största möjliga höjden i ett binärt sökträd med n stycken noder? U 80. Kan man använda ett binärt sökträd som hjälp för att sortera ett stort antal element? U 81. Antag att vi har följande klasser för att representera ett binärt sökträd: public class BinarySearchTree<E extends Comparable<? super E>> { private Node<E> root; // metoder för insättning, borttagning,... private static class Node<E extends Comparable<? super E>> { private E element; private Node<E> left; private Node<E> right; private Node(E element) { this.element = element; Lägg till en metod tostring() i klassen BinarySearchTree. Metoden ska returnera en sträng med innehållet i trädet i växande ordning. Elementen i trädet ska i strängen separeras med ett newline-tecken ( \n ). U 82. Lägg till följande metod i klassen BinarySearchTree: public void printpart(e min, E max); Metoden ska skriva ut innehållet i de noder som är större än eller lika med min och mindre än eller lika med max i växande ordning. Använd rekursiv teknik och undvik att besöka fler noder än nödvändigt. U 83. Vad innebär det att ett binärt sökträd är balanserat? Varför vill man balansera binära sökträd?

34 Binära sökträd Implementera interfacet Comparable U 84. Antag att vi ska lagra böcker i ett binärt sökträd av typen BinarySearchTree från uppgift U 81. En bok beskrivs av följande klass: public class Book { private String isbn; private String title; private String author; public Book(String isbn, String title, String author) { this.isbn = isbn; this.title = title; this.author = author; a) Vad händer om vi försöker deklarera och skapa ett binärt sökträd enligt följande: BinarySearchTree<Book> books = new BinarySearchTree<Book>(); b) En bok identifieras av sitt ISBN-nummer. Ändra i klassen Book så att den implementerar interfacet Comparable.

Hashtabeller 35 10 Hashtabeller Tema: Hashtabeller. Litteratur: Avsnitt 7.3 (9.3 i gamla upplagan), bilder från föreläsning 10. U 85. Ett antal objekt med ett heltalsattribut nbr ska sättas in i en hashtabell av storlek 10. Objekten har följande värden på nbr: 4371, 1323, 6173, 4199, 4344, 9679, 1989. Använd hashfunktionen h(x) = (x.nbr) % 10. Visa tabellens utseende efter insättningarna i följande tre fall genom. Ange alltså för varje upptagen plats i tabellen nbr-värdet för det objekt som placerats där. a) Linjär teknik används vid kollisioner b) Kvadratisk teknik används vid kollisioner c) En öppen hashtabell används (separate chaining) U 86. Ett stort antal person-objekt ska lagras i en hashtabell. Som hashfunktion väljs de två första siffrorna i personens personnummer. Förklara varför detta är olämpligt och beskriv hur man ska göra istället.

36 Mängder och mappar 11 Mängder och mappar Tema: Abstrakta datatyperna mängd (eng. set) och map (lexikon), användning av Javas interface Set och Map samt motsvarande konkreta klasser. Litteratur: Avsnitt 7.1 7.2, 7.4 7.5 (9.1 9.2, 9.4 9.5 i gamla upplagan), bilder från föreläsning 9-10. Abstrakta datatyperna mängd och map. U 87. Vad utmärker den abstrakta datatypen mängd (eng. Set)? Nämn hur man effektivt kan implementera en mängd. U 88. Beskriv kortfattat vad som utmärker den abstrakta datatypen lexikon (eng. Map)? Vilka är de viktigaste operationerna? Beskriv olika sätt att implementera ett lexikon (map). U 89. I java.util finns klasserna TreeSet och TreeMap som implementeras med hjälp av binära sökträd. I dokumentationen till dessa klasser talas det om att element jämförs enligt deras natural order. Vad menas med det? U 90. Antag att vi ska använda en av klasserna i Java Collections Framework för att hålla reda på böcker. En bok beskrivs av följande klass: public class Book { private String isbn; private String title; private String author; public Book(String isbn, String title, String author) { this.isbn = isbn; this.title = title; this.author = author; a) Vi vill snabbt snabbt kunna hitta en bok med hjälp av dess ISBN-nummer och väljer klassen HashMap. Skriv programrader för att skapa ett HashMap-objekt att lagra böcker i och för att sätta in ett par (påhittade) böcker i bokregistret. Gör också de eventuella förändringar som behövs i klassen Book. b) I ett annat sammanhang vill man lagra böcker i ett HashSet-objekt. Skriv programrader som skapar ett HashSet-objekt att lagra böcker och sätter in ett par (påhittade) böcker i mängden. Gör också de eventuella förändringar som behövs i klassen Book. U 91. Beskriv kort vad som händer vid sökning efter en bok i hashtabellen i uppgift U 90b, dvs. vad som görs i metoden contains i klassen HashSet. Redogör i beskrivningen för hur metoderna equals och hashcode används vid sökningen. U 92. Vi ska fortsätta arbeta med klasserna från uppgift U 90. a) Antag att vi istället för en hashtabell vill använda ett binärt sökträd. Vi byter därför ut HashMap mot TreeMap i uppgift U 90 a. Behövs det några ändringar i klassen Book? b) Vilken klass är att föredra, HashMap eller TreeMap, om antal böcker är stort och det är viktigt att sökningarna går snabbt?

Mängder och mappar 37 Tillämpningar U 93. Antag att du har fått i uppgift att skriva ett program som läser en textfil, som är indelad i sidor, och ska producera en s.k. korsreferenslista över innehållet. En korsreferenslista är en lista över alla förekommande ord i alfabetisk ordning och för varje ord en uppräkning av de sidor där ordet förekommer. Exempel: alla 1, 2, 5, 8, 19 att 3, 5, 7, 9 bara 2, 6, 7, 9 bo 5, 19 del 6 Sidnumren för varje ord ska vara ordnade i stigande följd. Även om samma ord finns flera gånger på samma sida ska sidnumret bara förekomma en gång. Beskriv med ord hur man kan lösa problemet. I din beskrivning ska det framgå vilka algoritmer och datastrukturer som ska användas för att producera korsreferenslistan. Ange också om du kan använda någon eller några av de klasser i Java Collections Framework du träffat på under kursen. Du kan anta att det finns en operation som hämtar nästa ord tillsammans med aktuellt sidnummer från filen. U 94. En grupp av ord är anagram om de kan bildas av varandra genom att ändra ordningen på de ingående bokstäverna. T.ex. är de svenska orden avig och viga anagram till varandra. Ett bra sätt att hålla reda på anagram är att använda en map där värdena består av mängder med ord som är anagram till varandra. Som nycklar i mappen använder man den sträng man får om man sorterar bokstäverna i alfabetisk ordning. Om vi t.ex. skulle sätta in orden avig, och viga i en sådan (från början tom) map så skulle följande inträffa: När ordet avig ska sättas in bildar vi först en sträng genom att sortera bokstäverna. Vi får då agiv. Denna nyckel finns inte i tabellen (som är tom). Den sätts då in med sitt tillhörande värde, mängden [ avig ]. När viga ska sättas in bildar vi den sorterade strängen som igen blir agiv. Denna nyckel finns och då läggs det nya ordet till dess värde som nu blir mängden [ avig, viga ]. a) Implementera klassen Anagram som håller reda på ord och dess anagram: public class Anagram { private Map<String, Set<String>> anagrams; /** Skapar ett objekt som hanterar anagram. */ public Anagram() { // Fyll i egen kod. /** Lägger till order word. */ public void add(string word) { // Fyll i egen kod. /** * Returnerar en mängd med alla ord som är anagram till ett visst ord. * word ska inte ingå i den mängd som returneras. Om word inte har

38 Mängder och mappar * några insatta anagram ska en tom mängd returneras. */ public Set<String> getanagramsof(string word) { // Fyll i egen kod. /** * Returnerar en sträng med bokstäverna i word sorterade i * bokstavsordning. */ private String alphabetize(string word) { // Färdig att använda. b) Vilken tidskomplexitet får metoden add i medelfall? Du kan anta att orden innehåller rimligt antal bokstäver och att metoden alphabetize därför har konstant tidskomplexitet.

Prioritetsköer, heapar 39 12 Prioritetsköer, heapar Tema: Prioritetsköer, implementering av prioritetsköer med hjälp av heap, användning av Javas klass PriorityQueue och interfacen Comparable och Comparator. Litteratur: Avsnitt 6.5 (8.5 i gamla upplagan), bilderna från föreläsning 11. Prioritetsköer U 95. Vad är en prioritetskö. Hur skiljer den sig från en vanlig kö? Vilka är de vanligaste operationerna på en prioritetskö. Heapar U 96. Visa hur heap ser ut efter insättning av element med följande nycklar: 2, 5, 1, 7, 9, 6, 3, 0, 8, 4. U 97. En heap implementeras ofta med hjälp av en vektor. Beskriv hur. Visa med en figur hur vektorn som motsvarar heapen från uppgift U 96 ser ut. U 98. Beskriv kortfattat hur borttagning av minsta elementet i en heap (poll) går till. U 99. I en prioritetskö kan det finnas flera element med samma prioritet. Ibland vill man, vid lika prioritet mellan flera element, vara säker på att elementen kommer att hämtas ut ur kön i den ordning de sattes in. Annorlunda uttryckt: vid lika prioritet vill man att det element som väntat längst tas ut först. Implementeringar av en prioritetskö som uppfyller detta villkor brukar kallas stabila. a) Visa att heapen inte är en stabil implementering av en prioritetskö. Gör detta genom att, med ett enkelt exempel, visa att lika element inte tas ut i den ordning de satts in. b) Finns det något användare kan göra som gör att elementen kommer ut ur heapen enligt ovan? U 100. Går det bra att använda en heap om vi ofta vill söka efter ett godtyckligt element? U 101. Vektorn är en lämplig representation av en binär heap eftersom en sådan är fylld på alla nivåer utom möjligen den som ligger längst bort från roten. På denna sista nivå ligger dessutom noderna samlade längst till vänster. Vektorrepresentationen av en binär heap med n noder kan därför utnyttja platserna 0..n-1. Roten placeras på plats 0 och barnen till nod på plats i finns på platserna 2i + 1 och 2i + 2. Föräldern till noden på plats i finns på plats (i 1)/2. a) Vektorn är inte lika lämplig som representation av binära träd i allmänhet. Tänk efter hur stor vektor som i värsta fall skulle krävas för att representera ett binärt träd med n noder i följande två fall trädet är skevt, dvs. har maximal höjd trädet är fyllt av noder på nivåerna 1..k och har dessutom en nod på nivå k+1 b) Den vanliga länkade strukturen för binära sökträd är inte så lämplig att använda för implementering av en binär heap bl a eftersom det är svårare än i en vektor att ange platsen för nästa insättning. Ett sådant träd representeras ju i princip av en referens till roten och det gäller då att beskriva hur man ska gå nedåt i trädet för att hamna på den plats där nästa insättning får göras. Finns det något sätt att beskriva denna väg? Tips: studera förhållandet mellan den binära talrepresentationen av antalet noder i trädet och vägen från roten till rätt plats.

40 Prioritetsköer, heapar Andra sätt att implementera prioritetsköer U 102. En prioritetskö implementeras ofta med en heap. Diskutera andra sätt att implementera en prioritetskö. Fördelar, nackdelar? U 103. För specialfallet att element har prioriteter som är heltal i ett visst intervall [i..j] så kan man implementera en prioritetsköklass där alla operationer har tidskomplexitet O(1) och där dessutom prioritetskön är stabil. Förklara hur. Klassen PriorityQueue och interfacet Comparable, statiska attribut U 104. Javas klass PriorityQueue ska används för att hålla reda på patienter som väntar på en akutmottagning. Varje patient tilldelas en prioritet, som är ett positivt heltal. Ett lågt värde på detta attribut motsvarar hög prioritet. Patienter representeras av följande klass: public class Patient { private String firstname; private String lastname; private String personnbr; private int prio; public Patient(String firstname, String lastname, String personnbr, int prio) { this.firstname = firstname; this.lastname = lastname; this.personnbr = personnbr; this.prio = prio; a) Se till att klassen implementerar gränssnittet Comparable. Det är patienternas prioritet som ska jämföras. Men på akutmottagningen vill man dessutom att patienter med lika prioritet ska behandlas i den ordning de kommit till mottagningen, dvs. den som väntat längst ska behandlas först. För att kunna garantera detta, oavsett vilken implementering av prioritetskö man använder, tänker man göra följande ändringar: Patientobjekt numreras. Det första objekt av klassen Patient som skapas får nummer 1, det andra nummer 2 etc. Tips! Använd ett statiskt attribut för att hålla reda på numret. Jämförelsen mellan patienter modifieras så att det vid lika värde på attributet prio är objektets nummer som avgör vilket objekt som är minst. Låt klassen Patient implementera Comparable enligt dessa förutsättningar. b) Skriv programrader som skapar ett objekt av Javas klass PriorityQueue för att lagra patienter och lägger in några påhittade patienter i prioritetskön. Interfacet Comparator U 105. Antag att klassen Patient i uppgift U 104 redan implementerar gränsnittet Comparable och att det där är personnummren som jämförs. a) Se till att man ändå kan använda klassen PriorityQueue för att lagra patienterna i prioritetsordning. Lös detta problem utan att ändra implementeringen av metoden compareto i klassen Patient. Tips! Skriva en klass som implementerar gränssnittet Comparator. b) Gör nödvändiga ändringar i programkoden från uppgift U 104 b.

Prioritetsköer, heapar 41 Tillämpningar med prioritertskö U 106. I den här uppgiften ska vi se närmare på några klasser som är tänkta att användas i ett program för att administrera aktiehandel. Programmet är under utveckling och till att börja med finns följande klasser: public class Customer { private String id; /** Skapar en kund som kan handla med aktier. */ public Customer(String id) { this.id = id; public class Order { private double price; private Customer customer; /** Skapar en köp- eller säljorder för en aktie med budpriset price och köpare/säljare customer. */ public Order(double price, Customer customer) { this.price = price; this.customer = customer; /** Returnerar köp/säljbudet för aktien. */ public double getprice() { return price; För enkelhets skull antar vi att en köp- respektive säljorder gäller en aktie. a) För att hålla reda på köp- och säljordrar för ett visst aktieslag används en klass OrderQueues: Ett aktieslag representeras helt enkelt av en specifik kod, t.ex. ABCD. public class OrderQueues { private String shareid; private PriorityQueue<Order> buyorders; private PriorityQueue<Order> sellorders; // sorterad efter avtagande pris // sorterad efter växande pris /** * Skapar ett objekt som hanterar en kö för köpordrar och en kö för * säljordrar för aktien med id shareid. * @param shareid aktieslag */ public OrderQueues(String shareid) { // Fyll i egen kod här. /** * Lägger till en köporder ifall matchande säljorder inte finns. * Om matchande säljorder finns tas säljordern bort och returneras. * @param buyorder köporder * @return matchande säljorder om sådan finns, i annat fall null */ public Order addbuyorder(order buyorder) { // Fyll i egen kod här.

42 Prioritetsköer, heapar /** * Lägger till en säljorder ifall matchande köporder inte finns. * Om matchande köporder finns tas köpordern bort och returneras. * @param sellorder säljorder * @return matchande köporder om sådan finns, i annat fall null */ public Order addsellorder(order sellorder) { // Ingår ej i uppgiften att implementera. // Blir liknande kod som i addbuyorder. Observera att: Köpordrarna ska vara sorterade efter avtagande pris. Säljordrarna ska vara sorterade efter växande pris. När någon vill lägga en köporder ska man först undersöka om den matchar en tidigare inlagd säljorder. Detta inträffar om köpbudet är större än eller lika med lägsta säljbud. Implementera konstruktorn och metoden addbuyorder i klasen OrderqQueues. Gör också de ändringar i befintliga klasser/tillägg av nya klasser som krävs för att köerna ska fungera som avsett. b) Själva aktiehandeln sköts i klassen ClearingHouse där attributet q håller reda på orderköerna för alla aktieslag. Implementera metoden buy. public class ClearingHouse { private Map<String, OrderQueues> q; /** Skapar ett objekt som hanterar aktiehandel. */ public ClearingHouse() { q = new TreeMap<String, OrderQueues>(); /** * Låter kunden customer lägga en köporder av aktieslaget shareid till * budpriset price. Genomför köpet om matchande säljorder finns, i annat * fall lagras köpordern i motsvarande orderkö. * @param customer kunden * @param shareid aktieslag * @param price budpris * @throws NoSuchElementException om det inte finns någon orderkö för * aktieslaget shareid. */ public void buy(customer customer, String shareid, double price) { // Fyll i egen kod. /** Genomför affären med ordrarna buyorder och sellorder. */ private void execute(order buyorder, Order sellorder) { //Färdig att använda // övriga metoder i klassen c) Vad får metoden addbuyorder för tidskomplexitet?

Sortering 43 13 Sortering Tema: Sorteringsalgoritmer. Litteratur: Avsnitt 1 8.1 8-2, 8.4 8.5, 8.7 8.9 (10.1 10.2, 10.4 10.5, 10.7 10.9 i gamla upplagan), bilderna från föreläsning 12. U 107. Avgör för var och en av följande sorteringsalgoritmer om de kan dra fördel av att indata består av en vektor med n lika tal. Det du ska avgöra är om respektive algoritm blir väsentligt effektivare i ett sådant specialfall än vad den normalt är. a) Insättningssortering b) Mergesort c) Heapsort d) Quicksort, med pivot = median av tre U 108. Tre personer har behov att sortera indata bestående av n element. De kan välja mellan de sorteringsmetoder som ingått i vår kurs. Det gäller lite olika förutsättningar för deras indata: 1. Person 1 är egentligen bara intresserad av att veta vilka som är de k minsta nycklarna, där k är väsentligt mindre än n. 2. Person 2 har indata som oftast är nästan sorterade från början. 3. Person 3 har inga speciella förutsättningar. Ge förslag på lämplig sorteringsalgoritm för var och en av de tre personerna. Motivera valen av algoritm. U 109. Antag att en vektor int[] v är fylld med tal. Sortera vektorn genom att använda någon lämplig metod bland Javas färdiga sorteringsmetoder. Vilken sorteringsalgoritm används i den metod du valt? (Se Javas dokumentation på nätet.) U 110. Effektiva sorteringsalgoritmer används ibland som en slags förbehandling i algoritmer för olika problem. Förklara (i ord, inte programkod) hur sortering kan utnyttjas för att konstruera effektiva algoritmer för följande problem: a) Ta bort alla dubbletter ur en vektor med n tal. b) Givet två vektorer med n tal vardera. Ingen av vektorerna innehåller dubbletter, däremot kan tal som finns i ena vektorn också finnas i den andra. Slå samman talen till en vektor av tal så att alla tal som fanns i någon av vektorerna finns med i den nya vektorn och så att den nya vektorn inte innehåller några dubbletter. c) Givet ett tal x och en vektor m innehållande n tal. Avgör om det finns två tal i m vars summa är x. Visa också att om talen är sorterade från början så kan man lösa problemet på linjär tid. U 111. Lägg till följande metod i klassen OrderedList från uppgift U 35, övning 4. Elementen i listan bör inte gås igenom onödigt många gånger. /** Samsorterar den här sorterade listan med listan other. Resultatet hamnar i den här listan och listan other blir tom. */ public void merge(orderedlist<? extends E> other);

44 Sortering U 112. Implementera följande metod som med liknande teknik som i quicksort effektivt tar reda på det i:te elementet i storleksordning i en vektor a: /** Sök upp det i:te elementet i storleksordning i vektorn a. */ public static <T extends Comparable<? super T>> T findith(t[] a, int i); Du har tillgång till följande färdigskrivna metod: /** Partitionera elementen i a[first]..a[last]. Den plats pivot-elementet hamnar på returneras. Metoden klarar av delvektorer ned till en storlek av ett element. */ public static <T extends Comparable<? super T>> int partition (T[] a, int first, int last);