Tweede Toets Datastructuren 29 juni 2016, 13.30 15.30, Educ-Γ. Motiveer je antwoorden kort! Zet je mobiel uit. Stel geen vragen over deze toets; als je een vraag niet duidelijk vindt, schrijf dan op hoe je de vraag interpreteert en beantwoord de vraag zoals je hem begrijpt. Cijfer: Elke vraag levert evenveel punten, nl. 3, met een totaal van 18. T2 is punten plus 1, gedeeld door 1,8. 1. Verwijderen uit gelinkte lijst: In een doubly linked list heeft elke Node een key, prev en next. In een singly linked list ontbreekt de prev. (a) Geef een methode die Node y verwijdert uit een doubly linked list. (b) Geef een methode die Node y verwijdert uit een singly linked list. (c) Moet je y meegeven als ref parameter (zowel voor (a) als voor (b))? Leg uit! Oplossing: (a) Laat de voorganger van y wijzen naar de opvolger van y, en de opvolger naar de voorganger: y.prev.next = y.next; y.next.prev = y.prev;. Uitzonderingsgevallen af te handelen: als y de eerste of laatste Node is hoeft de aapassing van y.prev danwel y.next niet maar moet je misschien een externe pointer aanpassen. (b) Om dit te kunnen doen moet je y als ref argument geven. De methodeheader is dan void DelFirst(ref Node y) en in de methode gaat het als y = y.next;. (c) Zonder ref argument kun je in de singly linked niet bij de voorganger komen. In de doubly linked list kan dat wel en heb je y niet als ref nodig. (Je kunt wel de key en next van y s opvolger naar y kopiëren: y.key = y.next.key; y.next = y.next.next;. Dit kan natuurlijk niet als y de laatste knoop is.) Beoordeling/Toelichting: Tot 3pt; 1 per deelvraag. Codes: GR = Bij (c) zeggen dat t niet nodig is, als je bij (b) de lineaire oplossing hebt: toch punt. K = Nodes selecteren op basis van Key, 0pt. L = Oplossingen die superlineaire tijd kosten (bij b), 1/2pt. R = Bij (b) geen Ref gebruikt maar wel assignatie aan y, 0pt. Nog 1/2 terug te verdienen met argumentatie bij (c) dat die wel moet. U = De Uitzonderingsgevallen aan begin en einde van de lijst hoeven er niet bij voor puntentoekenning. V = Bij (c) moet je zien dat er Verschil is in deze situaties, dus je krijgt alleen een punt als je beide goed hebt, en niet een halve punt voor een goed.
2. Master Theorem: Bepaal de asymptotische oplossing van deze recurrenties met de Master Theorem. (a) V (n) = 2V (n/3) + 2n. (b) W (n) = W (n/3) + 1, 5 n. (c) X(n) = 3X(n/2) + O(n n). Oplossing: (a) Hier is a = 2, b = 3 en f(n) = 2n. b log a is ln 2/ ln 3 is 0,63. De f(n) is n 1 dus weegt polynomiaal zwaarder, zodat V (n) = Θ(n). (Ook als je niet weet hoe je de log uitrekent, kun je inzien dat 3 1 = 3, 2 is minder dus de log is minder dan 1.) (b) Hier is a = 1, b = 3 en f(n) = 1, 5 n. b log a is ln 1/ ln 3 is 0. De f(n) is exponentieel dus weegt sowieso zwaarder, zodat W (n) = Θ(1, 5 n ). (c) Hier is a = 3 en b = 2 en f(n) = O(n 1,5 ). b log a is ln 3/ ln 2 is 1,58. Dit is meer dan 1,5 dus is deze term polynomiaal meer dan f(n) zodat X(n) = Θ(n 1,58... ). Beoordeling/Toelichting: Een punt per goed antwoord; geen halve punten voor goedbedoelde deelredeneringen of half goed toegepaste stellingen en gevallen. Bij (c) moet je wel echt even de log kunnen uitrekenen om te zien dat hij meer dan 1,5 is. Als je kunt bedenken dat 2 1,5 hetzelfde is als 2 2, en weet dat dit ongeveer 2,8 is, dus minder dan 3, en kunt concluderen dat de log dus meer dan 1,5 is, dan had je die log waarschijnlijk ook wel kunnen uitrekenen. M = Niet met de Master Theorem gedaan. P = Er is wel een Polynomiale factor (namelijk n 0,08.. ) tussen n 1,5 en n 1,58... T = Of je Θ of O moet antwoorden is weer een heel verhaal. Bij deze vragen was in alledrie de gevallen Θ gerechtvaardigd, maar als je O opschreef was het ook goed. V = De Vorm, bv. O(2n), is niet goed (moet O(n) zijn), 1/2pt.
3. MinHeap: Deze vraag gaat over een MinHeap in een 1-based array A. In A staan deze getallen: (8, 48, 31, 20, 18, 33, 35, 30, 45, 21, 20, 35). (a) Welke veranderingen vinden plaats als Heapify(2) wordt aangeroepen? (b) Vervolgens wordt key 27 toegevoegd. Zeg wat er gebeurt en geef de heap na toevoeging. (c) Welke posities in een heap met n keys hebben geen kinderen, welke hebben 1 kind en welke hebben 2 kinderen? Oplossing: (a) De key op plaats 2, 48, wisselt met zijn kleinste kind 18 op plaats 5. Dan wordt Heapify(5) aangeroepen en wisselt 48 weer met zijn kleinste kind, 20 op positie 11. Dan wordt Heapify(11) aangeroepen maar positie 11 heeft geen kinderen en er gebeurt niets meer. Heap is dus: (8, 18, 31, 20, 20, 33, 35, 30, 45, 21, 48, 35) (b) Nieuwe keys worden toegevoegd op de eerste lege plek en dan wordt Rootify aangeroepen. Dus 27 komt op plek 13, en Rootify(13) laat hem wisselen met zijn parent op plek 6, 33, want dat getal is groter. De volgende Rootify(6) laat 27 wisselen met zijn parent 31 op plek 3 want die is groter. De volgende Rootify(3) doet niets meer omdat 27 groter is dan zijn parent 8. Heap dan: (8, 18, 27, 20, 20, 31, 35, 30, 45, 21, 48, 35, 33). (c) Kinderen van knoop i zijn 2i en 2i + 1 maar deze bestaan alleen als dat kleinergelijk n is. Elke positie i < n/2 heeft twee kinderen. Alleen als n even is, bestaat er een knoop met 1 kind en dat is n/2: linkerkind is n (bestaat) en rechterkind is n + 1 (bestaat niet). Posities groter dan n/2 hebben geen kinderen. Beoordeling/Toelichting: Tot 3pt, 1 voor elke deelvraag. A = Niet Algemeen genoeg (antwoord bv alleen voor n een tweemacht), 0pt. E = Geen onderscheid Even/oneven gemaakt. T = Grens tussen 0 of 2 kinderen ligt niet bij Tweemacht. V = Bij (b) staat Vervolgens, je moet dus toevoegen na het Heapifyen uit (a).
4. ContainsValue: Christa slaat records op die een (spelers) naam en een score bevatten. Zij wil kunnen invoegen/verwijderen/zoeken op naam, en zij heeft een efficiente ZoekSc(s) nodig die de naam oplevert van een speler met score s. (a) Christa overweegt opslag in een hashtabel met de naam als key. Hoe kan zij een ZoekSc(s) uitvoeren? (b) Hoeveel tijd kost de ZoekSc bij deze opslag (noem de lengte van de hashtabel m en het aantal records n)? (c) Kan Christa haar ZoekSc(s) sneller krijgen door de records in een zoekboom op te slaan? Leg uit. Oplossing: (a) Christa moet alle records enumereren en checken of s erin zit (en kan misschien eerder termineren als ze s vindt). (b) Voor een hashtabel met m plaatsen en n keys kost dit O(n + m) tijd, dus zeg lineair. (c) Een zoekboom is voor Christa niet beter. Je kunt wel meer met de keys waarop de boom geordend is, maar zoeken op een andere waarde kan niet efficienter dan lineair. Christa zal haar boom moeten ordenen op naam en dan kost zoeken op score lineaire tijd. (Christa kan het beste bij haar verzameling records, twee hashtabellen maken: eentje waarin gehasht wordt op de key en eentje waarin gehasht wordt op value. Alle vier de operaties kunnen dan in O(1) tijd. Beoordeling/Toelichting: Tot 3pt, 1 per deelvraag. Voor de beoordeling moet wel duidelijk zijn dat je het centrale probleem snapt: dat Christa wil zoeken op een veld dat niet de key van de datastructuur is. B = Een Boom is altijd trager dan een hashtabel omdat (door de aanpassing van m aan n) de α doorgaans begrensd blijft. C = Ze moet een ContainsValue doen, ja, ok, maar hoe moet dat dan? 0pt. E = Boom Enumereert sneller omdat je de lege velden niet hebt geeft maar 1/2pt. Bij normale load factor enumereren hashtabel en boom in lineaire tijd, en Θ(n) is nog steeds heel veel. H = Uitlag hoe Hashen normaal werkt (key afbeelden op getal en in array opzoeken) Werd niet gevraagd. L = Bij begrensde Load factor α zijn n en m asymptotisch gelijk en kun je Θ(n) of Θ(m) schrijven. N = Itereren over alle Namen kan niet zomaar in een hashtabel. S = Een zoekboom (of hashtabel) met Score als key is niet goed voor Christa omdat ze daarmee geen toegang meer heeft met een naam, 0pt.
5. Selectie uit Boom: Gegeven is een binaire zoekboom, geaugmenteerd met het aantal keys per deelboom. Elke knoop bevat een key, deelbomen left en right, en een integer size die het aantal keys in de deelboom geeft. Geef een recursieve methode KR(node b, int k) die uit boom b het element met rang k oplevert (dwz., het op k na kleinste element; je mag aannemen dat alle keys verschillend zijn en dat 0 k < b.size geldt). De methode moet recursief zijn en de tijd moet lineair zijn in de hoogte van de boom (dus O(h)). Oplossing: Als (k == b.left.size) is de key in b de goede. Bij kleinere k moet je naar links en bij grotere naar rechts. Wel moet je er even aan denken dat je bij recursie naar rechts, de waarde van k moet verlagen. De verzameling keys in de rechterdeelboom is namelijk de hele set, minus de keys links en die in de wortel, dus de rang binnen de rechterdeelboom is b.left.size+1 kleiner dan de rang in de hele boom. Als je een truuk hebt geprogrammeerd zodat null.size automatisch 0 oplevert, ziet het er zo uit: KR(node b, int k) { if (k == b.left.size) return b.key; if (k < b.left.size) return KR(b.left, k); else return KR(b.right, k - b.left.size - 1); } Je kunt lege linkerkant ook expliciet afhandelen: erop testen en dan bij k = 0 de wortel opleveren, anders naar rechts met rang k 1. Beoordeling/Toelichting: Tot 3pt. A = Vergeten of onjuiste aanpassing van k in recursie. Incorrect algo, 2pt aftrek. B = Je moet k niet vergelijken met B.size maar met b.left.size; incorrect, aftrek 1,5pt. D = Dit is te Duur, je gebruikt tijd lineair in het aantal keys, 2pt aftrek. G = Over balancering is niets Gegeven; bij fout algoritme -2pt. K = GebruiK notatie uit de opdracht ipv nieuwe namen te verzinnen. L = Niets gezegd over Lege Linkerkant, 1/2pt aftrek. N = Het geval b == Null afhandelen is mooi, maar hoeft niet. R = Je methode is niet Recursief, 1.5pt eraf. 6. Recurrente betrekking: Los op: a 0 = 1, a 1 = 1, a n = a n 1 + 6a n 2. Oplossing: De oplossing is a n = 2 5 ( 2)n + 3 5 3n of 2 ( 2)n +3 3 n. 5 Het Karakteristiek Polynoom is x 2 x 6 en de nulpunten hiervan zijn 2 en 3. Je verkrijgt dus de Algemene Oplossing a n = C ( 2) n + D 3 n. Invullen van de Randwaarde voor n = 0 geeft C +D = 1 en voor n = 1 geeft 2C +3D = 1. Uit die twee vergelijkingen haal je C = 2 en D = 3. 5 5 Beoordeling/Toelichting: Tot 3pt om dit perfect op te lossen. Heb je het KP met nulpunten 2 en 3, daarvoor 1pt. Heb je de vergelijkingen voor C en D opgesteld en goed opgelost, 1pt. Verdere lettercodes: C = Conclusie vergeten, 1pt. G = Je hebt de vraag niet beantwoord, we wilden een Gesloten formule voor a n.