Detta skapar en PDF som du sedan kan skriva ut. Du kan även spara ner PDFn och skriva ut senare.
Titel på utskriften?
Tack för ditt bidrag
Om vi kan använda det så lägger vi upp det på sidan. Nedan en länk till ditt bidrag om du vill spara det.
Spara som ...
Du sparar ditt skript under detta namn och kan sedan hämta tillbaka det med samma namn.
Läs in
Läs in ett tidigare sparat skript. Obs att du enbart kan läsa in skript i den webbläsare där du sparade skriptet. Vill du kunna läsa in och spara skript oberoende av webbläsare, så behöver du skaffa ett login (enkelt och gratis).
Skicka in bidrag
Föreslå rubrik
Beskriv vad din kod gör
Skapa kort länk
Använd en kort URL för att skicka länk till koden via SMS eller epost. När mottagaren klickar på länken, så öppnas denna webbsida, med din kod och din text. Länken rensas bort automatiskt om den inte används.
Rubrik (frivilligt)
Beskrivning (frivilligt)
Länk (kopiera hela)
Träd
Ett träd är en datastruktur som efterliknar hur träd ser ut. Vi har en stam (root) som förgrenar sig i grenar som förgrenar sig i ännu mer grenar och ytterst sitter ett löv.
egenskaper
Om man tänker sig att en länkad lista's kännetecken är att om du befinner dig i en nod, så finns där en node.next, som leder till nästa nod, såtillvida inte node.next är None. Och du kan enkelt i en länkad lista, genom att koppla om node.next, montera in en ny nod mellan två existerande. Eller ta bort en nod genom att koppla förbi den.
Ett träd fungerar likadant, fast du har här två eller fler noder med vars hjälp du kan vandra ut i trädet. Om det är två noder (binärt träd) heter de oftast left och right. Så node.left leder till vänster delträd och node.right leder till högra. Om det är ett träd med godtyckligt många grenar (förgreningar), så ligger oftast alla grenar i en lista med namnet children och du kan komma åt grenarna genom att loopa över children.
Denna enkla introduktion till träd handlar om träd med godtyckligt många grenar.
Notera symmetrierna i ett träd. Vi kan klippa ut ett delträd (subtree) och det nya delträdet vi klippt ut har då fått en ny root. Rooten är bra hålla reda på, det är dels själva pekaren till trädet men också där trädet börjar.
Notera också hur en parent (förälder) har children (barn).
Varje nod kan t.ex. innehålla en lista med alla children. Dvs, om vi befinner oss i en nod, då kan vi loop:a över alla children. Notera att en typisk child kan vara parent till nya children.
Löven längst ut på trädet kännetecknas av att de saknar children. Listan med children är None.
Så, vill vi vandra nedåt i trädet kan vi göra det genom alla children. En typisk nod har ofta pekare till sin parent, så att vi även skall kunna vandra uppåt i trädet. Rooten har ingen parent, så vi känner igen rooten genom att parent är None.
En nod innehåller oftast någon typ av data. Hur många barn (förgreningar) en nod har kallas också för nodens grad. Så, en nod med 2 barn är av grad 2. Trädets grad räknas ut genom att titta på den nod som har högst grad (dvs flest barn, förgreningar, children = kärt barn har många namn!).
Det var en snabb genomgång av de flesta begrepp. Repetera nu för dig själv; Träd, rot, subträd, nod, förälder, barn, children, parent, löv, förgreningar, noden och trädets grad. Om du begriper dessa någorlunda har du kommit långt!
Låt oss skapa ett enkelt träd. Vi tar fasta på att varje nod innehåller data samt en lista med children, ifall sådana existerar. Dessa children är i sin tur en nod som kan ha children o.s.v. i all evighet.
class Node:
def __init__(self, data=None, children=None):
self.data = data
self.children = children if children is not None else []
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
game = Node('1')
print_tree(game)
class Node:
def __init__(self, data=None, children=None):
self.data = data
self.children = children if children is not None else []
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
game = Node('1')
print_tree(game)
I begynnelsen är trädet väldigt litet. Men vi kan enkelt bygga ut trädet. Vi kan skapa trädet direkt med vår klass Node eftersom våra barn ligger i en lista.
undvika delad lista
Det är lätt att tänka tanken konstruera en Node såhär
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
Om du inte genast börjar tvivla på denna konstruktion, ta en kort paus och gå igenom en kort sida om problemet med default argument och listor. När du gjort det, så är konstruktionen nedan glasklar.
class Node:
def __init__(self, name="", data=None, children=None):
self.name = name
self.data = data
self.children = children if children is not None else []
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + tree.name + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
game1 = Node('a','1', [Node('b','2'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5'), Node('f','6')])
print_tree(game2)
class Node:
def __init__(self, name="", data=None, children=None):
self.name = name
self.data = data
self.children = children if children is not None else []
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + tree.name + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
game1 = Node('a','1', [Node('b','2'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5'), Node('f','6')])
print_tree(game2)
För att hjälpa dig koda och labba med träd, här har du ytterligare en utskriftsfunktion av trädet som du kan kopiera. Du behöver kunna printa ut trädet för att labba och lära, men att göra en snygg utskriftsfunktion kräver en hel del insikter, så det är ett moment 22.
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
def print_tree(root, prefix="", is_last=True):
print(prefix, "└─ " if is_last else "├─ ", root.name, ": ", root.data, sep="")
prefix += " " if is_last else "│ "
child_count = len(root.children)
for i, child in enumerate(root.children):
is_last_child = (i == (child_count - 1))
print_tree(child, prefix, is_last_child)
game1 = Node('a','1', [Node('b','2'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5'), Node('f','6')])
print_tree(game2)
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
def print_tree(root, prefix="", is_last=True):
print(prefix, "└─ " if is_last else "├─ ", root.name, ": ", root.data, sep="")
prefix += " " if is_last else "│ "
child_count = len(root.children)
for i, child in enumerate(root.children):
is_last_child = (i == (child_count - 1))
print_tree(child, prefix, is_last_child)
game1 = Node('a','1', [Node('b','2'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5'), Node('f','6')])
print_tree(game2)
Nedan har du ytterligare en avancerad utskriftsfunktion. Den tog några timmar att koda ihop, så använd den nu för bövelen! Du kan säkert ta det ytterligare några nivåer.
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
class Tree:
def addNodes(self,r):
self.root = r
def printNodes(self,node, d=0, lr=''):
def cap(x,c):
if(x>c):
x=c
return x
if(node==None or node.children is None):
return
A = node.children
B = A[:1+len(A)//2]
C = A[1+len(A)//2:]
if(B):
for i in range(len(B)):
self.printNodes(B[i],d+1,'┌' if i==0 else '│')
self.c[d] += (1 if lr =='┌' or lr =='│' else -1)
if self.c[d]<0:
self.c[d]=0
if(lr=='└'):
self.c[d]=0
if(lr=='┌'):
self.c[d+1]=0
vbrack = ''.join([' ',' │'][cap(self.c[i],1)] for i in range(1,len(self.c)) if i < d)
print(vbrack+ ('' if d==0 else ' ') + lr +'──' +'(' +str(node.name)+str(node.data)+')')
if(C):
for i in range(len(C)):
self.printNodes(C[i],d+1,"└" if i == (len(C)-1) else '│')
def print(self):
self.c = [0 for x in range(20)]
self.printNodes(self.root)
tree = Tree()
game1 = Node('a','1', [Node('b','2'), Node('c','3'), Node('c','3'), Node('c','3'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5',[game1,game1,game1]), Node('f','6',[game1])])
tree.addNodes(game2)
tree.print()
class Node:
def __init__(self, name="", data=None, children=[]):
self.name = name
self.data = data
self.children = children
class Tree:
def addNodes(self,r):
self.root = r
def printNodes(self,node, d=0, lr=''):
def cap(x,c):
if(x>c):
x=c
return x
if(node==None or node.children is None):
return
A = node.children
B = A[:1+len(A)//2]
C = A[1+len(A)//2:]
if(B):
for i in range(len(B)):
self.printNodes(B[i],d+1,'┌' if i==0 else '│')
self.c[d] += (1 if lr =='┌' or lr =='│' else -1)
if self.c[d]<0:
self.c[d]=0
if(lr=='└'):
self.c[d]=0
if(lr=='┌'):
self.c[d+1]=0
vbrack = ''.join([' ',' │'][cap(self.c[i],1)] for i in range(1,len(self.c)) if i < d)
print(vbrack+ ('' if d==0 else ' ') + lr +'──' +'(' +str(node.name)+str(node.data)+')')
if(C):
for i in range(len(C)):
self.printNodes(C[i],d+1,"└" if i == (len(C)-1) else '│')
def print(self):
self.c = [0 for x in range(20)]
self.printNodes(self.root)
tree = Tree()
game1 = Node('a','1', [Node('b','2'), Node('c','3'), Node('c','3'), Node('c','3'), Node('c','3')])
game2 = Node('d','4', [game1, Node('e','5',[game1,game1,game1]), Node('f','6',[game1])])
tree.addNodes(game2)
tree.print()
Traversering av träd
Beroende på vad vi vill göra, så vill vi traversera trädets noder i olika ordning.
in-order
4
2
5
1
6
3
7
pre-order
1
2
4
5
3
6
7
post-order
4
5
2
6
7
3
1
level-order
1
2
3
4
5
6
7
in-order
In-order är vanligtvis bara vettigt om vi har ett binärt träd. Algoritmen är:
1. Gå igenom vänster delträd
2. Beakta rooten (skriv ut eller gör vad du vill)
3. Gå igenom höger delträd
4
2
5
1
6
3
7
pre-order
Algoritmen är:
1. Beakta rooten (skriv ut eller gör vad du vill)
2. Gå igenom vänster delträd
3. Gå igenom höger delträd
1
2
4
5
3
6
7
post-order
Algoritmen är:
1. Gå igenom vänster delträd
2. Gå igenom höger delträd
3. Beakta rooten (skriv ut eller gör vad du vill)
4
5
2
6
7
3
1
level-order
Innebär att vi traverserar noderna nivå för nivå med start från level 0 (rooten). Algoritmen är lite mer komplicerad och förutsätter att vi använder en kö. Vi kan enkelt skapa en kö i python med en lista och använda append (push) samt pop(0) (obs viktigt med 0:an, annars får vi en stack)
1. Skapa en tom kö
2. Placera rooten i kön
3. Loopa sålänge kön innehåller något och gör nedan:
3a. Plocka nod ur kön och beakta denna (skriv ut t.ex.)
3b. Placera nodens barn i kön.
1
2
3
4
5
6
7
class Node:
def __init__(self, data=None, children=None):
self.data = data
self.children = children if children is not None else []
# När vi printar trädet är det pre-order
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
t = Node('1', [
Node('2',
[
Node('4'),
Node('5')]),
Node('3',
[
Node('6'),
Node('7')])
])
print_tree(t)
def print_inorder(node):
if(node.children):
print_inorder(node.children[0])
print(node.data, end="->")
print_inorder(node.children[1])
else:
print(node.data, end="->")
def print_preorder(node):
print(node.data, end="->")
if(node.children):
for child in node.children:
print_preorder(child)
def print_postorder(node):
if(node.children):
for child in node.children:
print_postorder(child)
print(node.data, end="->")
def print_levelorder(root):
if (not root):
return
queue = []
queue.append(root)
while (len(queue) > 0):
node = queue.pop(0)
print(node.data, end="->")
if(node.children):
for child in node.children:
queue.append(child)
print("\ninorder:")
print_inorder(t)
print("\npreorder:")
print_preorder(t)
print("\npostorder:")
print_postorder(t)
print("\nlevelorder:")
print_levelorder(t)
class Node:
def __init__(self, data=None, children=None):
self.data = data
self.children = children if children is not None else []
# När vi printar trädet är det pre-order
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
if tree.children:
for child in tree.children:
print_tree(child,d+1)
t = Node('1', [
Node('2',
[
Node('4'),
Node('5')]),
Node('3',
[
Node('6'),
Node('7')])
])
print_tree(t)
def print_inorder(node):
if(node.children):
print_inorder(node.children[0])
print(node.data, end="->")
print_inorder(node.children[1])
else:
print(node.data, end="->")
def print_preorder(node):
print(node.data, end="->")
if(node.children):
for child in node.children:
print_preorder(child)
def print_postorder(node):
if(node.children):
for child in node.children:
print_postorder(child)
print(node.data, end="->")
def print_levelorder(root):
if (not root):
return
queue = []
queue.append(root)
while (len(queue) > 0):
node = queue.pop(0)
print(node.data, end="->")
if(node.children):
for child in node.children:
queue.append(child)
print("\ninorder:")
print_inorder(t)
print("\npreorder:")
print_preorder(t)
print("\npostorder:")
print_postorder(t)
print("\nlevelorder:")
print_levelorder(t)
Ofta i en nod i ett träd, så finns en referens parent som refererar till föräldern. Detta kan göra manipulation eller beräkningar lättare. Vi kan t.ex. enkelt härleda fullständiga vägen från roten till en nod (se findPath nedan).
class Node:
def __init__(self, data=None, children=None):
self.parent = None
self.data = data
self.children = children if children is not None else []
for child in self.children:
child.parent = self
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
for child in tree.children:
print_tree(child,d+1)
def findPath(node, data):
path = ""
if node.data == data:
while(node is not None):
path = node.data + '/' + path
node=node.parent
return path
for child in node.children:
result = findPath(child, data)
if result:
return result
game = Node('1', [Node('2'), Node('3',[Node('4')])])
print_tree(game)
print()
print()
print("path=",findPath(game, '4'))
class Node:
def __init__(self, data=None, children=None):
self.parent = None
self.data = data
self.children = children if children is not None else []
for child in self.children:
child.parent = self
def print_tree(tree, d=0):
if(tree):
print("\n" + " "*d + '('+str(tree.data)+')',end="->")
for child in tree.children:
print_tree(child,d+1)
def findPath(node, data):
path = ""
if node.data == data:
while(node is not None):
path = node.data + '/' + path
node=node.parent
return path
for child in node.children:
result = findPath(child, data)
if result:
return result
game = Node('1', [Node('2'), Node('3',[Node('4')])])
print_tree(game)
print()
print()
print("path=",findPath(game, '4'))
insert och delete
Såklart vill vi ofta sätta in eller ta bort noder i trädet. Om vi ska sätta in en ny nod letar vi först reda på noden med find. Därefter hänger vi på ny data där. Delete tar bort en nod. Om noden har barn (children) så omlokaliserar vi dem först så att de inte blir föräldrarlösa.
class Node:
def __init__(self, data=None, children=None):
self.parent = None
self.data = data
self.children = children if children is not None else []
for child in self.children:
child.parent = self
def print_tree(tree, d=0):
if tree:
print("\n" + " " * d + '(' + str(tree.data) + ')', end="->")
if tree.children:
for child in tree.children:
print_tree(child, d + 1)
def insert(parent, data):
new_node = Node(data)
new_node.children = None
new_node.parent = parent
parent.children.append(new_node)
return new_node
def find(node, data):
if node.data == data:
return node
for child in node.children:
result = find(child, data)
if result:
return result
return None
def delete(node):
if node.parent:
node.parent.children.remove(node)
for child in node.children:
child.parent = node.parent
node.parent.children.append(child)
node.parent = None
node.children = []
t = Node('Fritidsaktiviteter', [
Node('Musik',
[
Node('Piano'),
Node('Mandolin')]),
Node('Sport',
[
Node('Gräs'),
Node('Is',[
Node('Ishockey'),
Node('Konståkning')
])])
])
print_tree(t)
node = find(t, 'Ishockey')
print("\n\nhittade:",node.data)
print("Tar bort denna nod")
delete(node)
print_tree(t)
print("\n\nStoppar in ny nod")
node = find(t, 'Is')
insert(node, 'Bandy')
print_tree(t)
class Node:
def __init__(self, data=None, children=None):
self.parent = None
self.data = data
self.children = children if children is not None else []
for child in self.children:
child.parent = self
def print_tree(tree, d=0):
if tree:
print("\n" + " " * d + '(' + str(tree.data) + ')', end="->")
if tree.children:
for child in tree.children:
print_tree(child, d + 1)
def insert(parent, data):
new_node = Node(data)
new_node.children = None
new_node.parent = parent
parent.children.append(new_node)
return new_node
def find(node, data):
if node.data == data:
return node
for child in node.children:
result = find(child, data)
if result:
return result
return None
def delete(node):
if node.parent:
node.parent.children.remove(node)
for child in node.children:
child.parent = node.parent
node.parent.children.append(child)
node.parent = None
node.children = []
t = Node('Fritidsaktiviteter', [
Node('Musik',
[
Node('Piano'),
Node('Mandolin')]),
Node('Sport',
[
Node('Gräs'),
Node('Is',[
Node('Ishockey'),
Node('Konståkning')
])])
])
print_tree(t)
node = find(t, 'Ishockey')
print("\n\nhittade:",node.data)
print("Tar bort denna nod")
delete(node)
print_tree(t)
print("\n\nStoppar in ny nod")
node = find(t, 'Is')
insert(node, 'Bandy')
print_tree(t)