Övning 2. (Länkade) Listor, noder

Relevanta dokument
Föreläsning 13 och 14: Binära träd

Inom datalogin brukar man använda träd för att beskriva vissa typer av problem. Om man begränsar sig till träd där varje nod förgrenar sig högst två

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Träd Hierarkiska strukturer

Linjärt minne. Sammanhängande minne är ej flexibelt. Effektivt

KTH, NADA, Vahid Mosavat. 1. Flervalsfrågor (5p)

Fredag 10 juni 2016 kl 8 12

Tentamen kl Uppgift 4. Uppgift 5

Algoritmer och datastrukturer H I HÅKAN S T R Ö M B E R G N I C K L A S B R A N D E F E L T

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

Länkade listor, stackar och köer

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Måndag 13 mars 2017 kl Rita en KMP-automat för CAMCORDERCAMERA samt ange next-vektorn.

Föreläsning Datastrukturer (DAT037)

Tildatenta Lösningsskiss

DD1320 Tillämpad datalogi. Lösning (skiss) till tenta 20 okt 2011

Lösningar Datastrukturer TDA

Föreläsning 13. Träd

Programkonstruktion och Datastrukturer

Sätt att skriva ut binärträd

Tentamen'('Datastrukturer,'algoritmer'och'programkonstruktion.'

Självbalanserande träd AVL-träd. Koffman & Wolfgang kapitel 9, avsnitt 1 2

Repetition i Python 3. Exemplen fac. Exemplen fac motivering. Exemplen fac i Python

Föreläsning Datastrukturer (DAT036)

Träd. Rot. Förgrening. Löv

Föreläsning 5. Rekursion

Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5

Programmering i C++ EDAF30 Dynamiska datastrukturer. EDAF30 (Föreläsning 11) HT / 34

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

Datastrukturer i kursen. Föreläsning 8 Innehåll. Träd rekursiv definition. Träd

Grundläggande datalogi - Övning 3

Tentamen Datastrukturer D DAT 035/INN960 (med mycket kortfattade lösningsförslag)

Föreläsning 9 Innehåll

Föreläsning 3 Datastrukturer (DAT037)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Föreläsning 9 Datastrukturer (DAT037)

Föreläsning 6 Innehåll. Rekursion. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursiv problemlösning. Rekursion. Rekursivt tänkande:

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

DAI2 (TIDAL) + I2 (TKIEK)

Rekursion. Koffman & Wolfgang kapitel 5

Datalogi, grundkurs 1

Rekursion och induktion för algoritmkonstruktion

Några saker till och lite om snabbare sortering

Föreläsning 9 Innehåll

Ett generellt träd är. Antingen det tomma trädet, eller en rekursiv struktur: rot /. \ /... \ t1... tn

Programmering i C++ EDA623 Dynamiska datastrukturer. EDA623 (Föreläsning 11) HT / 31

Inlämningsuppgiften. Föreläsning 9 Innehåll. Träd. Datastrukturer i kursen

Föreläsning 4. Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö

Grundläggande Datalogi för F

Lösningsförslag till tentamen Datastrukturer, DAT037,

PROV I MATEMATIK Algoritmik 26 mars 2008

Rekursion och induktion för algoritmkonstruktion

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning Datastrukturer (DAT036)

Självbalanserande AVL-träd Weiss, avsnitt 4.4

Övning 1. Abstrakta datatyper. 1. Stacken. class Stack: """A representation of a last-in-first-out (LIFO) stack of objects."""

Datastrukturer. Föreläsning 5. Maps 1

ADT Kö. Seminarium 4 Köer och Stackar Innehåll. Operationer. ADT Stack. Definition. Definition

Upplägg. Binära träd. Träd. Binära träd. Binära träd. Antal löv på ett träd. Binära träd (9) Binära sökträd (10.1)

Länkade strukturer, parametriserade typer och undantag

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

Föreläsning 3 Datastrukturer (DAT037)

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Algoritmer och datastrukturer 2012, fo rela sning 8

