Teori Singkat
Untuk menghapus node, langkah pertama adalah mencari node tersebut. Kemudian melakukan delete node.
Ada tiga kondis penghapusan, yaitu zero, one dan two child.
Zero Child, jika node yang dihapus tidak memiliki children. Kita bisa langsung delete node tersebut. Lihat gambar-1, contoh yang akan dihapus adalah node 25.
One Child, jika node yang dihapus memiliki 1 children. Maka node children tersebut akan menjadi posisi parent (node yang dihapus). Lihat gambar-2, node yang akan dihapus adalah 70.
Two Child, jika node yang dihapus memiliki 2 children. Gunakan metoda RTFM, Right Tree Find Minimum. Jadi telusuri node di kaki kanan, cari nilai minimum. Gunakan node minimum tersebut untuk menggantikan node yang dihapus.
Lihat gambar-3, node yang akan dihapus adalah node 70. Langkah pertama telesuri kaki kanan untuk mencari node minimum, yaitu node 80. Karena node minimum, sudah dipastikan hanya memiliki kaki kanan (jika memiliki kaki kiri, node tersebut bukan node minimum).
Pindahkan node 80 untuk menggantikan node 70. Jika memiliki child, maka pindahkan child ke posisi node 80 sebelumnya.
Implementasi Pada Python
Pertama kita buat helper function untuk mencari minimum node.
def findMinNode(self):
if self.left:
return self.left.findMinNode()
return self.data
Lalu kita buat fungsi untuk delete Node
def delNode(self, target):
if self.data == target:
if self.left and self.right:
#do RTFM
minNode = self.right.findMinNode()
self.data = minNode
self.right = self.right.delNode(minNode)
return self
else:
#one child or two child
return self.left or self.right
Jangan lupa untuk menambahkan fungsi delNode pada class wrapper Tree.
def delNode(self, target):
self.root = self.root.delNode(target)
Berikut isi lengkap program tree.
class Node: def __init__(self, data): self.data = data self.left = None self.right = None def search(self, target): if self.data == target: print("Node found") return self if self.left and self.data > target: return self.left.search(target) if self.right and self.data < target: return self.right.search(target) print("No Node Found") def traversePreorder(self): print(self.data) if self.left: self.left.traversePreorder() if self.right: self.right.traversePreorder() def traverseInorder(self): if self.left: self.left.traverseInorder() print(self.data) if self.right: self.right.traverseInorder() def traversePostorder(self): if self.left: self.left.traversePostorder() if self.right: self.right.traversePostorder() print(self.data) def height(self, h=0): leftHeight = self.left.height(h+1) if self.left else h rightHeight = self.right.height(h+1) if self.right else h return max(leftHeight, rightHeight) def getNodeAtDepth(self, depth, nodes=[]): if depth==0: nodes.append(self.data) return nodes if self.left: self.left.getNodeAtDepth(depth-1, nodes) else: nodes.extend([None]*2**(depth-1)) if self.right: self.right.getNodeAtDepth(depth-1, nodes) else: nodes.extend([None]*2**(depth-1)) return nodes def addNode(self, val): if self.data == val: return if val < self.data: if self.left is None: self.left = Node(val) else: self.left.addNode(val) if val > self.data: if self.right is None: self.right = Node(val) else: self.right.addNode(val) def findMinNode(self): if self.left: return self.left.findMinNode() return self.data def delNode(self, target): if self.data == target: if self.left and self.right: #do RTFM minNode = self.right.findMinNode() self.data = minNode self.right = self.right.delNode(minNode) return self else: return self.left or self.right if self.right and target > self.data: self.right = self.right.delNode(target) if self.left and target < self.data: self.left = self.left.delNode(target) return self class Tree: def __init__(self, root, name=''): self.root = root self.name = name def search(self, target): return self.root.search(target) def traversePreorder(self): self.root.traversePreorder() def traverseInorder(self): self.root.traverseInorder() def traversePostorder(self): self.root.traversePostorder() def height(self): return self.root.height() def getNodeAtDepth(self, depth): return self.root.getNodeAtDepth(depth) def _nodeToChar(self, n, space): if n is None: return '_' + (' '*space) space = space - len(str(n))+1 return str(n)+(' '*space) def printTree(self, label=''): print(self.name + ' ' + label) height = self.root.height() space = 3 width = int((2**height-1) * (space+1) +1) offset = int((width-1)/2) for depth in range(0, height+1): if depth>0: print(' '*(offset+1) + (' '*(space+2)).join(['/' + (' '*(space-2)) + '\\']*(2**(depth-1)))) row = self.root.getNodeAtDepth(depth, []) print ((' '*offset)+ ''.join([self._nodeToChar(n,space) for n in row])) space = offset + 1 offset = int(offset/2)-1 print ('') def addNode(self, val): self.root.addNode(val) def delNode(self, target): self.root = self.root.delNode(target) node = Node(55) node.left = Node(25) node.right = Node(70) node.right.left = Node(60) node.right.right = Node(90) node.right.right.left = Node(80) node.right.right.right = Node(120) node.right.right.left.right = Node(85) myTree = Tree(node, 'Basic BST') myTree.printTree() myTree.delNode(70) myTree.printTree()
$ python tree.py
Basic BST
55
/ \
25 70
/ \ / \
_ _ 60 90
/ \ / \ / \ / \
_ _ _ _ _ _ 80 120
/ \ / \ / \ / \ / \ / \ / \ / \
_ _ _ _ _ _ _ _ _ _ _ _ _ 85 _ _
Basic BST
55
/ \
25 80
/ \ / \
_ _ 60 90
/ \ / \ / \ / \
_ _ _ _ _ _ 85 120
Pada program dilakukan penghapusan node 70, sesuai ekspektasi, node 80 akan menggantikan node 70, dan node 85 akan menggantikan posisi node 80.