DD1320 Tillämpad Datalogi
Föreläsning 3: Komplexitetsanalys, sökning, rekursion
- Läs i boken: kap 3 och 4, utom 3.2.3, 3.4.3, 4.3.3, 4.4 (som kommer senare)
- Komplexitetsanalys
- Linjärsökning
- Binärsökning
Komplexitetsanalys
Det är intressant att se tidsåtgången för en algoritm.
Denna anges ofta som funktion av indatas storlek,
som av tradition kallas n
.
Exempel: För sortering är n
antalet tal som ska sorteras.
Hur växer tidsåtgången T(n)
för växande n
?
|
            n     |
        log(n)         |
      nlog(n)       |
        n2         |
        2n         |
10 | 10 s | 1 s | 10 s | 100 s | 17 min |
100 | 100 s | 2 s | 3 min | 2 tim | 1022 år |
10000 | 10000 s (ca 3 tim) | 4 s | 11 tim | 3 år | |
Vi analyserar oftast värsta fallet (det är i regel
enklare att räkna på) men man kan också räkna på medelfallet.
Istället för att ange den exakta tidsfunktionen T(n)
nöjer vi
oss med att ange ordoklassen O(n)
.
Definition
T(n)
är O(F(n))
om det finns positiva konstanter
c
och n0
sådana att 0<=T(n)<=cF(n)
för n>=n0
Vad innebär detta?
-
cF(n)
anger en övre gräns för T(n)
då n
är stort.
- Vi behöver bara ta bara med den term som växer snabbast.
- Vi kan bortse från multiplikation med konstant.
- Det spelar ingen roll vilken logaritm vi använder.
Exempel:
T(n) = 10n2 + 100n + 10logn + 1000
säger vi är O(n2)
.
- För små indata är analys onödig - använd den enklaste algoritmen!
- Inläsning från fil tar längre tid än åtkomst av redan inlästa värden.
- Minnesåtgång kan också vara relevant.
Uppgift: Matrismultiplikation
Vad är komplexiteten för matrismultiplikation?
Sökning
Förutsättningar:
- Vi söker efter något element i en lista med n element.
- Det element vi söker efter karakteriseras av en söknyckel (eng key) men kan också ha andra data.
Frågor:
- Vad ska hända om det sökta elementet inte finns med?
- Kan det finnas flera element med samma nyckel? Vill man isåfall hitta alla?
Linjärsökning (Sequential search)
Algoritm:
- Sök igenom elementen i tur och ordning.
- Bryt när det sökta elementet påträffas eller när det uppenbaras att det sökta elementet
inte finns med.
Linjärsökning är O(n)
(i värsta fallet måste vi titta på alla n elementen).
Här följer en funktion för linjärsökning i en lista.
def sequentialSearch(alist, item):
for x in alist:
if x == item:
return True
return False
Binärsökning
Om listan är sorterad är den snabbaste sökningsalgoritmen binärsökning.
Algoritm:
- Beräkna intervallets mittpunkt.
- Avgör om det sökta elementet finns i första eller andra halvan och fortsätt söka där.
11 | 13 | 13 | 20 | 22 | 25 | 28 | 30 | 31 | 32 | 32 | 48 | 62 |
11 | 13 | 13 | 20 | 22 | 25 |
     |      |      |      |      |      |      |
     |      |      | 20 | 22 | 25 |
     |      |      |      |      |      |      |
     |      |      |      |      | 25 |
     |      |      |      |      |      |      |
Binärsökning är O(log n)
i värsta fallet:
Vi söker bland n
element och undrar hur många varv sökningen kan ta.
Antal element att söka bland halveras i varje varv, så första varvet får vi
n/2
, andra varvet n/4
, tredje varvet n/8
. Vi är klara när det bara finns ett
element kvar att titta på och då är n/2x=1
där x
är antal varv.
Vi två-logaritmerar bägge led och får att x=2log(n)
.
Här följer en funktion för binärsökning (kursboken s. 146):
def binarySearch(alist, item):
"""Söker i "alist" efter "item". Returnerar True om den hittas, False annars"""
first = 0
last = len(alist)-1
found = False
while first <= last and not found:
midpoint = (first + last)/2
if alist[midpoint] == item:
found = True
else:
if item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return found