DD1320 Tillämpad datalogi. Lösnings-skiss till tentamen

Länkade listor kan ingå som en del av språket, dock ej i C Länkade listor är ett alternativ till:

Dekomposition och dynamisk programmering

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Tentamen i Algoritmer & Datastrukturer i Java

Vad har vi pratat om i kursen?

F4: Mer om OU1, OU2, listor och träd. Carl Nettelblad

Problemlösning och funktioner Grundkurs i programmering med Python

Trädstrukturer och grafer

Föreläsning 7. Träd och binära sökträd

Exempel: Förel Rekursion III Nr 14. Uno Holmer, Chalmers,

Grundläggande Datalogi för F

Föreläsning Datastrukturer (DAT036)

Grundläggande datalogi - Övning 4

Mer till P-uppgiften: Dokumentation. Nyheter. Algoritm för sökning. Mer hjälp. DD1311 Programmeringsteknik med PBL

Tentamen i Algoritmer & Datastrukturer i Java

Binära sökträd. Seminarium 9 Binära sökträd Innehåll. Traversering av binära sökträd. Binära sökträd Definition. Exempel på vad du ska kunna

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Datastrukturer och algoritmer

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

3. Toppkvinnor på hög Låt lådan och de två kvinnornas famnar utgöra stackarna L, K1 respektive K2. Från början finns alla kort i L.

Föreläsning 4 Datastrukturer (DAT037)

729G04: Inlämningsuppgift Diskret matematik

Föreläsning 10 Datastrukturer (DAT037)

Tentamen Datastrukturer för D2 DAT 035

Tillämpad Programmering (ID1218) :00-13:00

Övning 3 - Tillämpad datalogi 2012

Översikt. Stegvis förfining. Stegvis förfining. Dekomposition. Algoritmer. Metod för att skapa ett program från ett analyserat problem

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Programkonstruktion och. Datastrukturer

Sökning. Översikt. Binärt sökträd. Linjär sökning. Binär sökning. Sorterad array. Linjär sökning. Binär sökning Hashtabeller

Föreläsning 4 Innehåll

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

Transkript:

Per Sedholm DD30 (tilda3) 03-09-03 Övning Listor, pekare, binära träd, rekursion, komplexitet (Länkade) Listor, noder. Ta bort andra noden (a) Skriv en sats som tar bort andra noden ur en länkad lista. OBS Detta måste fungera: om listan är tom om listan har ett element om listan har två element om listan har fler element Ett exempel på en länkad lista: Listan (List) har en first, som pekar på första noden Varje nod (Node) har en next, och en value from MyUtils import LinkedList def remove_second(lst): n = lst.first if n!= None and n.next!= None: sec = n.next n.next = n.next.next return sec raise IndexError( List does not have two elements ) ll = LinkedList() ll.insert( foo ) ll.insert( bar ) ll.insert( baz ) print(ll) remove_second(ll) print(ll) # < baz ; bar ; foo > # < baz ; foo > Vi kan även testa vad som händer när det blir fel: try: ll = LinkedList() ll.insert( Spanish inquisition ) print(ll) remove_second(ll) print(ll) except IndexError: print("<caught IndexError!>") (b) Nu ska du ta bort andra noden ur en stack. Lös uppgiften abstrakt, alltså med anrop till push och pop!

from MyUtils import Stack s = Stack() s.push( snap ) s.push( crackle ) s.push( pop ) print(s) e = s.pop() s.pop() s.push(e) print(s) # [Stack]{pop; crackle; snap} # [Stack]{pop; snap}. Ta bort varannan nod OBS Tänk igenom och rita bilder för att visa att alla dessa fungerar för alla listor: tom lista lista med ett element lista med ojämnt antal element lista med jämnt antal element (a) genom att meka med pekare Vi ska ha kvar det aktuella elementet n Ifall den har en efterföljare, så ska n next sättas till dess next, n next next, för att hoppa över efterföljaren. def remove_every_second(lst): n = lst.first while n!= None and n.next!= None: n.next = n.next.next n = n.next (b) abstrakt, med hjälp av en extra stack Ifall vi har två element, lägg undan ett och släng det andra. Varför fungerar det när vi har ett element? Hamnar allt i rätt ordning? def remove_every_second(lst): stack = Stack() while len(lst) >= : a = lst.getfirst() # lst.pop(0) för <list> #lst.removefirst() # ifall inte getfirst gör det stack.push(a) # motsv lst.insert(0, a) för <list> b = lst.getfirst() #lst.removefirst() while not stack.isempty(): el = stack.pop() lst.insertfirst(el) # lst.insert(0, el) för <list> return lst

