Ö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)

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

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

Föreläsnings 10 - Överlagring, Konstruerare, Arv, Mer Exceptions, Reguljära Uttryck

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

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

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

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

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

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

Repetition av OOP- och Javabegrepp

DAT043 - föreläsning 8

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 2 Innehåll

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

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

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

Listor. Koffman & Wolfgang kapitel 2, avsnitt , och 2.9

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

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

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