TENTAMEN
TENTAMEN
TENTAMEN
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Institutionen för Kommunikation och Information<br />
Kurs:<br />
Delkurs:<br />
Kurskod:<br />
Datum:<br />
Ansvarig lärare:<br />
Berörda lärare<br />
Hjälpmedel/<br />
Bilagor:<br />
Övrigt:<br />
Anvisningar<br />
<strong>TENTAMEN</strong><br />
Algoritmer och Datastrukturer<br />
DA114G<br />
2010-01-14<br />
Gunnar Mathiason<br />
Högskolepoäng: 7.5 hp<br />
Ta nytt blad för varje lärare (endast för lärare på IVN)<br />
Ta nytt blad för varje ny fråga<br />
Skriv endast på en sida av papper.<br />
Använd inte röd penna.<br />
Skriv namn och personnummer på samtliga inlämnade blad.<br />
Numrera lösbladen löpande.<br />
Markera med kryss på omslaget vilka uppgifter som är lösta.<br />
Skrivtid: 14:30-19:30<br />
Poänggränser Examination sker utfrån kursmålen. En fråga på varje mål kan ge max 10 p.<br />
För godkänt krävs minst 5 p på alla frågor utom en.<br />
För betyg 4 krävs minst 7 p på alla frågor utom en.<br />
För betyg 5 krävs minst 9 p på alla frågor utom en.<br />
Skrivningsresultat bör offentliggöras inom 18 arbetsdagar<br />
Lycka till!<br />
Sidan 0(6)
Tentamen har 4+2 sidor (inklusive en bilaga).<br />
Alla svar skall motiveras väl, d.v.s. det räcker inte med ett faktasvar. Enbart en faktauppgift<br />
(exempelvis, ett tal eller en benämning) är aldrig tillräckligt. Om en fråga verkar oklar, ange din<br />
egen tolkning först i ditt svar på frågan.<br />
Denna tentamen examinerar utifrån kursmålen, där det avgivna svaret värderas mot varje<br />
kursmål. Svaret för varje kursmål poängbedöms 1-10.<br />
• Kursmål 1: Användning av komplexitetsteori.<br />
• Kursmål 2: Användning av grundläggande datastrukturer.<br />
• Kursmål 3: Användning sorteringsalgoritmer.<br />
• Kursmål 4: Användning av grafer och tillämpliga algoritmer.<br />
• Kursmål 5: Användning av generella principer för algoritmdesign: giriga algoritmer,<br />
söndra och härska, dynamisk programmering, samt backtracking.<br />
• (Kursmål 6: Examineras i laborationsuppgiften, inte i denna tentamen).<br />
Frågor:<br />
1. [Kursmål 1]<br />
Algoritmanalys.<br />
a. Komplexitetsbegrepp<br />
i. Beskriv vad O() ‐begreppet (Big‐Oh) innebär i algoritmanalys. Varför är detta<br />
begrepp så viktigt vid konstruktion av en algoritm?<br />
ii. Hur skiljer sig O() från Ω() (dvs. Big‐Omega) och Θ() (dvs. Big‐Theta)?<br />
iii. Som komplexitetsuttryck används ofta en grov uppskattning. Vilka två grova<br />
antaganden gör man ofta för att få fram ett enklare komplexitetsuttryck?<br />
Varför gör man detta? Tips: Man är ute efter att veta hur komplexiteten<br />
växer med problemets storlek.<br />
1
. Grenanders problem (“Maximum Sub Sequence Problem”). Se följande<br />
implementation av algoritmen, vilken har logaritmisk tidskomplexitet.<br />
2. [Kursmål 2]<br />
int grenander4(int a[], int l, int h) {<br />
if (l > h) return 0;<br />
if (l == h) return max(0, a[l]);<br />
int m = (l + h) / 2;<br />
int sum = 0;<br />
int maxLeft = 0;<br />
for (int i = m; i >= l; i‐‐) {<br />
sum += a[i];<br />
maxLeft = max(maxLeft, sum);<br />
}<br />
sum = 0;<br />
int maxRight = 0;<br />
for (int i = m + 1; i
. Köer<br />
i. Jämför två olika implementationer av köer, dels som array och dels som<br />
länkad lista. Motivera skillnaden i deras komplexitet för de följande<br />
operationerna:<br />
insert(a), (insättning av element a i kö:n)<br />
remove(a), (hämta ut och ta bort element a ur kö:n)<br />
n=lookupElementIndex(a), (returnera element a på position n)<br />
där a är ett element och n är en position i kö:n.<br />
c. Binära sökträd<br />
i. Beskriv ett allvarligt problem med binära träd och vad konsekvenserna blir<br />
när det uppträder.<br />
ii. Beskriv angreppssättet hur man ofta löser detta. Ge exempel på två kända<br />
algoritmer som försöker lösa detta problem och principen för hur detta görs.<br />
d. Sentinels<br />
i. Vad är meningen med en sentinel?<br />
ii. Vad är en sentinel‐nod och när används detta?<br />
3. [Kursmål 3]<br />
Sorteringsalgoritmers komplexitet.<br />
a. Jämför en sorteringsalgoritm med tidskomplexiteten O(n log n) med en<br />
sorteringsalgoritm med tidskomplexiteten O(n 2 ).<br />
Detta är en essäfråga, besvara frågan utförligt och noggrant.<br />
i. Basera analysen på komplexiteten för de olika operationerna som ingår.<br />
ii. Vilken del bidrar med största beräkningskomplexiteten?<br />
iii. Jämför hur enkelt/svårt de båda sorteringsalgoritmerna realiseras.<br />
Hur påverkas beräkningstiden av indatas beskaffenhet?<br />
Vad är värsta och bästa fallet?<br />
iv. Stabilitet, behålls en underliggande sorteringsordning?<br />
4. [Kursmål 4]<br />
Traversering av grafer<br />
a. Ge en algoritm, i pseudokod, som med hjälp av en kö och ett minne för besökta<br />
noder traverserar alla noderna i en graf enligt en bredden‐först‐ordning. Varje nod<br />
besöks alltså endast en gång.<br />
3
5. [Kursmål 5]<br />
Giriga algoritmer<br />
a. I ett kassasystem vill vi kunna ge tillbaka växel till en kund. Mynten vi har att tillgå<br />
är på 1, 5, 10 respektive 25 enheter. Problemet är nu att för ett godtyckligt<br />
växelbelopp välja ett antal mynt av de olika valörerna så att: 1) myntens<br />
sammanlagda värde exakt uppgår till det eftersökta växelbeloppet; 2) ett så litet<br />
antal mynt som möjligt används. Vi antar att det finns tillräckligt många mynt av<br />
varje valör.<br />
i. Använd pseudokod för att ge en utförlig beskrivning av en girig algoritm<br />
som löser ovanstående problem.<br />
ii. Antag att vi förutom valörerna ovan också har mynt som är värda 12<br />
enheter. På vilket sätt påverkar det din giriga lösning?<br />
iii. Har vi situationen ”ii” är det bättre att försöka lösa växlingsproblemet<br />
m.h.a. söndra och härska (divide‐and‐conquer). Använd pseudokod för att<br />
ge en utförlig beskrivning av en algoritm som löser växlingsproblemet med<br />
denna teknik.<br />
Ledning: Tänk rekursivt! Antingen så kan vi växla hela beloppet med<br />
endast ett mynt eller så kan vi (på något lämpligt sätt) dela upp<br />
växelbeloppet, växla delbeloppen med minimalt antal mynt rekursivt och<br />
sedan konstruera en fullständig lösning från dellösningarna.<br />
b. En naiv lösning för problemet med 12‐enhetersmyntet (”iii”) lider av ett problem<br />
som är vanligt hos söndra‐och‐härska algoritmer. Beskriv detta problem. Vilken<br />
generell lösning finns på problemet?<br />
4
BILAGA 1: Att beskriva algoritmer<br />
Ett schema för hur man kan beskriva en algoritm är följande:<br />
1. ge en informell algoritm (intutiv beskrivning)<br />
2. ge en abstrakt algoritm (i pseudokod)<br />
3. analysera egenskaper, framförallt tidskomplexitet<br />
4. förklara de datastrukturer som används<br />
5. förfina algoritmen stegvis.<br />
Nedan ges en mer utförlig beskrivning av de olika stegen.<br />
1. Förklara hur algoritmen fungerar<br />
Först måste man förklara varför (i vilken mening/på vilket sätt) algoritmen löser problemet i<br />
fråga. För att göra detta kan man med fördel använda både sig av både text och bild.<br />
Beskrivningen ska vara intuitiv och lättförstålig men samtidigt kortfattad och koncis (med fördel<br />
används en mer matematisk notation på lagom nivå). Ett bra sätt är ofta att göra en "torrsimning"<br />
på ett konkret exempel. Det väsentliga i detta första steg är att algoritmens idé framgår tydligt<br />
och att man får hjälp med att förstå den abstrakta algoritmen i nästa steg.<br />
2. Ge (beskriv) en abstrakt algoritm<br />
Detta är en programspråksliknande beskrivning (i pseudokod) där man kan använda ADT:er för<br />
t.ex. listor, matriser och grafer, samt satser (instruktioner) av typen "för varje nod n i grafen G<br />
gör" och "om x finns i listan L så". Denna beskrivning ska alltså så långt som möjligt vara<br />
programspråksoberoende.<br />
Det väsentliga i detta steg är att algoritmens struktur framgår tydligt, att man får en förståelse<br />
för hur algoritmen skulle kunna implementeras i ett (imperativt) programspråk.<br />
Om man använder resultatet från en känd algoritm, t.ex. binärsökning i en sorterad lista, så räcker<br />
det att man i detta steg bara beskriver hur resultatet ser ut (och nämner vilken algoritm man har<br />
använt för att beräkna det). Anpassar man en känd algoritm för att passa den algoritm man håller<br />
på att beskriva så måste den anpassade algoritmen beskrivas i sin tur (vilket görs efteråt).<br />
Men man får inte vara för abstrakt! Om man t.ex. arbetar med ett binärt träd och vill skriva ut alla<br />
löv i trädet så är inte "traversera trädet" en bra abstraktion. En bra tumregel är att de satser som<br />
man använder i detta steg ska vara så abstrakta som det går samtidigt som det direkt måste framgå<br />
att de är fullt möjliga att implementera. Om detta inte är uppenbart måste man visa hur man har<br />
tänkt sig att implementera dessa satser. Detta gör man i sådana fall efter den abstrakta algoritmen,<br />
inte i den.<br />
3. Analysera algoritmens komplexitet<br />
Här är det nästan alltid tidskomplexiteten som är det mest intressanta. Analysen behöver inte vara<br />
formell utan det handlar snarare om att ge en uppskattning av komplexiteten och om att ge en<br />
övertygande motivering för hur man kom fram till denna. I mer generell mening är syftet med<br />
detta steg att beskriva algoritmens egenskaper.<br />
5
4. Beskriv de olika delarna i den abstrakta algoritmen<br />
Här beskriver man t.ex. hur man implementerar de ADT:er som ingår i den abstrakta algoritmen,<br />
hur "för varje nod n i grafen G gör" utförs och hur eventuella hjälpalgoritmer (både kända och<br />
egenkonstruerade) fungerar. Kända hjälpalgoritmer behöver normalt bara beskrivas enligt<br />
punkterna 1- 2 ovan. Naturligtvis behöver man inte beskriva hur en länkad lista implementeras<br />
eller hur linjär sökning i en lista går till (såvida de inte har modifierats förstås).<br />
Syftet med detta steg är att ge ytterligare förståelse för att den abstrakta algoritmen verkligen kan<br />
implementeras, att ge grundläggande idéer till hur den abstrakta algoritmen kan implementeras,<br />
att ge ytterligare detaljer till en eventuell utförligare komplexitetsanalys samt, inte minst, att<br />
förbereda inför nästa steg.<br />
5. Implementera algoritmen<br />
Här beskrivs hur algoritmen implementeras i valt programspråk. Detta sker ofta genom stegvisa<br />
förfiningar av algoritmen, där man för varje steg implementerar fler och fler detaljer. Eventuellt<br />
ska alla detaljer implementeras (ska algoritmen kunna köras på en dator är ju detta en<br />
förutsättning). Observera att implementationen av en algoritm kan skilja sig markant från den<br />
abstrakta algoritmen. Ett komplett körbart program är inte målet här, det räcker med att<br />
implementera den del av programmet som utgörs av själva algoritmen.<br />
6