(c) abstrakt, med hjälp av rekursion Varje anrop tar in listan, och returnerar listan till ovanstående rekursionsnivå En stack med mindre än två element är klar. Annars, ta bort två element, gör rekursivt anrop, stoppa tillbaka. def remove_every_second(lst): if len(lst) < : return lst a = lst.getfirst() b = lst.getfirst() lst = remove_every_second(lst) lst.insertfirst(a) return lst Binära sökträd. Trädbygge Hur ser det binärträd ut som skapas om man puttar in talen 4 3 7 5 i denna ordning? Och hur ser det ut om man sätter in dom i omvänd ordning, alltså 5 7 3 4? Är båda träden binära sökträd? Är de balanserade? I ett balanserat träd är höjdskillnaden i alla grenar. Inordning vänster träd noden höger träd Preordning noden vänster träd höger träd Postordning vänster träd höger träd noden Insättning av 4 3 7 5 Binärt sökträd: Ja. Balanserat: Ja. 4 3 5 7 Insättning av 5 7 3 4 Binärt sökträd: Ja. Balanserat: Ja. 5 3 7 4 3

. Postorderträd Skriv ut något av träden i inordning och bygg upp ett nytt träd från denna talföljd. Skriv sedan ut dom i preordning och bygg upp nya träd från dessa talföljder. Skriv slutligen ut dom i postorder och bygg upp nya träd från dessa talföljder. Inordning Bägge träd blir... 0 i inordning. Nytt träd blir helt obalanserat ( tarm ) 7 Preordning Första: 4,,, 3,, 5, 7 = (ursprungsträdet) Andra: 5, 3,,, 4, 7, = 5 3 7 4 Postordning Första:, 3,, 5, 7,, 4 = 3 5 4 7 4

Andra:,, 4, 3,, 7, 5 = 4 3 5 7 Rekursion. Euklides algoritm för att beräkna GCD För att beräkna största faktorn som två tal m och n har gemensamt kan vi använda Euklides algoritm: Om m är jämnt delbar med n så är n den största gemensamma faktorn. Annars är GCD(m, n) = GCD(n, m % n). Skriv en rekursiv funktion! # -*- coding: utf-8 -*- def gcd(m, n): print("gcd(" + str(m) + ", " + str(n) + ") -> ", end= ) if m % n == 0: print(n) return n print("gcd(" + str(n) + ", " + str(m%n) + ")") return gcd(n, m % n) gcd(87, 989) # GCD(87, 989) -> GCD(989, 87) ## 87 < 989 => 87 % 989 = 87 # GCD(989, 87) -> GCD(87, 55) ## 989 = 87* + 55 # GCD(87, 55) -> GCD(55, 0) ## 87 = 55*3 + 0 # GCD(55, 0) -> GCD(0, 5) ## 55 = 0* + 5 # GCD(0, 5) -> 5 ## 0 = 5* + 0. Fibonaccital Leonardo Fibonacci skrev år 5 en bok där han beskrev denna intressanta talföljd: Sista december föds en kaninpojke och en kaninflicka. Vid två månaders ålder och varje månad därefter producerar varje kaninpar ett nytt kaninpar. Vi kan skriva en rekursiv formel för antal kaninpar: f 0 = 0 f = f n = f n + f n 5

