Nekaj zgledov

Download Report

Transcript Nekaj zgledov

Python - rekurzija
Zgledi
Izpiši števila od 1 do n
Nerekurzivno
def izpis(n):
for i in range(1, n + 1):
print(i)
2
"Šefovsko razmišljanje"
Denimo, da imamo nekoga, ki zna izpisati števila
od 1 do n-1
Ali: imamo funkcijo izpisDoNminus1
def izpis(n):
izpisDoNminus1(n – 1)
print(n)
Kako bi bila videti funkcija izpisDoNminus1?
Enako kot izpis!
def izpis(n):
izpis(n – 1)
print(n)
3
Za n = 3
klic: izpis(3)
klic: izpis(2)
klic: izpis(1)
...
po opravljenem klicu izpis(1) se izpiše 2
po opravljenem klicu izpis(2) se izpiše 3
… klic izpis(0), pod njo bi sledil izpis(-1), itd.
vsak klic funkcije delo prelaga dalje.
Če delo samo prelagamo, ne bo nikoli narejeno!
Gordijski vozel prerežemo tako, da končno nekdo nekaj res
naredi.
4
Izpis(1)
Ne bo več prelagal dela, ampak res izpisal
def izpis(n):
if n == 1:
print(1)
return
izpis(n - 1)
print(n)
5
Dogajanje
klic: izpis(3)
zaustavitveni pogoj ni izpolnjen, zato:
klic: izpis(2)
zaustavitveni pogoj ni izpolnjen, zato:
klic: izpis(1)
zaustavitveni pogoj je izpolnjen
izpišemo 1
vrnemo se iz klica izpis(1)
vrnili smo se iz klica izpis(1)
izpišemo 2
vrnemo se iz klica izpis(2)
vrnili smo se iz klica izpis(2)
izpišemo 3
vrnemo se iz klica izpis(3)
vrnili smo se iz klica izpis(3)
končamo
6
Izpis nazaj
def izpisNazaj(n):
if n == 1:
print(1)
return
print(n)
izpisNazaj(n - 1)
7
Ven z 'a'-ji
Iz niza sestavi nov niz (ali lahko spremenimo
obstoječega?), ki pa ne vsebuje 'a' jev
def odstraniA(niz):
novi = ""
for znak in niz:
if znak != "a":
novi += znak
return novi
8
Rekurzivno
def odstraniA(niz):
if niz == "":
return ""
prvi = niz[0]
preostanek = niz[1:]
novi = odstraniA(preostanek)
if prvi != "a":
return prvi + novi
return novi
9
Fibonacci-jevo zaporedje
a0 = 1
a1 = 1
an = an-1 + an-2
Brez rekurzije
def a(n):
if n == 0 or n == 1:
return 1
sez = [1, 1]
for i in range(2, n + 1):
sez.append(sez[-2] + sez[-1])
return sez[-1]
10
Fibonacci - nerekurzivno
Verjetno lepše pa je takole
def a(n):
prvi = 1
drugi = 1
for i in range(n):
prvi, drugi = drugi, prvi + drugi
return prvi
11
Fibonacci - rekurzija
def fib(n):
if n == 0 or n == 1:
return 1
return fib(n-1) + fib(n-2)
12
Seznam besed v nizu
'Matija Mataja hruške prodaja'
['Matija', 'Mataja', 'hruške', 'prodaja']
>>> niz = 'Matija Mataja hruške prodaja'
>>> sez = niz.split(' ')
>>> sez
['Matija', 'Mataja', 'hruške', 'prodaja']
>>> niz = 'Matija
Mataja
hruške prodaja'
>>> sez = niz.split(' ')
>>> sez
['Matija', '', '', 'Mataja', '', '', '', '', '', '', 'hruške',
'prodaja']
>>>
13
Malo čaranja
def seznamBesed(niz):
return [i for i in niz.split(" ") if i != ""]
Seznamski izrazi
[izraz seznam pogoj]
Seveda znamo tudi brez čaranja
Recimo kar
def seznamBesed(niz):
return niz.split()
14
Kaj pa z rekurzijo?
Brez split seveda!
Postopek
Določi prvo besedo bes,
na preostanku niza niz rekurzivno izračunaj
seznam besed sez,
prvo besedo dodaj na začetek seznama sez in vrni
tako popravljen seznam sez.
15
Zaustavitveni pogoj
Več jih je!
Ko v obdelavo dobimo
niz z eno besedo
[beseda]
niz sestavljen iz samih presledkov
[]
prazen niz
[]
Kako prepoznamo primere:
preostanek je prazen niz
poskušamo pridobiti prvo besedo, a neuspešno
== ''
16
Koda
def seznamBesed(niz):
if niz == "":
return []
bes, preostanek = razdeliNaPrviBesedi(niz)
if bes == "":
return []
if preostanek == "":
return [bes]
sez = seznamBesed(preostanek)
sez.insert(0, bes)
return sez
17
razdeliNaPrviBesedi
Vračamo dva podatka!
Če niza "ni", vrnemo dva prazna niza (besedo in
preostanek)
Če je prvi znak presledek
Rezultat je tak, kot bi uporabili to funkcijo na nizu
brez prvega (rekurzivni klic)
Če pa prvi ni presledek
Poiščemo mesto, kje nastopa prvič
Find
Če vrne < 0, presledka ni
Če pa je, le razrežemo niz
18
Koda
def razdeliNaPrviBesedi(niz):
if niz == "":
return "", ""
if niz[0] == " ":
return razdeliNaPrviBesedi(niz[1:])
ind = niz.find(" ")
if ind < 0:
return niz, ""
return niz[:ind], niz[ind + 1:]
19