Primerjava različnih algoritmov

Primerjava različnih algoritmov

Avtor: Matija Lokar

Problem

  • Sestavi funkcijo indeks(x, sezL) , ki vrne indeks mesta, kjer v seznamu sezL prvič nastopa x . Če x v seznamu ni, naj vrne dolžino seznama sezL .

sezL = [1, 3, 5, 3, 2, 4]
print(indeks(3, sezL)) # dobimo 1
print(indeks(4, sezL)) # dobimo 5
print(indeks(13, sezL)) # dobimo 6

Različni algoritmi

  • Dejansko so vse ideje enake, le njihova realizacija bo različna

    • Uporabili bomo različne konstrukte v Pythonu
    • Ideja: zaporedoma primerjaj elemente iz seznama z iskanim elementom
  • Uporaba zanke while
  • Uporaba iteriranja po vrednostih
  • Uporaba iteriranja po indeksih
  • Uporaba stražarja

Iteracija po indeksih

for i in range(len(sezL)):
   if sezL[i]== x:
     return i
 return len(sezL) #zanka for se je
  # zaključila, torej ga ni

Iteracija po vrednostih

Potrebujemo "svoj" indeks

i = 0
for vred in sezL:
  if vred == x:
    return i
  i = i + 1
return len(sezL) #zanka for se je
 # zaključila, torej ga ni

Iteracija po vrednostih (2)

Znebimo se funkcije len i je tako ali tako ravno len(sezL)

i = 0
for vred in sezL:
  if vred == v:
    return i
  i = i + 1
return i #zanka for se je
 # zaključila, torej ga ni

Zanka while

i = 0
while sezL[i] != x:
      i = i + 1
return i

  • Zakaj ni v redu?
  • Popravek:

while i != len(sezL) and sezL[i] != x:
   i = i + 1
return i

Uporaba "stražarja"

  • Pri zanki while po nepotrebnem (razen zadnjič) preverjamo, če smo še "znotraj"
  • Zato na koncu dodamo stražarja – kar element, ki ga iščemo! sezL.append(x)
         i = 0
         while sezL[i] != x:
             i = i + 1
         # ne pozabimo se znebiti stražarja!
         sezL.pop()
         return i

In pa seveda

  • Vgrajena funkcija!

    • sezL.index(x)
    • Vendar, kaj se zgodi, če elementa ni?

      • Izjema (ValueError)

try:
    rez = sezL.index(x)
except ValueError:
    rez = len(sezL)
return rez

(10.jpg)

St1

def indeks(x, sezL):
  length = len(sezL)
  for i in range(0,length):
     if x == sezL[i]:
        return i; # element x je element seznama
 return length; # vrni dolzino, ce x
  # ni element seznama

St2

def indeks(x,sezL):
    for i in range(len(sezL)):
        if sezL[i]==x:
                return [i]
    return len(sezL)

St3

def indeks(x, sezL):

    sez = [] #ustvarim prazen seznam
    dolSez = len(sezL) #dolzina danega seznama
    for i in range(dolSez):
        if sezL[i] == x: #preverim pogoj, ali na i-tem mestu seznama obstaja x
                sez.append([i]) #seznam vseh mest, kjer se nahaja x

    n = len(sez) #dolzina seznama mest, kjer se nahaja x
    if n == 0:
        return dolSez
    else:
        return sez[0]

St4

def indeks(v, sezL):
    dolzina=len(sezL)
    if v in sezL:
        for i in range(dolzina):
            if v==sezL[i]:
                return i
            i=i+1
    else:
        return dolzina

Merjenje časa

  • import time
  • time.time() # dobimo nek čas v sekundah
    t1 = time.time()
    … NEKAJ
    t2 = time.time()
    časIzvajanja = (t2 – t1)*1000
  • Čas izvajanja je v milisekundah

Merjenje časa

Funkcija za merjenje

def izmeriČas(išči, x, sezL):
'''Koliko časa traja, da funcija z imenom, kot ga določa išči, poišče vrednost x v seznamu sezL'''
   t1 = time.clock()
   išči(x, sezL)
   t2 = time.clock()
   return (t2 - t1) * 1000.

Uporaba

  • sezL = range(100000)
  • časMet1 = izmeriČas(metoda1, 10, sezL)
  • časMet2 = izmeriČas(metoda2, 10, sezL)
  • časMet3 = izmeriČas(metoda3, 10, sezL)
  • Vse metode se imenujejo enako
  • import Met1, Met2, Met3
  • časMet1 = izmeriČas(Met1.indeks, 10, sezL)
  • časMet2 = izmeriČas(Met2.indeks, 10, sezL)
  • časMet3 = izmeriČas(Met3.indeks, 10, sezL)

MerjenjeIndeks.py