Skriv en rekursiv funktion för att beräkna Fibonaccital. Visa vilka rekursiva anrop den ger upphov till vid beräkningen av f(5). Är det här det effektivaste sättet att beräkna Fibonaccitalen? # -*- coding: utf-8 -*- def fib(n): if n <= : return n return fib(n-) + fib(n-) print(fib(5)) # fib(5) -> fib(4) + fib(3) # fib(4) -> fib(3) + fib() # fib(3) -> fib() + fib() # fib() -> fib() + fib(0) # fib() -> # fib(0) -> 0 # fib() -> # fib() -> fib() + fib(0) # fib() -> # fib(0) -> 0 # fib(3) -> fib() + fib() # fib() -> fib() + fib(0) # fib() -> # fib(0) -> 0 # fib() -> # 5 Man kan visa att antalet anrop faktiskt växer snabbare än själva Fibonaccitalen! (För n = 40 är Fibonaccitalet ca hundra miljoner men antalet rekursiva anrop är över 300 miljoner.) Bättre vore här att använda en for-slinga: def fib(n): f0 = 0 f = for i in range(n-): f = f + f0 f0 = f f = f return f Den här implementationen går i linjär tid, O(n). 3. Rekursiv trädsumma Ge en rekursiv tanke för summan av alla talen i trädet och programmera den så att anropet tree.sum() ger rätt svar. # Om den står utanför klassen slipper man self def summa(p): if p == None: return 0 return int(p.value) + summa(p.left) + summa(p.right) class Bintree(object): """- - -""" def sum(self): return summa(self.root) print("sum:", b.sum())

Med första exemplet från trädbygge: # Sum: 8 # # summa(<4>) = 4 + summa(<>) + summa(<>) # summa(<>) = + summa(<>) + summa(<3>) # summa(<>) = + summa(none) + summa(none) # summa(<3>) = 3 + summa(none) + summa(none) # summa(<>) = + summa(<5>) + summa(<7>) # summa(<5>) = 5 + summa(none) + summa(none) # summa(<7>) = 7 + summa(none) + summa(none) 4. Rekursiv trädhöjd Ge en rekursiv tanke för höjden av ett träd. Höjden är den maximala nivån som nån av trädets noder befinner sig på. Ett träd med bara en rotnod har höjden 0, och ett tomt träd har höjden. Rekursiv tanke: Höjden är +max(höjd vänster, höjd höger)... men tomt träd har höjden. Krångligare att läsa utskrifterna, notera att en extra nivå lagts till. def height(p): if p == None: return - h = height(p.left) h = height(p.right) return max(h, h) + class Bintree(object): """- - -""" def height(self): return heightl(self.root) print "Height:", b.height() # Height: 3 # # height(none) = - # height(none) = - # height(<>) = max(-, -) + # height(none) = - # height(none) = - # height(<3>) = max(-, -) + # height(<>) = max(0, 0) + # height(none) = - # height(none) = - # height(<5>) = max(-, -) + # height(none) = - # height(none) = - # height(<0>) = max(-, -) + # <7> replaced with <7> # height(none) = - # / \ # height(none) = - # <0> <> # height(<>) = max(-, -) + # height(<7>) = max(0, 0) + # height(<>) = max(0, ) + # height(<4>) = max(, ) + 7

Komplexitet. Körtider En viss algoritm tar 0.5 ms när antal indata är 00. Hur lång kommer körtiden att bli när antal indata är 500 om man vet att körtiden är: - linjär, dvs O(n) - O(n log(n)) - kvadratisk, dvs O(n ) - kubisk, dvs O(n 3 ) Linjär: t k n n = 00 k 00 = n = 500 k 500 = x } k = 0.5 00 x = 500 =.5 (5 ggr längre) 00 O(n log(n)): t k n log(n) n = 00 k 00 log(00) = n = 500 k 500 log(500) = x } x = 5 500 3.37 (.74 ggr längre) 00 Kvadratisk: t k n n = 00 k 00 = n = 500 k 500 = x } x = 5 5 =.5 (5 ggr längre) Kubisk: t k n 3 n = 00 k 00 3 = n = 500 k 500 3 = x } x = 5 5 5 =.5 (5 ggr längre) 8