Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6?
DAGENS AGENDA Komplexitet Ordobegreppet Komplexitetsklasser Loopar Datastrukturer Några nyttiga regler OBS! Idag jobbar vi med pseudokod
KOMPLEXITET Anta att ADT:n Fält behöver en operation som returnerar vilket index som en viss iterator pekar på (kanske ett meningslöst exempel, men enkelt...). Om x inte pekar på något element i fältet så returneras storleken... En möjlig algoritm: Integer GetIndex(Iterator x) Integer i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next() Return i
KOMPLEXITET Anta att operationen - finns för iteratorer och att den beräknar avståndet mellan två iteratorer (uttryckt i antal element). Följande algoritm är då möjlig Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i
KOMPLEXITET Vi räknar operationerna som kommer att utföras för ett visst indatafall. Operationer är aritmetiska (+, - etc), jämförelser och tilldelningar. Först fallet att det efterfrågade elementet ligger först: Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next()
KOMPLEXITET Vi räknar operationerna som kommer att utföras för ett visst indatafall. Operationer är aritmetiska (+, - etc), jämförelser och tilldelningar. Först fallet att det efterfrågade elementet ligger först: Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next()
KOMPLEXITET För detta fall är algoritmen med iteration effektivast Först fallet att det efterfrågade elementet ligger först: Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i 5 i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next() 3
KOMPLEXITET Vi räknar nu operationer för fallet att det efterfrågade elementet ligger först på plats 1 000 000 Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next()
KOMPLEXITET Vi får nu det omvända förhållandet: algoritmen med loop blir ineffektivare 4 000 000 mot 5 Det efterfrågade fallet ligger på plats 1 000 000 Integer GetIndex(Fält f, Iterator x) Integer i i = x - First() If i < 0 OR i >= Size() then i = NrOfElements() End If Return i 5 i = 0 p = First() While p!= x do If p.isend() then Break End If i = i + 1 p = Next() ca 4 000 000
KOMPLEXITET I detta fall vet vi inte det det exakta antalet iterationer för varje sökning. Vi vet inte heller hur lång tid respektive operation tar, men det är uppenbart att loop-lösningen tar enormt mycket mer datorkraft.
KOMPLEXITET I detta fall vet vi inte det det exakta antalet iterationer för varje sökning. Vi vet inte heller hur lång tid respektive operation tar, men det är uppenbart att loop-lösningen tar enormt mycket mer datorkraft. Om t.ex. Två algoritmer som löser samma problem ska jämföras eller vi vill ha en grov uppfattning om en algoritms komplexitet/effektivitet och mängden data kan vara stor Använd stora ordo, O(x) för att ge en grov bild av komplexiteten
ORDOBEGREPPET Komplexiteten för en algoritm är det antal distinkta steg den kan behöva för att slutföra en beräkning Komplexiteten uttrycks som en funktion av datamängden n n är mängden data som algoritmen behandlar O-notation beskriver prestanda och komplexitet Kan beskriva exekveringstid eller minne
ORDOBEGREPPET Komplexiteten för en algoritm är det antal distinkta steg den kan behöva för att slutföra en beräkning Komplexiteten uttrycks som en funktion av datamängden n n är mängden data som algoritmen behandlar O-notation beskriver prestanda och komplexitet Kan beskriva exekveringstid eller minne Idag kan vi tänka på exekveringstid när vi pratar om komplexitet
ORDOBEGREPPET Komplexiteten för en algoritm är det antal distinkta steg den kan behöva för att slutföra en beräkning Komplexiteten uttrycks som en funktion av datamängden n n är mängden data som algoritmen behandlar O-notation beskriver prestanda och komplexitet Kan beskriva exekveringstid eller minne Idag kan vi tänka på exekveringstid när vi pratar om komplexitet O-notation beskriver (oftast) värsta möjliga scenario
Dessa är de komplexiteter vi kommer att hålla oss till NÅGRA VANLIGA KOMPLEXITETSKLASSER
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma - halverad sökmängd
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma - halverad sökmängd - direkt beroende av n
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma - halverad sökmängd - direkt beroende av n - blandning av log n och n
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma - halverad sökmängd - direkt beroende av n - blandning av log n och n - nästlade loopar i två steg
NÅGRA VANLIGA KOMPLEXITETSKLASSER Dessa är de komplexiteter vi kommer att hålla oss till - alltid samma - halverad sökmängd - direkt beroende av n - blandning av log n och n - nästlade loopar i två steg - nästlade loopar i tre steg
ORDOBEGREPPET Om körtiden för en algoritm inte alls påverkas av antalet element säger man att den är konstant eller O(1) Om körtiden för en algoritm påverkas linjärt av antalet element säger man att den är linjär eller, där n är antalet element Om körtiden för en algoritm påverkas kvadratiskt av antalet element säger man att den är kvadratisk eller O(n²), där n är antalet element Att nollställa en matris är O(m*n) där m är antalet rader och n är antalet kolumner
O(1) Algoritmen kommer alltid att exekvera på samma tid oavsett hur stort indatat är Exempel: bool IsFirstElementNull(String[] strings) If string[0] = NULL then Return true End If Return false
O(LOG N) Algoritmen kommer att exekvera på en tid proportionell till logaritmen av indatats storlek. Detta betyder generellt att algoritmen jobbar med en datamängd som iterativt delas Exempel: Sökning i sorterat binärt träd Binärsökning log(n) < n, när n går mot stora värden Algoritmer som körs i O(log n) använder inte hela indatat
O(N) Algoritmens exekveringstid kommer att växa linjärt och i direkt proportion till indatats storlek Exempel: bool ContainsValue(String[] strings, String value) For i = 0; i < strings.length; i++ do If strings[i] = value then Return true End If Return false
ORDOBEGREPPET 2 algoritmer, A och B, som löser samma typ av problem - Komplexitet på A är 5000n - Komplexitet på B är 1,1 n Indata A B n 5 000n [1,1 n ] 10 50 000 3 100 500 000 13 781 1 000 5 000 000 2,5 * 10 41 1 000 000 5 * 10 9 4,8 * 1041 392
ORDOBEGREPPET 2 algoritmer, A och B, som löser samma typ av problem - Komplexitet på A är 5000n - Komplexitet på B är 1,1 n För n = 10: - A kräver 50 000 steg - B kräver 3 steg B är bättre Indata A B n 5 000n [1,1 n ] 10 50 000 3 100 500 000 13 781 1 000 5 000 000 2,5 * 10 41 1 000 000 5 * 10 9 4,8 * 1041 392
ORDOBEGREPPET B kan inte användas för stora datamängder 2 algoritmer, A och B, som löser samma typ av problem - Komplexitet på A är 5000n - Komplexitet på B är 1,1 n För n = 10: - A kräver 50 000 steg - B kräver 3 steg För n = 1 000: - A kräver 5 000 000 steg - B kräver 2,5 * 10 41 steg B är bättre A är bättre Indata A B n 5 000n [1,1 n ] 10 50 000 3 100 500 000 13 781 1 000 5 000 000 2,5 * 10 41 1 000 000 5 * 10 9 4,8 * 1041 392
ORDOBEGREPPET B kan inte användas för stora datamängder 2 algoritmer, A och B, som löser samma typ av problem - Komplexitet på A är 5000n - Komplexitet på B är 1,1 n För n = 10: - A kräver 50 000 steg - B kräver 3 steg För n = 1 000: - A kräver 5 000 000 steg - B kräver 2,5 * 10 41 steg B är bättre A är bättre Indata A B n 5 000n [1,1 n ] 10 50 000 3 100 500 000 13 781 1 000 5 000 000 2,5 * 10 41 1 000 000 5 * 10 9 4,8 * 1041 392 Vad som är viktigt är hur funktionen växer vid stora n
KÖRTID FÖR OLIKA KOMPLEXITETSKLASSER Algoritmen körs på f(n) mikrosekunder f(n) n = 2 n = 16 n = 256 n = 1024 n = 1 048 576 1 1 1 1 1 1 log2n 1 4 8 10 20 n 2 1,6 * 10 1 2,6 * 10 2 1,02 * 10 3 1,05 * 10 6 n log2n 2 6,4 * 10 1 2,1 * 10 3 1,02* 10 4 2,10 * 10 7 n 2 4 2,6 * 10 2 6,6 * 10 4 1,05 * 10 6 1,10 * 10 12 n 3 8 4,1 * 10 3 1,7 * 10 7 1,07 * 10 9 1,15 * 10 18 2 n 4 6,6 * 10 4 1,2 * 10 77 1,80 * 10 308 6,74 * 10315 652
KÖRTID FÖR OLIKA KOMPLEXITETSKLASSER f(n) n = 2 n = 16 n = 256 n = 1024 n = 1 048 576 1 1 µsec 1 µsec 1 µsec 1 µsec 1 µsec log2n 1 µsec 4 µsec 8 µsec 10 µsec 20 µsec n 2 µsec 16 µsec 260 µsec 1,02 ms 1,05 sec n log2n 2 µsec 64 µsec 2,1 ms 10,2 ms 21 sec n 2 4 µsec 260 µsec 66 ms 1,05 sec 1,8 wks n 3 8 µsec 4,1 ms 17 sec 17,9 min 36 559 yrs 2 n 4 µsec 66 ms 3,7 * 10 63 yrs 5,7 * 10 294 yrs 2,1 * 10 315 639 yrs
KOMPLEXITET Formellt gäller: Om f(n) är en funktion som uttrycker komplexiteten exakt, så är g(n) en övre begränsning, dvs vi kan säga O(g(n)), om det går att välja en konstant K och fixt n 0, så att K * g(n) >= f(n) för alla n > n 0 Dvs om man bortser från små värden och konstanta faktorer så är g(n) större eller lika
KOMPLEXITET Vi kan säga O(g(n)) om det går att välja en konstant K och ett fixt n 0, så att K * g(n) >= f(n) för alla n > n 0
KOMPLEXITET Det är de STORA värdena på n som är intressanta Värsta möjliga scenario! Därför räknar vi inte exakt utan gör en uppskattning baserat på komplexitetklasserna Vi kan säga O(g(n)) om det går att välja en konstant K och ett fixt n 0, så att K * g(n) >= f(n) för alla n > n 0
EXEMPEL En operation Clear() på ADT:n Matrix med m rader och n kolumner. Den nollställer alla matrisens element med hjälp av operationen ClearElement() Clear() Integer i = 0; j = 0 While i < m do While j < n do ClearElement(i, j) j = j + 1 j = 0 i = i + 1
EXEMPEL En operation Clear() på ADT:n Matrix med m rader och n kolumner. Den nollställer alla matrisens element med hjälp av operationen ClearElement() Clear() Integer i = 0; j = 0 While i < m do While j < n do ClearElement(i, j) j = j + 1 j = 0 i = i + 1 Vilken är komplexiteten? Och hur räknar vi ut den? Använd komplexitetsklasserna
EXEMPEL En operation Clear() på ADT:n Matrix med m rader och n kolumner. Den nollställer alla matrisens element med hjälp av operationen ClearElement() Clear() Integer i = 0; j = 0 While i < m do While j < n do ClearElement(i, j) j = j + 1 j = 0 i = i + 1 Vilken är komplexiteten? Och hur räknar vi ut den? Använd komplexitetsklasserna Komplexiteten: O(m*n), ty för varje varv i den yttre loopen (det är m st) kommer hela den inre loopen att snurra n st varv, dvs totalt n*m iterationer av den inre loopens kropp (dvs anrop till ClearElement()):
EXEMPEL Skulle vi räkna mer exakt skulle det bli 4n 2 + 4m + 3 enligt tidigare sätt att räkna operationer. Men vi säger alltså ändå att den är O(n 2 ) Allmänt: endast den terms om har högst dignitet tas med och konstanta faktorer på denna ignoreras. Motivering: För stora mängder av data är det den tyngst vägande termen som kommer att dominera Man kan t.ex. jämföra kurvorna för n 2 + 20n + 400 och n 2. Ju större värden på n, desto mindre relativ skillnad. För 1 miljon är den 0.002%, men för 1 är den 42100%. Det intressanta är beteendet vid stora mängder data.
EXEMPEL Skulle vi räkna mer exakt skulle det bli 4n 2 + 4m + 3 enligt tidigare sätt att räkna operationer. Men vi säger alltså ändå att den är O(n 2 ) Allmänt: endast den terms om har högst dignitet tas med och konstanta faktorer på denna ignoreras. Motivering: För stora mängder av data är det den tyngst vägande termen som kommer att dominera För att inte behöva räkna så mycket använder vi alltså de övergripande komplexitetsklasserna för att beskriva komplexiteten. Man kan t.ex. jämföra kurvorna för n 2 + 20n + 400 och n 2. Ju större värden på n, desto mindre relativ skillnad. För 1 miljon är den 0.002%, men för 1 är den 42100%. Det intressanta är beteendet vid stora mängder data.
ÖVNINGAR A Init(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 a[i].i = i i = i + 1 Vilken Init har högst komplexitet? - kod A eller kod B? B Init(A a[], Integer n) InitD(a, n) InitI(a, n) InitD(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 i = i + 1 InitI(A A[], Integer n) Integer i = 0 While i < n do a[i].i = i i = i + 1 end loop
Loopen körs i värsta fallet n ggr Init(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 a[i].i = i i = i + 1 Båda har komplexiteten Alltså samma! Init(A a[], Integer n) InitD(a, n) InitI(a, n) InitD(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 i = i + 1 InitI(A A[], Integer n) Integer i = 0 While i < n do a[i].i = i i = i + 1 end loop
Loopen körs i värsta fallet n ggr Init(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 a[i].i = i i = i + 1 Båda har komplexiteten Alltså samma! Looperna InitD och InitI körs vardera i värsta fallet n ggr alltså n+n = 2n Init(A a[], Integer n) InitD(a, n) InitI(a, n) InitD(A a[], Integer n) Integer i = 0 While i < n do a[i].d = 42 i = i + 1 InitI(A A[], Integer n) Integer i = 0 While i < n do a[i].i = i i = i + 1 end loop
ÖVNINGAR G(B b[], Integer n) Integer i = 0 While i < n do b[i].c = 0 i = i + 1 Vilken komplexitet har F?? F(A a[], Integer n) Integer i = 0 While i < n do G(a[i].b, n) i = i + 1
I F() körs loopen i värsta fallet n ggr, för varje varv så körs loopen i G() n ggr = n*n O(n 2) G(B b[], Integer n) Integer i = 0 While i < n do b[i].c = 0 i = i + 1 O(n 2 ) F(A a[], Integer n) Integer i = 0 While i < n do G(a[i].b, n) i = i + 1
ÖVNINGAR F(A a[], Integer n) Integer i = 0 While i < n do a[i].x = 0 i = i + 1 Integer j = 0 While j < 2*n do a[j].c = 0 j = j + 1 Vilken komplexitet har F??
Den första loopen körs i värsta fallet n ggr, den andra loopen körs i värsta fallet 2n ggr = n + 2n = 3n F(A a[], Integer n) Integer i = 0 While i < n do a[i].x = 0 i = i + 1 Integer j = 0 While j < 2*n do a[j].c = 0 j = j + 1
ÖVNINGAR 1: 2: F(A a[][], Integer n) While i < n do While j < n do a[i][j] = 7 F(A a[][], Integer n) While i < n do While j < 42 do a[i][j] = 7 Vilken komplexitet har F i de båda fallen??
Den yttre loopen körs i värsta fallet n ggr, den inre loopen körs i värsta fallet n ggr = n*n = n 2 O(n 2) F(A a[][], Integer n) While i < n do While j < n do a[i][j] = 7 O(n 2 ) F(A a[][], Integer n) While i < n do While j < 42 do a[i][j] = 7
Den yttre loopen körs i värsta fallet n ggr, den inre loopen körs i värsta fallet n ggr = n*n = n 2 O(n 2) F(A a[][], Integer n) While i < n do While j < n do a[i][j] = 7 O(n 2 ) Den yttre loopen körs i värsta fallet n ggr, den inre loopen körs i värsta fallet 42 ggr = n*42 = 42n O(n ) F(A a[][], Integer n) While i < n do While j < 42 do a[i][j] = 7
NÄSTLADE LOOPAR Oberoende nästlade loopar: Antalet iterationer i den inre loopen är inte beroende av antalet iterationer i den yttre loopen Exempel: x = 0 For j = 1; j <= n/2; j++ do For k = 1; k <= n*n; k++ do x = x + j + k Den yttre loopen exekverar n/2 gånger. För varje varv i den yttre loopen, exekverar den inre loopen n 2 gånger. Så kroppen till den inre loopen exekverar (n/2)*n 2 = n 3 /2 gånger Algoritmens komplexitet är O(n 3 )
NÄSTLADE LOOPAR Beroende nästlade loopar: Antalet iterationer i den inre loopen beror på ett värde från den yttre loopen Exempel: x = 0 For j = 1; j <= n/2; j++ do For k = 1; k <= 3*j; k++ do x = x + j När j är 1, körs den inre loopen 3 gånger; När j är 2, körs den inre loopen 3*2 gånger;... När j är n, körs den inre loopen 3*n gånger. Totalt körs den inre loopen 3+6+9+...3n = 3(1+2+3+...n) = 3n 2 /2 + 3n/2 gånger. Algoritmens komplexitet är alltså O(n 2 )
NÅGRA ENKLA REGLER OM LOOPAR Det är bara loopar vars antal iterationer som är beroende av indatats storlek som man behöver ta hänsyn till Nästlingen avgör vilket O (ordo) det blir Man måste titta i alla funktioner som anropas O för nästlade loopar multipliceras om de är oberoende O för sekventiella loopar adderas Om två loopar är nästlade på samma nivå i loophierarkin så är det den av looparna som har högst O som man räknar med Bara den största (mest dominanta) termen behålls, resten skippas
KOMPLEXITET FÖR OPERATIONER PÅ DATASTRUKTURER Man kan ofta hitta komplexitet för en operation (på en datastruktur) genom att gå igenom hur den fungerar (och vad den faktiskt gör)
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first O(1) Remove last Remove Find O(1)
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Insert Remove first Remove last O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Insert Remove first Remove last O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Värsta fallet: i början - flytta alla efterföljande för att skapa plats (förutsatt att det finns plats) Remove last O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first Remove last O(1) O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Värsta fallet: i början - flytta alla efterföljande för att skapa plats (förutsatt att det finns plats) Det blir en lucka. Alla kvarvarande element måste flyttas ett steg bakåt Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first Remove last O(1) O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Värsta fallet: i början - flytta alla efterföljande för att skapa plats (förutsatt att det finns plats) Det blir en lucka. Alla kvarvarande element måste flyttas ett steg bakåt Ta bort det med högst index Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first Remove last Remove Find O(1) O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Värsta fallet: i början - flytta alla efterföljande för att skapa plats (förutsatt att det finns plats) Det blir en lucka. Alla kvarvarande element måste flyttas ett steg bakåt Ta bort det med högst index Värsta fallet: i början - flytta alla efterföljande för att täppa till lucka
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Insert first Insert last Insert Remove first Remove last Remove Find O(1) O(1) Alla som redan ligger i arrayen måste flyttas ett steg framåt för att skapa plats (förutsatt att det finns plats) Lägg in på nästa lediga plats (förutsatt att det finns en) Värsta fallet: i början - flytta alla efterföljande för att skapa plats (förutsatt att det finns plats) Det blir en lucka. Alla kvarvarande element måste flyttas ett steg bakåt Ta bort det med högst index Värsta fallet: i början - flytta alla efterföljande för att täppa till lucka Värsta fallet: Det eftersökta finns inte i listan - alla element måste genomsökas
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Insert last O(1) O(1) Insert Remove first O(1) Remove last O(1) O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Insert Remove first O(1) Remove last O(1) O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Remove first O(1) Remove last O(1) O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Värsta fall: I slutet - sök upp noden Remove first O(1) Remove last O(1) O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Remove first O(1) Värsta fall: I slutet - sök upp noden Ta bort vid head Remove last O(1) O(1) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Remove first O(1) Remove last O(1) O(1) Värsta fall: I slutet - sök upp noden Ta bort vid head Ta bort vid tail (föregående nod nås via länk bakåt) Remove Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Remove first O(1) Remove last O(1) O(1) Remove Värsta fall: I slutet - sök upp noden Ta bort vid head Ta bort vid tail (föregående nod nås via länk bakåt) Värsta fall: i slutet - sök upp noden Find
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Insert first O(1) Länka in vid head Insert last O(1) O(1) Länka in vid tail Insert Remove first O(1) Remove last O(1) O(1) Remove Find Värsta fall: I slutet - sök upp noden Ta bort vid head Ta bort vid tail (föregående nod nås via länk bakåt) Värsta fall: i slutet - sök upp noden Värsta fall: finns inte - sök igenom hela listan
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Balanserat Binärt Sökträd Insert first O(1) X Insert last O(1) O(1) X Insert O(log n) Remove first O(1) X Remove last O(1) O(1) X Vid sökning efter rätt plats i trädet halveras sökmängden för varje iteration Remove O(log n) Find O(log n)
KOMPLEXITETER PÅ DATASTRUKTURERNA Värsta fallet: degenererat träd (beter sig som en länkad lista). Sökmängden halveras aldrig utan alla element måste i värsta fallet sökas igenom Lista Array Lista Dubbellänkad lista med head och tail Balanserat Binärt Sökträd Obalanserat Binärt Sökträd Insert first O(1) X X Insert last O(1) O(1) X X Insert O(logn) Remove first O(1) X X Remove last O(1) O(1) X X Remove O(logn) Find O(logn)
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Balanserat Binärt Sökträd Obalanserat Binärt Sökträd Insert first O(1) X X Insert last O(1) O(1) X X Insert O(logn) Remove first O(1) X X Remove last O(1) O(1) X X Remove O(logn) Find O(logn)
KOMPLEXITETER PÅ DATASTRUKTURERNA Lista Array Lista Dubbellänkad lista med head och tail Balanserat Binärt Sökträd Obalanserat Binärt Sökträd Insert first O(1) X X Insert last O(1) O(1) X X Insert O(logn) Remove first O(1) X X Remove last O(1) O(1) X X Remove O(logn) Find O(logn)?