Upload
duongdieu
View
220
Download
1
Embed Size (px)
Citation preview
Struktur Data Tree(Pohon)
Husni
Based on Problem Solving with Algorithms & Data Structures - Release 3.0 - September 22, 2013
Introduction to TreesChapter 6
• Tree atau pohon sangat berdayaguna di bidangInformatika (Computer Science).
• Pohon menyediakan suatu struktur bagipenyimpanan, manipulasi dan penemuan kembaliinformasi yang efisien.
• Pohon dapat digunakan untuk memetakan relasiantar obyek atau sistem klasifikasi dalam dunianyata.
• Tree juga mengantarkan dasar untuk memahamiGraph Theory.
3
Why Trees?
By Ptelea (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
• Kita sering bekerja dengan pohon berakar atau rooted trees (berbentuk graf berarah) dan terlihat seperti ini:
4
Different Types of Trees
http://en.wikipedia.org/wiki/File:Binary_tree.svg
Root atau akar
Node interior
daun
edge atau cabang
• Our trees are upside down. The root is at the top and the leaves are at the bottom.
• The only reason for this is that we normally write and read from the top of the page to the bottom.
• It is easier to add things to the bottom of our diagrams.
• We start at the root and move down the tree.
• Usually our trees will be binary trees (a maximum of two branches from a node).
5
What is Special?
•One person chooses a subject and answers 20 questions with “yes” or “no” answers.
• This is an example of following one branch of a binary tree as each question leads to only two possible answers.
• In theory (with well designed questions) this can lead to differentiating 220 (over a million) different subjects.
6
Example: 20 questions
• Most file systems are trees (folders or directories and files)
• Note the line at the bottom - this shows the path to the current directory. • There is a unique path from the root to the leaf.• This tree is not a binary tree (many files and directories can be
descendants of one directory)
7
Example: Sistem File
• Karena semua node di dalam pohon (kecuali node root) adalahketurunan dari tepat satu node lain maka kita dapat secararekursif menganggap setiap node sebagai noe root dari pohonyang lebih kecil.
• Pohon-pohon yang lebih kecil ini dinamakan sub-pohon(subtrees).
• Contoh: Node Users adalah root dari subtree direktoripengguna dalam diagram berikut:
8
Sub-Pohon
XML dan HTML
9
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>simple</title>
</head>
<body>
<h1>A simple web page</h1>
<ul>
<li>List item one</li>
<li>List item two</li>
</ul>
<h2><a href="xyz">XYZ</a><h2>
</body>
</html>
• Parent - a node is the parent of all nodes it connects to with outgoing edges.
• Children - all nodes with incoming edges from the same parent node are children of that node.
• Siblings - all nodes with the same parent are siblings.
• Level - the number of edges from the root node to this node. The root node is therefore level 0.
• Height - the height of a tree is the maximum level of all the nodes in the tree.
10
Istilah Penting
• A tree
• has a root node
• every node (except the root node) is connected by one edge from its unique parent node
• a unique path goes from the root to each node
• (and remember that a binary tree is one where the maximum number of children from a node is 2)
11
Tree definition 1
• A tree
• can be empty
• or consists of a root node and zero or more subtrees (subtrees are trees)
• the root of a subtree is connected to the root of the tree by an edge
• (a binary tree has no more than 2 subtrees from any root)
12
Tree definition 2
• Pohon yang umum digunakan dalam informatika adalah pohonbiner (kecuali disebutkan khusus)
• Mudah dimanfaatkan: setiap node induk mempunyai nilai kiridan/atau kanan.
• Dapat direpresentasikan seperti:
13
Binary Trees
class BinaryTree():
def __init__(self, root_data):self.data = root_dataself.left = Noneself.right = None
• Biasanya dibuatkan kelas BinaryTree dengan link ke sub-pohon kiri dan kanan.
• Bentuk sederhana adalah dengan List.
['a',
['b',
[],
['d',
[],
[]
]
],
['c',
['e',
[],
[]
],
['f',
[],
[]
]
]
]
14
Pohon dengan List
a
b c
d e f
List Sebenarnya:['a', ['b', [], ['d', [], []]], ['c', ['e', [], []], ['f', [], []]]]
Setiap node dalam pohon adalah list dengan 3 elemen:•Data atau nilai atau payload atau key (kunci)• Sub-pohon kiri (left subtree, berupa list)• Sub-pohon kanan (right subtree, juga suatu list)
15
[data, left, right]
• Beberapa operasi pohon yang disediakan kelas BinaryTree:
• BinaryTree() - create a new BinaryTree
• set_value(new_value) - sets the value of the node to new_value
• get_value() - gets the value of the node
• insert_left(value) - creates a new node with value to the left of the current node, the existing left node becomes the left node of the new one
• insert_right(value) - as above but to the right
• get_left_subtree() - gets the subtree to the left of this node
• get_right_subtree() - gets the subtree to the right of this node
• Catatan: Karena definisi rekursif, setiap node adalah root dari suatusubtree.
16
ADT BinaryTree
Kelas BinaryTreeSedikit berbeda dengan textbooks 6.4.1
class BinaryTree:
DATA = 0 # hanya agar mudah dibacaLEFT = 1 # dapat dirujuk dengan, misalnya:RIGHT = 2 # BinaryTree.DATA atau self.DATA
def __init__(self, root_value, left=None, right=None):self.node = [root_value, left, right]
Adanya nilai default untuk “left” dan “right” berarti bahwakonstruktor dapat dipanggil hanya dengan nilai unutk node root, sehingga subtree kiri dan kanan masih kosong (empty).
17
Penambahan/Penyisipan# Pendekatan di textbook untuk insert_leftdef insert_left(root, new_branch):
t = root.pop(1)if len(t) > 0:
root.insert(1, [new_branch, t, []])else:
root.insert(1, [new_branch, [], []])return root
# Pendekatan alternatifdef insert_left(self, value):
self.node[self.LEFT] = BinaryTree(value, self.node[self.LEFT], None)
def insert_right(self, value):self.node[self.RIGHT] = BinaryTree(value, None, self.node[self.RIGHT])
18
Fungsi-fungsi laindef set_value(self, new_value):
"""Sets the value of the node."""self.node[self.DATA] = new_value
def get_value(self):"""Gets the value of the node."""return self.node[self.DATA]
def get_left_subtree(self):"""Gets the left subtree of the node."""return self.node[self.LEFT]
def get_right_subtree(self):"""Gets the right subtree of the node."""return self.node[self.RIGHT]
19
Printing dengan str()• Printing pada versi textbook lebih mudah karena hanya mencetak
isi list.• Pendekatan alternative di sini adalah menggunakan rekursi dan
fungsi khusus __str__.• __str__(self) dipanggil ketika fungsi str() digunakan, misalnya oleh
fungsi print().
def __str__(self):return '['+str(self.node[self.DATA])+', '+\
str(self.node[self.LEFT])+', '+\str(self.node[self.RIGHT])+']'
20
Outputr = BinaryTree(1)r.insert_left(2)r.insert_right(3)r.insert_right(4)r.get_left_subtree().insert_left(5)r.get_left_subtree().insert_right(6)
print(r)print(r.get_left_subtree())print(r.get_right_subtree())print(r.get_left_subtree().get_left_subtree())
Menghasilkan:
[1, [2, [5, None, None], [6, None, None]], [4, None, [3, None, None]]][2, [5, None, None], [6, None, None]][4, None, [3, None, None]][5, None, None] 21
1
2 4
65 3
• Normally if you can use a built-in or standard Python data type to represent your data you should.
• Or as we just did create a new class with Python standard types as “instance variables” of the class.
• Sometimes you may subclass an existing class or data type to provide additional behaviour but this is beyond the scope of this course.
• Dengan kelas BinaryTree kita dapat menggunakan implementasiyang sangat berbeda yang tidak bersandar pada list dari Python.
22
K.I.S.S.
Node & Referensi# lihat kelas BinaryTree di Textbook sebagai bandingan
class MyBinaryTree:
def __init__(self, root_key, left=None, right=None):self.key = root_keyself.left = leftself.right = right
Sehingga kelas diatas dapat dipanggil dengan banyak cara:
MyBinaryTree(3)MyBinaryTree(3, existing_left, None)MyBinaryTree(3, MyBinaryTree(4), MyBinaryTree(5))MyBinaryTree(3, MyBinaryTree(4, MyBinaryTree(2), MyBinaryTree(7)),
MyBinaryTree(5, MyBinaryTree(6))
23
Implementasi Lanjutandef insert_left(self, value):
self.left = MyBinaryTree(value, left=self.left) # kanan?
def insert_right(self, value):self.right = MyBinaryTree(value, right=self.right) # kiri?
def get_left_subtree(self):return self.left
def get_right_subtree(self):return self.right
def set_value(self, new_value):self.data = new_value
def get_value(self):return self.data
24
Priority Queues & Binary Heaps
Chapter 6.5
• Suatu antrian (queue) adalah struktur data FIFO• the first element in is the first element out•which of course means the last one in is the last one
out
• But sometimes we want to sort of have a queue but we want to order items according to some characteristic the item has.
26
Some animals are more equal than others
• Prioritas: karakteristik penempatan atau pengurutan.
• Saat kita menarik sesuatu dari “queue” ini kita selalumendapatkan elemen dengan prioritas terbaik (kadang kala terbaik berarti paling rendah).
• Sangat umum di Sistem Operasi menggunakan prioritas untukmenjadwal saat sesuatu terjadi, misal:
• Proses yang sangat penting sebaiknya berjalan sebelumproses yang tidak begitu penting
• data dari disk sebaiknya diambilkan untuk proses-proses sangat penting lebih dahulu.
27
Priorities
• A priority queue always produces the element with the best priority when queried.
• You can do this in many ways
• keep the list sorted
• or search the list for the minimum value (if like the textbook -and Unix actually - you take the smallest value to be the best)
• You should be able to estimate the Big O values for implementations like this. e.g. O(n) for choosing the minimum value of an unsorted list.
• There is a clever data structure which allows all operations on a priority queue to be done in O(log n).
28
Priority Queue
• Properti bentuk: pohon biner lengkap, semua level kecualiterakhir harus penuh. Node level akhir diisi dari kiri.
• Properti heap: semua induk harus kurang atau sama (<) dengan anak-anaknya.
29
Binary HeapFokus pada min-heap biner
http://en.wikipedia.org/wiki/Binary_heap
• Pohon biner lengkap dapat direpresentasikan sangat bagus dalam array atau list.
• Karena tak ada gap kita dapat merepresentasikan baris dari tree sebagai rentetan list yang dapat kemudian digabungkan ke dalam satu list.
30
Cara Cerdas
1
2 3
17 19 36 7
25 100
1 2 3 17 19 36 7 25 100
• Jika kita menambahkan suatu elemen kosong (empty) pada awallist, maka kita kemudian dapat menjumpai anak kiri dari node tertentu pada posisi p pada 2p dan anak kanan pada posisi 2p + 1.
• Misal: anak dari elemen pada posisi 2 ada pada posisi 4 dan 5. Anak dari 2 adalah 17 dan 19.
31
Anak dua kali Induk
1 2 3 17 19 36 7 25 100
1 2 3 4 5 6 7 8 9 0
32
Pohon biner lengkap & Representasinya
• Create an empty binary heap
• Insert an item in the heap
• Retrieve the smallest item (removing it)
•Get the size of the heap
• Build a heap from a list
33
Operasi Binary Heap
Membuat Heap Biner Baru# dapat dimulai dengan sesuatu seperti:
class BinHeap:def __init__(self):self.heap_list = [0]
# akan dikembangkan lebih baik nantinya.# Catatan: tidak mencatat size seperti dalam Textbook# karena dapat digunakan len(self.heap_list) - 1.
def size(self):"""Mengembalikan ukuran dari heap."""return len(self.heap_list) - 1
34
• Kita perlu menjaga dua properti min-heap:
• Properti bentuk (shape): tree harus tetap lengkap (complete)
• Properti heap: nilai terkecil berada pada root
• Properti bentuk mudah dijaga. Kita cukup menambahkan nilai baruke dalam posisi daun berikutnya. Dalam list ini berartimenambahkan elemen ke list.
35
Penambahan ke dalam Heap
• To keep the heap property we may need to move the new value further up the tree.
•We repeatedly compare it to its parent exchanging them if it is smaller than its parent.
• This is sometimes called percolating because the smallest values bubble to the top.
36
Mempertahankan Heap
37
Men
apis
no
de
bar
u k
e p
osi
si t
epat
nya
• When we are swapping a value with its parent (say we are halfway up the tree) we know that the heap property will still be true for the subtree we are currently looking at because
• The new value is smaller than its parent and if the other child was greater than or equal to the parent value it must be greater than the new value.
• Any subtree below the current position of the new value must have values all greater than the parent so they are still in the correct positions.
38
Why is the exchange safe?
Kode Penyisipan (Penambahan)
def insert(self, k):self.heap_list.append(k)self.perc_up(self.size())
def perc_up(self, i):# we keep comparing with the parent until we reach the top# or the parent is smaller than the childwhile i // 2 > 0 and self.heap_list[i] < self.heap_list[i // 2]:
self.heap_list[i], self.heap_list[i // 2] = \self.heap_list[i // 2], self.heap_list[i]
i = i // 2
39
•Dengan suatu min heap ini cukup gampang.• Itu adalah elemen root atau dalam implementasi list
adalah elemen pada indeks 1.
• Jika kita menghapusnya maka harus memastikan propertybentuk dan heap.• Bentu mudah untuk ditetapkan lagi: kita memindahkan
daun terakhir di dalam heap ke posisi pertama (atauroot).
40
Mengambil Nilai Minimum
• Saat ini kita telah (hamper pasti) memindahkan suatu nilaiyang lebih besar ke dalam root.
• Kita perlu menapis nilai ini turun ke bawah tree.
41
Memelihara Heap (lagi)
42
Pen
apis
an N
od
e R
oo
t ke
Baw
ah T
ree
43
Pen
apis
an N
od
e R
oo
t ke
Baw
ah T
ree
• Percolating up was straight-forward because each child only has one parent.
• Percolating down we want to swap with the smallest child (to preserve the heap property).
44
Going down is a little trickier than going up
Kode: Penghapusandef del_min(self):
ret_val = self.heap_list[1]replacement = self.heap_list.pop()
if self.size() > 0:self.heap_list[1] = replacement
self.perc_down(1)return ret_val
45
Penalisan (Percolating) Turundef perc_down(self, i):
while (i * 2) <= self.size():child = self.min_child(i)if self.heap_list[i] > self.heap_list[child]:
self.heap_list[child], self.heap_list[i] = self.heap_list[i], self.heap_list[child]i = child
def min_child(self, i):”””Mengembalikan indeks dari anak minimum ber-indeks i.”””left = i * 2right = left + 1if right > self.size():
return leftif self.heap_list[left] < self.heap_list[right]:
return leftelse:
return right
46
•We can do it the boring way.• Start with an empty list and insert each element in
turn.• This will be O(n log n) as there are n elements to add
and each could percolate up the levels of the tree.
•Or we can do it the clever way.
47
Membangun Heap dari List
•We start half way through the list.• Any nodes in the last half of the list are leaves because
of the shape of our complete binary tree. Each level of the tree has one more node than the sum of the nodes in all previous levels.
•Moving backwards through the list percolate each element down to its correct position.
• This is O(n) - but I am not going to prove it :).
48
Cara Efisien
49
This is what Figure 6.12 should look like.
Membangun Heap dari List [9, 6, 5, 2, 3]
•Nomor di dalam lingkaran menunjukkan jumlah maksimum pertukaran yang diperlukan saat penambahan node ke heap
50
Pegeseran Naik & Turun
Kode: Membangun Heap
def __init__(self, a_list=[]):"""Constructs a BinHeap object.
Can either create an empty BinHeap or can constructit from a_list."""self.heap_list = [0] + a_list # add the dummy to listfor i in range(self.size() // 2, 0, -1):
self.perc_down(i)
51
Heap Beda Hasilnya sama
bh = BinHeap()bh.insert(9)bh.insert(6)bh.insert(5)bh.insert(2)bh.insert(3)print(bh)
bh = BinHeap([9,6,5,2,3])print(bh)
52
Output
[2, 3, 6, 9, 5]
[2, 3, 5, 6, 9]
• The BinHeap class has a special __str__ method to print out the heap values but leave out the dummy first element.
def __str__(self):
return str(self.heap_list[1:])
53
And by the way
Aplikasi Pohon BinerChapter 6.6
• What is parsing?• Originally from language study• The breaking up of sentences into component parts e.g. noun
phrase
• In computing compilers and interpreters parse programming languages.
• One aspect is parsing expressions.
55
Parse Trees
• The leaves are values and the other nodes are operators.
• We can use them to represent and evaluate the expression.
• We work up from the bottom evaluating subtrees.
• Compilers can use this to generate efficient code - e.g. how many registers are needed to calculate this expression.
56
Expression Trees
• Parsing starts with recognising tokens.
• A token is a symbol made up of one or more characters (commonly separated by white space).• e.g. a variable name or a number or an operator “+”.
• For an expression tree the tokens are numbers, operators and parentheses.
57
Tokens
• As we identify tokens we can apply rules to what we should do.• If the expression is fully parenthesised• a left parenthesis “(“ starts a subtree• a right parenthesis “)” finishes a subtree
58
Parsing Rules
1. If the current token is a ‘(’, add a new node as the left child of the current node, and descend to the left child.
2. If the current token is in the list [‘+’,’−’,’*’,‘/’], set the root value of the current node to the operator represented by the current token. Add a new node as the right child of the current node and descend to the right child.
3. If the current token is a number, set the root value of the current node to the number and return to the parent.
4. If the current token is a ‘)’, go to the parent of the current node.
59
4 Rules
(3 + (4 * 5))
60
Node Aktif
(3 + (4 * 5))
61
Node Aktif
(3 + (4 * 5))
62
3
Node Aktif
(3 + (4 * 5))
63
+
3 Node Aktif
(3 + (4 * 5))
64
+
3
Node Aktif
(3 + (4 * 5))
65
+
3
4
Node Aktif
(3 + (4 * 5))
66
+
3 *
4
(3 + (4 * 5))
67
+
3 *
4 5
Node Aktif
(3 + (4 * 5))
68
+
3 *
4 5
Node Aktif
(3 + (4 * 5))
69
+
3 *
4 5
• Bangkitkan expression tree untuk notasi matematikaberikut:
((2 * ((3 - 4) + 6)) + 2)
70
Giliran Anda!
• We need to be able to move back up the tree.
• So we need to keep track of the parent of the current working node.
• We could do this with links from each child node back to its parent.
• Or we could store the tree in a list and use the 2 x n trick (if the tree is not complete - most won’t be) then there will be lots of empty space in this list.
• Or we could push the parent node onto a stack as we move down the tree and pop parent nodes off the stack when we move back up.
71
Keeping Track of the Parent
Kode: Membangun Pohonset up
def build_expression_tree(parenthesized_expression):"""Builds an expression parse tree.
parenthesized_expression -- a fully parenthesized expressionwith spaces between tokens"""token_list = parenthesized_expression.split()parent_stack = Stack()expression_tree = BinaryTree('')parent_stack.push(expression_tree)current_tree = expression_tree
72
Menerapkan Aturan (Rule)
for token in token_list:if token == '(':
current_tree.insert_left('')parent_stack.push(current_tree)current_tree = current_tree.get_left_child()
73
1.If the current token is a ‘(’, add a new node as the left child of the current node, and descend to the left child.
Menerapkan Rule
elif token in ['+', '-', '*', '/']:current_tree.set_value(token)current_tree.insert_right('')parent_stack.push(current_tree)current_tree = current_tree.get_right_child()
74
2.If the current token is in the list [‘+’,‘−’,‘*’,‘/’], set the root value of the current node to the operator represented by the current token. Add a new node as the right child of the current node and descend to the right child.
Menerapkan Rule
elif is_number(token):current_tree.set_value(float(token))current_tree = parent_stack.pop()
75
3.If the current token is a number, set the root value of the current node to the number and return to the parent.
def is_number(token):"""Check if the token is a number."""try:
float(token)except:
return Falseelse:
return True
Menerapkan Rule
elif token == ')':current_tree = parent_stack.pop()
else:raise ValueError
76
4.If the current token is a ‘)’, go to the parent of the current node.
•Once we have generated the expression tree we can easily evaluate the expression.
• In a compiler the expression would contain variables which we wouldn’t know the value of until the program ran, so the evaluation would be done at run time.
77
Evaluasi Ekspresi
Bagaimana Evaluasi Dilaksanakan?
78
+
3 *
4 5
Evaluasi sub-pohon ini
• To evaluate the subtree under a node
• if the node has children
• the node holds an operator
• return the result of applying the operator on the left and right subtrees
• else the node held a number
• return the number
79
Algoritma
Kode: Evaluasiimport operator
def evaluate(expression_tree):"""Return the result of evaluating the expression."""token = expression_tree.get_value()
operations = {'+':operator.add, '-':operator.sub,'*':operator.mul, ‘/':operator.truediv}
left = expression_tree.get_left_child()right = expression_tree.get_right_child()if left and right:
return operations[token](evaluate(left), evaluate(right))else:
return token
80
• The operator module provides functions to add, subtract etc.
• We use a dictionary “operations” to connect the tokens “+”, “-”, “*” and “/” with the corresponding function.
• The line
operations[token](evaluate(left), evaluate(right))
evokes the function on its parameters.
81
What is that operator stuff?
• With a binary tree we can recursively travel through all of the nodes (or traverse) in three standard ways.
• We can deal with the node first then deal with the left subtree, then the right subtree.
• This is a preorder traversal.
• We can deal with the left subtree, then with the node, then with the right subtree.
• This is an inorder traversal (and as we will see this keeps things in order).
• We can deal with the left subtree, then the right subtree and lastly the node itself.
• This is a postorder traversal (we used this to evaluate expression trees).
82
Penjelajahan PohonText book sub-bab 6.7
Kode: Cetak Penjelajahan Pohondef print_preorder(tree):
"""Print the preorder traversal of the tree."""if tree:
print(tree.get_value(), end=' ')print_preorder(tree.get_left_child())print_preorder(tree.get_right_child())
def print_postorder(tree):"""Print the postorder traversal of the tree."""if tree:
print_postorder(tree.get_left_child())print_postorder(tree.get_right_child())print(tree.get_value(), end=' ')
def print_inorder(tree):"""Print the inorder traversal of the tree."""if tree:
print_inorder(tree.get_left_child())print(tree.get_value(), end=' ')print_inorder(tree.get_right_child())
83
Pohon Pencarian BinerSub-bab 6.8
•Many algorithms can be performed on trees in O(log n) time.
• Searching for elements using a binary search can work on a tree if the elements are ordered in the obvious way.
• Adding and removing elements is a little trickier.
85
Trees are efficient
• All values in the nodes in the left subtree of a node are less than the value in the node.
• All values in the nodes in the right subtree of a node are greater than the value in the node.
86
The Binary Search Tree property
http://en.wikipedia.org/wiki/Binary_search_tree
•We can go through a list of elements adding them in the order they occur.•Misal: 70, 31, 93, 94, 14, 23, 73
87
Membangun BST
70, 31, 93, 94, 14, 23, 73
88
70
70, 31, 93, 94, 14, 23, 73
89
70
31
70, 31, 93, 94, 14, 23, 73
90
70
31 93
70, 31, 93, 94, 14, 23, 73
91
70
31 93
94
70, 31, 93, 94, 14, 23, 73
92
70
31 93
9414
70, 31, 93, 94, 14, 23, 73
93
70
31 93
9414
23
70, 31, 93, 94, 14, 23, 73
94
70
31 93
9414
23
73
• Tambahkan elemen 17, 5, 25, 2, 11, 35, 9, 16, 29, 38, 7 kesuatu pohon pencarian biner!
95
Giliran Anda!
• If we use a key as the ordering component in our BSTs we can also store a separate value.
• We can then use a BST as a Map with functions such as:
• put(key, value) - stores value using key
• get(key) - returns the value found from key
• The text book does this.
• Most introductions just use a value - this is what I will use.
96
ADT Map dan BST
Kode: Binary Search Treeclass BST:
"""A Binary Search Tree (BST) class."""
def __init__(self, value, parent=None):"""Construct a BST.
value -- the value of the root nodeparent -- the parent node (of this BST subtree)"""self.value = valueself.left = Noneself.right = Noneself.parent = parent # useful for some operations
97
Menyisipkan Suatu Nilai
def insert(self, value):"""Insert value into the BST."""if value == self.value: # already in the tree
returnelif value < self.value:
if self.left:self.left.insert(value)
else:self.left = BST(value, parent=self)
else:if self.right:
self.right.insert(value)else:
self.right = BST(value, parent=self)
98
A Factory Method
def create(a_list):"""Create a BST from the elements in a_list."""bst = BST(a_list[0])for i in range(1, len(a_list)):
bst.insert(a_list[i])return bst
# A factory method is one which creates and returns# a new object.
# e.g. this would be called like thisbst = BST.create([70, 31, 93, 94, 14, 23, 73])
99
Doing something in order
def inorder(self, function):"""Traverse the BST in order performing function."""if self.left: self.left.inorder(function)function(self.value)if self.right: self.right.inorder(function)
# for example:bst = BST.create([70, 31, 93, 94, 14, 23, 73])bst.inorder(print)
# The output is 14 23 31 70 73 93 94
100
• Tuliskan metode __contains__ yang akan mengembalikanTrue jika BST mengandung nilai, jika tidak False.
def __contains__(self, value):
101
Giliran Anda
•We need to find the node the value is stored in.
• There are three cases• the node has no children• the node has one child• the node has two children
102
Menghapus Nilai
Menemukan Nodedef locate(self, value):
"""Return the node holding value."""if value == self.value:
return selfelif value < self.value and self.left:
return self.left.locate(value)elif value > self.value and self.right:
return self.right.locate(value)else:
return None
103
104
Tidak Punya AnakMenghapus No 16 (tanpa anak)
• Cukup hapus node tersebut dan betulkan induknya.
105
Node Tanpa Anak
Satu anakMenghapus node 25 (memiliki satu anak)
106
•Hapus node dan geser anaknya (menempati tempatnya) dengan mengubah induknya.
107
Satu Anak
Dua AnakMenghapus Node 5 (dua anak)
108
•Ganti nilai dalam node dengan suksesor inorder-nya.
• Juga hapus node suksesor inorder-nya.• Tetapi ini tidak dapat mempunyai lebih dari satu anak.•Mengapa tidak?
109
Dua Anak
•Masukkan elemen dengan urutan berikut:
50, 70, 30, 37, 43, 81, 12, 72, 99
110
Gambarkan BST
111
Hapus Elemen Merah
23
51
76
3217
45
80
9 28
26
40
33
112
Hapus Elemen Merah
23
51
76
3217
45
80
9 28
26
40
33
113
Hapus Elemen Merah
23
51
76
3217
45
80
9 28
26
40
33
114
Hapus Elemen Merah
23
51
76
3217
45
80
9 28
26
40
33
Kode: Penghapusan
def delete(self, value):"""Delete value from the BST."""node = self.locate(value) # saw this last lectureif node:
node.delete_this_node()
def delete_this_node(self):left = self.leftright = self.rightif left and right: # two children
self.delete_with_children()elif left or right: # one child
self.delete_with_child()else: # no children
self.delete_no_children() 115
• Harus menemukan node yang menyimpan nilai yang akan dihapus.• Ada 3 kasus:
• Node mempunyai dua anak• Node mempunyai satu anak • Node tidak mempunyai anak
Penghapusan Tanpa Anak
def delete_no_children(self):if self.parent:
if self.parent.left == self:self.parent.left = None
else:self.parent.right = None
else: # special case the root nodeself.value = None
116
• Hanya hapus node tersebut dan betulkan induknya
Penghapusan Dengan Satu Anak
def delete_with_child(self):child = self.left if self.left else self.rightif self.parent:
if self.parent.left == self:self.parent.left = child
else:self.parent.right = child
child.parent = self.parentelse: # special case the root node
self.replace(child)
117
• Hapus node tersebut dan geser naik untuk mendapatkantempat baru dengan mengubah induknya.
Mengganti Isi Node# Kita telah menghapus nilai root namun kita tidak ingin# menghapus node root tersebut (karena ini mendefinisikan BST).# Jadi letakkan info baru ke dalam node root tersebut.
def replace(self, other):"""Ganti node ini dengan nilai dari yang lain.
Juga perlu melekatkan-ulang anak-anak lain."""self.value = other.valueself.left = other.leftif self.left: self.left.parent = selfself.right = other.rightif self.right: self.right.parent = self
118
Penghapusan Dengan Anak
def delete_with_children(self):replacement = self.right.min() # the successorsuccessor_value = replacement.valuereplacement.delete_this_node() # max of one child of thisself.value = successor_value
119
• Ganti nilai dalam node tersebut dengan suksesorinordernya
• Juga hapus node suksesor inorder-nya.
Kode: Inorder successor
def min(self):"""Mengembalikan node paling kiri dari BST."""min_node = selfwhile min_node.left:
min_node = min_node.leftreturn min_node
120
• It depends on how the tree has been constructed.
•A full binary tree or one close to it (every node not a leaf node has two children) is ideal.
•The algorithms depend on how far down the tree you have to go in order to insert or delete nodes.
•With a full binary tree the number of nodes in level d is 2d. And the number of nodes in a tree of height h is 2h+1 - 1.
121
Big O Dari Operasi
• A balanced tree has approximately the same number of nodes in the left subtree as in the right subtree. This will give O(log n) operations for retrieval, insertion and deletion.
• Unbalanced trees have runs of single children. This can be as bad as a simple list and so has O(n) operations.
122
Balanced dan Unbalanced
Pohon Pencarian Biner Miring akan memberikan kinerja buruk