Decimalt | Binärt | Oktalt | Hexadecimalt |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 10 | 2 | 2 |
3 | 11 | 3 | 3 |
4 | 100 | 4 | 4 |
5 | 101 | 5 | 5 |
6 | 110 | 6 | 6 |
7 | 111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 | 16 | E |
15 | 1111 | 17 | F |
16 | 10000 | 20 | 10 |
17 | 10001 | 21 | 11 |
18 | 10010 | 22 | 12 |
19 | 10011 | 23 | 13 |
20 | 10100 | 24 | 14 |
Fråga: Hur skriver man talet n binärt?
Rekursivt svar: Först skriver man n/2 (heltalsdivision) binärt
och sen skriver man en nolla eller etta beroende på om n var jämnt eller udda,
...men talen 0 och 1 skrivs likadant binärt.
def writebinary(n): if n == 0 or n == 1: print n, else: writebinary(n/2) print n%2,
def iso2utf(strang): """ Konverterar från iso8859 till utf-8 """ ustrang = strang.decode('iso8859-1') return ustrang.encode('utf-8')
bintree.py
och vi vill använda det som en abstrakt ordlista.
För en abstrakt ordlista bör åtminstone tre anrop finnas:
exists
, put
och write
.
wordlist.exists(word)
Returnerar True om ordet finns i trädet wordlist.put(word)
Sorterar in ett nytt ord i trädet wordlist.write()
Skriver ut alla ord i bokstavsordning finns(p,value)
och därför definierar man ytterligare tre
metoder i filen bintree.py
, men ovanför klassen Bintree
.
Den metod som anropas,
wordlist.exists(word)
,
innehåller bara en sats.
def exists(self,value): return finns(self.root,value)
Den låter alltså
finns
göra jobbet. Varför kan då inte
huvudprogrammet direkt göra anropet if finns(wordlist.root,word)
?
Det skulle ju strida mot abstraktionen - det är inte meningen att någon
utomstående ens ska känna till att det finns en root
!
Svårast att implementera är insättningen. Man skulle tro att satsen
putta(self.root,newvalue)
skulle kunna skicka vidare jobbet till en rekursiv metod putta
,
men det går inte. När trädet är tomt är rotpekaren None
, men när
den första noden sätts in ska rotpekaren peka på den. Men self.root
kan bara ändras inifrån objektet, så därför får man skriva så här.
def put(self,newvalue): self.root = putta(self.root,newvalue)Anropet till putta returnerar en pekare till det nya trädet och den läggs in i
self.root
.
Så här blir principen för putta:
def putta(p,newvalue): if p == None: # Skapa en ny nod med det nya - - - # värdet och returnera den if newvalue < p.value: p.left = putta(p.left,newvalue) # Rekursiv inputtning elif newvalue > p.value: p.right = putta(p.right,newvalue) else: # Värdet fanns redan i trädet! - - - return p # Returnera pekare till det # modifierade trädet |
Dessutom kan ju användaren hela tiden använda
exists
-funktionen för att kontrollera om det den har för
avsikt att lägga till redan finns i trädet...
class Node: def __init(self, key, info): self.key = key # Det som man sorterar på self.info = info # Objekt med information om key self.left = None self.right = NoneSökmetoden
getInfo(key)
blir likadan som exists
men returnerar p.info
i stället för True/False
.
Det här inträffar i praktiken oftare än man kan tro, till exempel när nyfödda förs in i ett träd sorterat på personnummer och då alltid hamnar längst till höger, eller när vi lägger in tidningsartiklar sorterade efter publiceringsdatum.
Det finns många sätt att göra om ett obalanserat träd till ett balanserat. Till exempel kan man spara hela trädet i en (sorterad) lista och skapa trädet på nytt genom att ta elementen i lämplig ordning. Att göra om hela trädet tar O(n) varje gång.
Bättre är att se till att trädet är balanserat efter varje insättning. Ett sätt att göra det är röd-svarta träd där man ger varje nod en extra egenskap (röd eller svart) och ställer upp regler för hur noderna ska vara ordnade. Om reglerna tillämpas varje gång man lägger till eller plockar bort en nod så hålls trädet balanserat. Mer om detta kan man lära sig i fortsättningskursen DD1352 Algoritmer, datastrukturer och komplexitet.