Akademin för innovation, design och teknik Caroline Uppsäll 1(4) Datastrukturer,algoritmerochprogramkonstruktion DVA104,HT2015 Laboration4–Implementeringochutvärderingav sökalgoritmer Läs noga igenom hela labbspecen innan du börjar implementera. Nål i höstacken Man brukar säga “det är som att leta efter en nål i en höstack” när man står inför en till synes hopplös uppgift att leta efter någonting. En outtröttlig dator kan dock finna en nål i en höstack - förr eller senare. Med tillräckligt sluga algoritmer kan man dessutom se till att det går fort. Ni ska utvärdera hur olika sökmetoder påverkas av ”höstackens storlek” då man letar efter en ”nål” i den. För att ni ska få tider som är tillräckligt långa för att vara mätbara måste ni ha rejält många ”strån i stacken” (ett antal miljoner element för den största storleken). Ni behöver ha minst 3 olika storlekar (med stora skillnader i storlek) för att kunna dra några slutsatser. Förslag på storlekar är 50 000, 500 000 samt 5 000 000 element. (höstacken = mängd av data/tal, nål = data/tal att leta efter, strån = enskilt data/tal i mängden) • För att slumpen inte ska påverka mätningen måste ni upprepa mätningen flera gånger, förslag är att mäta tiden över minst 50-100 sökningar/varv för varje datamängd. För varje sökning/varv så ska en ny nål slumpas fram. På detta sätt får ni en mätning som är mer oberoende av tur eller otur. • Eftersom olika sökmetoder är olika effektiva, så måste ni också välja olika antal upprepningar för olika sökmetoder. Annars kommer ni antingen att få vänta väldigt länge på de långsamma sökmetoderna eller så blir de snabba inte mätbara. • Sökmetoderna påverkas också olika av storleken på ”höstacken”, vissa är ganska oberoende av ändrad storlek medan andra påverkas kraftigt. • Det kan vara bra att leta upp lite information om hur komplexiteten för de olika sökmetoderna varierar för att lättare komma fram till ett lämpligt antal upprepningar för respektive testfall. Alternativt får ni prova fram ett lämpligt antal upprepningar. • Ni måste förstås tänka på att skala om den mätta tiden till en gemensam enhet så att det blir jämförbart. En viss variation i mätningarna kan uppstå om man byter dator mellan körningarna, åtminstone om det är stor skillnad mellan datorernas prestanda. Ni bör därför notera resultaten för de olika metoderna från körningar på samma datortyp (eller åtminstone datorer med hyfsat lika prestanda). För att ”höstacken” ska fungera för de olika metoderna måste ni representera den med unika värden. Detta kan ni t.ex. göra genom att använda de filer med data som tillhandahålls på Blackboard eller genom att fylla en n element lång ”höstack” med värdena 1 – n. I de senare fallet kommer ni att få tänka till lite extra på hashtabellen i uppgift 4, ni får också se till att den ”nål” ni sedan ska söka efter är slumpad på ett sådant sätt att den inte nödvändigtvis behöver finnas i ”höstacken”. Akademin för innovation, design och teknik Caroline Uppsäll 2(4) Tips1: Skapa ett fält (array) för varje höstack, alltså en array med 50.000 element, en med 500.000 element och en med 5.000.000 element, där elementen är slumpade och unika. Använd sedan dessa fält för att skapa de andra datatyperna som sökningen ska köras på. Tips2: När sökning sker i såhär stora mängder kan det hända att ni får ”stack overflow”, detta betyder att minnet på stacken inte räcker till. Fundera på hur ni kan lösa detta problem. Tiden ni mäter ska bara inkludera själva sökningen. Hur stor noggrannhet behöver man mäta med? Ta reda på vilken kod i C som behövs för att ni ska kunna få ut exekveringstiden. Sökningen ska ske på följande fyra sätt: 1 – Sekventiell sökning Själva koden ni ska skriva är trivial, bara att loopa igenom höstacken (arrayen med element) till dess att nålen (ett specifikt element) är funnen. Sökningen får i detta fall inte förutsätta att det finns en nål att hitta. (I många verkliga problem kan det vara lika värdefullt att få svar på om det finns en nål i höstacken, som att få reda på data som är associerad med den). Själva sökningen ska givetvis implementeras som en funktion. 2 – “Optimerad” sekventiell sökning Om ni tittar på er kod för sekventiell sökning så ser det kanske ut som en hopplös uppgift att göra den ännu enklare. Men om ni är riktigt kluriga så inser ni att det borde gå att snabba upp sökningen genom att ta bort lite kod. Hur ska det gå till? - Jo, genom att lägga till den ”nål” ni söker sist i ”höstacken”, dvs. efter alla ”strån” (efter alla element) så kan villkoren för att avbryta loopen göras enklare. Ni behöver då inte testa om slutet av fältet har nåtts, för nu vet ni att även om det inte finns någon ”nål” i ”höstacken” så får ni ändå träff på den extra ditlagda ”nålen”. Lägg in resultatet från denna och uppgift 1 i samma diagram. Inte illa va? - Kanske inte revolutionerande, men det borde i alla fall märkas en skillnad. Får du ingen skillnad i tid mellan de två sökmetoderna så behöver du fundera över/diskutera hur det kan komma sig. Den ”optimerade” versionen behöver inte göra jämförelsen vilket i teorin betyder att den borde gå snabbare. Du kan också prova att öka storleken på datamängderna samt antal varv som sökningen körs för att få ett tydligare utslag. 3 – Balanserat binärt sökträd I många tillämpningar sker sökning betydligt oftare än insättning. T.ex. kan det vara så att man skapar ”höstacken” initialt (dvs. sätter in elementen i någon datasamling) och i just det initiala skedet spelar exekveringstiden inte någon roll. Det kan t.ex. ske vid systemstart. Därefter är sökning den helt dominerande operationen, insättning och borttagning av element sker förhållandevis sällan. I denna typ av tillämpningar “lönar” det sig alltså att “investera” i en “dyr” datalagring som görs initialt, om man därigenom uppnår att de efterföljande sökningarna blir “billiga”. Akademin för innovation, design och teknik Caroline Uppsäll 3(4) I sådana fall kan ett binärt sökträd vara ett bra alternativ, speciellt om man inte vet något om storleken på datamängden. I denna deluppgift ska ni använda ert sorterade binära träd från laboration 3 (som också är ett sökträd). Repetera körningen med samma storlekar på höstacken som i de två tidigare deluppgifterna, och lägg in i ett diagram. Jämför med de tidigare körningarna. Nå? Om ni valt att fylla en n element stor array (i 1 och 2) med värdena 0 – n så behöver ni använda er balanseringsfunktion för att bygga trädet utifrån arrayen, annars kommer ni att få ett degenererat träd att arbeta i (det kommer då att ta extremt lång tid att fylla samt balansera trädet för de stora mängderna). Tips: Oavsett hur ni valt att fylla trädet, se till att det är balanserat innan ni sätter igång med sökningen. 4 – Hashtabell Upphetsad av framgångarna ska ni nu göra en fjärde utvärdering. Med samma motiveringar som i föregående deluppgift kan man tänka sig att ta kostnaden för att bygga upp en hashtabell i utbyte mot en efterföljande effektiv uppslagning. Hashtabeller kommer bäst till sin rätt då man i förväg har ett hum om hur mycket data som ska lagras. Låt oss anta en sådan situation. Hur stor bör tabellen vara relativt mängden data som man tror ska läggas in? Ni kan med fördel använda “chained hash table”. Och då kan det kanske vara läge att tänka på återanvändning. Av vad? Leta upp en hashfunktion som verkar bra. Det finns bland annat en del skrivet på nätet. Ange referens som kommentar, och skriv även en motivering till ditt val. Många hashfunktioner baserar sig på strängar. Om dina nålar t.ex. är av någon heltalstyp så blir ju inte det riktigt samma sak. Går det att använda strängbaserade funktioner ändå på något sätt om nycklarna utgörs av heltal? Ni ska förstås göra er hashtabell som en ADT. Lägg återigen in era körningar i samma diagram. Vad säger ni nu då? Kanske ni behöver lägga in resultaten från binärt träd och hashtabell i ett eget diagram för att det ska vara möjligt att jämföra dem inbördes. Om ni valt att fylla en n element stor array (i 1 och 2) med värdena 0 – n så kommer ni aldrig att få några krockar i tabellen, ni kommer alltså hamna på bästa fallet för sökningen oavsett nål, detta måste lösas på något sätt. Nedan följer två alternativ: • • När ni fyller tabellen så slumpar ni för varje nytt värde fram ett index. Värdet som ligger på det indexet i arrayen ska sedan läggas in i tabellen. Då kommer ni att få dubbletter i trädet. I sökningen så kommer ni alltid att hitta den första ”instansen” av dessa dubbletter. För att få mer realistiska mätvärden så kan ni vid sökning slumpa fram en nål att söka efter och vilken ”instans” av den nålen ni vill hitta (i ett avgränsat intervall). Den andra lösningen på problemet är att använda de färdiggenererade filerna med slumpade unika data som finns tillgängliga på Blackboard. Vilka åtgärder var mest värda att investera i om man tar hänsyn till långsiktiga effekter? Akademin för innovation, design och teknik Caroline Uppsäll 4(4) Redovisning Samtliga uppgifter ska redovisas muntligt under ett och samma redovisningstillfälle genom att visa fungerande implementationer till labbassistenten. Om samtliga laborationer redovisats och godkänts innan tentamen erhålls bonuspoäng på denna. Tänk dock på att redovisa labbarna utspridda under hela kursens gång då det troligtvis inte finns tid om alla ska redovisas på slutet.
© Copyright 2024