Tweede Toets Datastructuren 26 juni 2019, 17.00 19.00, Educ-β. Motiveer je antwoorden kort! 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: Maak vraag 1 en 2 op de voorkant, vraag 3 en 4 op pagina 2 en vraag 5 en 6 op pagina 3. Vragen 1 en 4 zijn 3pt, de andere vragen 2pt. T2 is totaal plus 1 gedeeld door 1,4. 1. Master Theorem: Bepaal de asymptotische oplossing van deze recurrenties met de Master Theorem. Geef aan hoe je tot de oplossing komt. (a) V (n) = 4V (n/2) + 2n 2. (b) W (n) = W (n/2) + ( 3 2 )n. (c) X(n) = 2X(n/3) + O( n). Oplossing: (a) Hier is a = 4, b = 2 en f(n) = 2n 2. b log a is ln 4/ ln 2 is 2. De f(n) is n 2 dus evenveel, zodat V (n) = Θ(n 2 lg n). (b) Hier is a = 1, b = 2 en f(n) = 1, 5 n. b log a is ln 1/ ln 2 is 0. De f(n) is exponentieel dus weegt sowieso zwaarder, zodat W (n) = Θ(1, 5 n ). (c) Hier is a = 2 en b = 3 en f(n) = O(n 0,5 ). b log a is ln 2/ ln 3 is 0,63. Dit is meer dan 0,5 dus is deze term polynomiaal meer dan f(n) zodat X(n) = Θ(n 0,63... ). 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. A = Alleen juist antwoord zonder toelichting, 1/2. C = Overbodige Constante: bv. O(2n 2 lg n); 1/2pt. F = Een extra lg-factor betekent vermenigvuldigen met lg n, dus n 2 lg n en niet n 2 + lg n. H = Je moet 3 2 n met Haakjes schrijven! L = Je zegt wel n 3 log 2 maar die log is niet of fout uitgerekend. M = Niet met de Master Theorem gedaan. P = Er is wel een Polynomiale factor (namelijk n 0,13.. ) tussen n 0,5 en n 0,63... 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.
2. Hashing: Open Addressing: In een array A van lengte 13 worden integers opgeslagen met open addressing en hashfunctie h i (x) = (x + i (x%12 + 1))%13. (a) Geef de Probe Sequence (eerste zes waarden) van keys 144 en 146. (b) Na het invoegen van 144 en 146 wordt gezocht naar 94. Welke posities in de array worden bekeken en bij welke wordt geconcludeerd dat 94 er niet is? Oplossing: (a) Key 144 heeft rest 1 modulo 13 dus de reeks begint bij 1. Rest modulo 12 is 0 dus de stapjes zijn ook 1, de sequence is dus: 1, 2, 3, 4, 5, 6. Key 146 heeft rest 3 modulo 13 dus de reeks begint bij 3. Rest modulo 12 is 2 dus de stapjes zijn 3, de reeks is dus 3, 6, 9, 12, 2, 5. (b) De probe sequence van 94 is 3, 1, 12,... De zoekmethode vindt plek 3 bezet (door 146), plek 1 bezet (door 144), en plek 12 leeg, waarna het zoeken wordt geëindigd. Beoordeling/Toelichting: Per deelvraag 1pt. Codes: A = Het zoeken zal zeker niet Alle locaties bekijken! L = Je moest 6 waarden geven maar dat is niet de Lengte van de probe Sequence, het was een vrij willekeurige keuze. N = De Probe Sequence begint bij i = 0. Beginnen bij i = 1 is dus niet goed, maar maakt ook (b) makkelijker omdat je niet laat zien hoe het zoeken over bezette plaatsen gaat; zie ook Z. Z = Met verkeerde Probe Sequence laat je niet zien hoe Zoeken omgaat met bezette plaatsen.
3. Tree en InsertMax: Gegeven is een binaire zoekboom T, gebouwd uit Node objecten met een String key en (pointers naar) deelbomen Node left en Node right. Schrijf een methode InsertMax(ref Node t, String nk) die nk invoegt in de boom, en die alleen gebruikt wordt wanneer bekend is dat nk groter is dan alle al aanwezige keys. Oplossing: Als boom leeg is, vervang hem door een knoop met nk, en anders voeg in in de rechterdeelboom: public void InsertMax(ref Node t) { if (t == null) t = new Node(nk, null, null); else InsertMax(ref t.right, nk); } Het is een deel van de standaard Insert, waarbij alleen bij niet-lege t de vergelijking met de key in de wortel wordt overgeslagen. Beoordeling/Toelichting: Tot 2pt voor een mooi compact stukje code. Codes: B = Bovenin invoegen met t = new Node(nk, t, null); kan ook. E = De else bestaat niet voor niets! if (c) A; if (!c) B; is namelijk geen synoniem voor if (c) A; else B;. G = Instructie t = t.right Gooit wortel en Ldb weg. I = Invoegen niet (goed) uitgevoerd. K = Wil je een ref parameter gebruiken, dan beter niet Kopiëren. Anders dan bij value parameters, is me(ref a); niet te vervangen door b = a; me(ref b);, deze omweg verandert namelijk a niet! L = Crash op Lege boom door direct veld van t op te vragen. Test altijd op lege boom (t == null) voordat je in het object t kijkt! P = De strings Parsen werd niet om gevraagd. S = Strings kun je gewoon alfabetisch vergelijken, de aanname dat groter langer betekent is overbodig en onzinnig. T = Test op iets wat gegeven is (nieuwe string groter dan aanwezige). V = Door de ref kun je t Veranderen in de methode! Bijna niemand gebruikte dit.
4. Coupon Collector: Chocolade: Chris heeft gehoord dat er in chocoladerepen foto s van 80 celebrities (waaronder natuurlijk Duncan Laurence) worden meeverpakt, in elke reep een random celebrity, uniform en onafhankelijk getrokken. (a) Hoeveel repen moet Chris verwacht kopen tot hij zes verschillende celebrities heeft? (b) Hoe groot is de kans dat Duncan bij Chris eerste tien verschillende plaatjes zit? (c) Hoe groot is de kans dat Duncan voorkomt in de eerste tien repen van Chris? Oplossing: (a) Volgens de theorie van de coupon collector is het krijgen van het i-de plaatje een Bernoulli-experiment met slaagkans 81 i 80, dus verwacht aantal repen. Het 80 81 i totaal is dan 80(H 80 H 74 ) dat is 80 (0, 07756) dus 6,1966. (b) Doorsparen tot tien unieke celebs geeft een random combinatie van 10 uit 80 en de C(79, 9) kans dat Duncan daarbij zit is = 1/8. C(80, 10) (c) Elke reep heeft kans 79 om Duncan niet te bevatten, door de onafhankelijkheid is de 80 kans ( 79 80 )10 ofwel 0.8818 dat ze alle tien non-duncan zijn. De kans op Duncan in de eerste tien repen is dus 0,1182 dus 11,82%. Beoordeling/Toelichting: Per deelvraag een punt voor het goede antwoord. Het is niet mogelijk om hier alle drogredeneringen een voor een te weerleggen; van de meeste heb ik niet geprobeerd uit te zoeken waar het fout ging. Elke redenering die een andere uitkomst geeft dan de goede, is fout. Codes: A = Verwachting mag je niet Afronden, zelfs niet van een geheeltallige stochast, dus 6 is gewoon fout. C = Het juiste antwoord bij (b) is 1/8 en dat is niet het juiste antwoord bij (c). Bij (c) levert 1/8 geen punt. L = Je mag het verschil van Harmonische getallen afschatten op ln 80 en dan kom je op 74 6,2369 repen. V = De formule n.p geeft de Verwachting van het aantal successen, dus niet de kans op succes in een reeks van n pogingen.
5. Delete uit Heap: Geef een methode void Delete(int i), die uit een MinHeap A het element op positie i verwijdert (in logaritmische tijd; Rootify en Heapify zijn gegeven). Oplossing: Begin met het laatste element op plek i te zetten en n te verlagen. Op positie i kunnen nu twee dingen mis zijn. (1) Als het element groter is dan een van zijn kinderen moet je Heapify(i) toepassen (Bubble Down); Heapify stopt vanzelf als deze conditie niet geldt. (2) Als het element kleiner is dan zijn ouder moet je omwisselen en met de ouder verder gaan (Bubble Up); ook Rootify stopt vanzelf als verdergaan niet nodig is. void Delete(int i) { A[i] = A[n--]; Heapify(i); Rootify(i); } Beoordeling/Toelichting: Tot 2pt voor een complete methode. A = Een Aanroep van removeat(i) kost lineaire tijd en verprutst de hele heap omdat alle hoger elementen opschuiven. remove(i) is een String-methode. B = Een heap is 1-Based dus laatste plek is A[Size], niet A[Size-1]. H = Zonder Heapify is t niet goed, want de key die op plek i komt, kan groter zijn dan zijn kinderen; 1pt. N = Op Null zetten of met Nullen goochelen doen we in een heap niet! Per definitie zijn de plekken 1 t/m n met keys gevuld; 1pt. P = Lees op de goeie Plek, dwz A[i] = A[n--], niet --n immers de heap is 1-based. R = Zonder Rootify is t niet goed, want de key die op plek i komt, kan kleiner zijn dan zijn parent! 1pt. T = Omdat Rootify en Heapify zelfstoppend zijn, is een test of t nodig is, overbodig, die zit er als het ware al in; 1/2pt. V = Verlaag de counter, en doe dat voor de Heapify, ander stopt Heapify misschien verkeerd; 1/2pt. 6. Recurrente betrekking: Los op: T 0 = 1, T 1 = 2, T n = T n 1 + 2T n 2. Oplossing: Stel het karakteristieke polynoom op: x 2 + x 2. Nulpunten vind je met de ABC formule: α 1 = 1 en α 2 = 2. De Algemene Oplossing is dus T n = C + D.( 2) n. Gebruik de gegeven waarden voor n = 0 en n = 1 en stel op: C + D = 1 en C 2D = 2. Trek de tweede vergelijking af van de eerste en zie 3D = 1 dus D = 1/3. Met de eerste vgl geeft dit C = 4/3. (Of vind dit door de tweede vgl op te tellen bij tweemaal de eerste.) Oplossing T n = 1 3 (4 ( 2)n ). (Controleer met de eerste waarden: 1, 2, 0, 4, 4, 12, 20. Klopt!) Beoordeling/Toelichting: Voor een goede oplossing 2pt. Codes: A = Kom je t/m de Algemene Oplossing a n = C.1 n + D.( 2) n, 1pt. C = Controleer je uitkomst! Het kost je maar 10 seconden om met de gegevens de eerste vijf waarden van T te berekenen en vul dan 2 t/m 4 in in je oplossing. Geen zichzelfrespecterende wiskundige zou dit als een bewijs voor de juistheid van de formule accepteren. Maar als je graag een correcte formule inlevert, is dit een handig truukje om 99% van de foute antwoorden te ontmaskeren.