import time
import Met1, Met2, Met3, Met4, Met5, Met6

def izmeriČas(išči, x, sezL):
   '''Koliko časa traja, da funcija z imenom, kot ga določa išči,
      poišče vrednost x v seznamu sezL'''
   t1 = time.clock()
   išči(x, sezL)
   t2 = time.clock()
   return (t2 - t1) * 1000.

def izpišiČase(x, sezL):
   '''izpiši število milisekund, ki jih različne metode potrebujejo,
     da izvedejo metodo indeks(x, sezL).
     metoda je (z enakim imenom) v datotekah Met1.py, Met2.py, ...
   ''' 

MerjenjeIndeks.py

časM1 = izmeriČas(Met1.indeks,x, sezL) # iteracija po indeksih
časM2 = izmeriČas(Met2.indeks,x, sezL) # iteracija po vrednostih
časM3 = izmeriČas(Met3.indeks,x, sezL) # iteracija po vrednostih, brez len
časM4 = izmeriČas(Met4.indeks,x, sezL) # zanka while
časM5 = izmeriČas(Met5.indeks,x, sezL) # zanka while s stražarjem
časM6 = izmeriČas(Met6.indeks,x, sezL) # vgrajen index

print
("{0:>10d}{1:10.2f}{2:10.2f}{3:10.2f}{4:10.2f}{5:10.2f}{6:10.2f}".format \
        (x, časM1, časM2, časM3, časM4, časM5, časM6))
# konec izpiši čase

for velPoskusa in [10**5, 10**6, 10**7] :
    L = list(range(velPoskusa + 1))
    izpišiČase(1000, L)
    izpišiČase(velPoskusa // 2, L)
    izpišiČase(velPoskusa + 1, L)
    print('='*65)

Rezultati


      1000      0.55      0.66      0.70      1.21      0.73      0.15
     50000     29.27     31.16     32.18     63.11     35.44      6.66
    100001     58.68     28.50     25.94     48.29     27.45      5.14
=================================================================
      1000      0.22      0.25      0.24      0.45      0.25      0.06
    500000    117.13    143.76    145.58    255.31    144.56     25.60
   1000001    224.12    281.63    275.28    504.24    285.75     52.35
=================================================================
      1000    205.31      5.10      4.26      1.20     71.51     14.67
   5000000   1686.30   1469.95   1480.46   2577.09   1480.01    257.55
  10000001   2352.30   2813.75   2820.62   4957.93   2779.80    590.91
=================================================================
 časM1 = … # iteracija po indeksih
 časM2 = … # iteracija po vrednostih
 časM3 = … # iteracija po vrednostih, brez len
 časM4 = … # zanka while
 časM5 = … # zanka while s stražarjem
 časM6 = … # vgrajen index

Kaj nam povedo ti rezultati!

Kaj lahko sklepamo o časovni zahtevnosti?

Iskanje v naključnem seznamu

def nakljucniSeznam(dol = 10**6, stev = 10**6):
   ''' naključni seznam velikost dol, s števili
       med 1 in stev '''
   sez = [random.randint(1, stev) for i in range(dol)]
   return sez


L = nakljucniSeznam();
izpišiČase(L[len(L)//2], L)#iščemo srednji element, ki zagotovo je
izpišiČase(-100, L) # iščemo -100, ki ga ni

Rezultati


 646195     43.25     50.86     50.80    100.92     52.34     12.61
   -100     81.32     96.64     93.52    197.70    103.34     21.01

 časM1 = … # iteracija po indeksih
 časM2 = … # iteracija po vrednostih
 časM3 = … # iteracija po vrednostih, brez len
 časM4 = … # zanka while
 časM5 = … # zanka while s stražarjem
 časM6 = … # vgrajen index

Primerjava z vašimi idejami


      1000      0.13      0.15      0.12      0.12     12.05      0.14
     50000      3.96      4.75      4.24      4.01      8.13      7.15
    100001      8.03      9.82      8.00      8.08      7.99      2.10
======================================================================
      1000      0.09      0.10      0.08      0.08     81.10      0.15
    500000     41.30     51.73     42.93     41.33     82.75     76.48
   1000001     85.97    101.48     82.60     85.56    123.54     22.24
======================================================================
      1000      0.09      0.10      0.08      0.08    832.57      0.15
   5000000    416.07    535.62    413.18    418.16    829.59    781.60
  10000001    871.97   1022.78    857.72    897.77    854.31    217.27
======================================================================
               M1         M5       St1       St2        St3       St4

Iskanje v naključnem seznamu


>>>
     90196     41.89     51.25     41.86     41.86     84.03     78.00
      -100     81.73    102.20     82.60     81.96     82.21     20.89
  ======================================================================
               M1         M5       St1       St2        St3       St4

>>>

0%
0%