# BTS CRUD 完整版 # BTS_CRUD完整程式碼 [toc] ## 和二元樹的比較 1. preorder 相同 2. BST search 部分 需要多一個和父節點比大小去判斷是不是要繼續recursive(同時也要保有原本的是否存在左右子樹),也因此造就筆BT 更快速的search 3. ```python! class Node: def __init__(self, value=None): self.value = value self.left_child = None #smaller self.right_child = None #greater self.parent = None # pointer to parent node in tree class Binary_search_tree: def __init__(self): self.root = None def insert(self, value): #判斷tree是否為空 if self.root == None: self.root = Node(value) else: self._insert(value, self.root) def _insert(self, value, cur_node): if value < cur_node.value: if cur_node.left_child == None: cur_node.left_child = Node(value) cur_node.left_child.parent = cur_node #set parent else: self._insert(value, cur_node.left_child) elif value > cur_node.value: if cur_node.right_child == None: cur_node.right_child = Node(value) # 為什麼要回頭設parent 是因為這個example 是雙向鏈結嗎? cur_node.right_child.parent = cur_node #set parent else: self._insert(value, cur_node.right_child) # value == cur_node.value else: print("This value has existed") def print_tree(self): if self.root!=None: self._print_tree(self.root) def _print_tree(self,cur_node): if cur_node!=None: self._print_tree(cur_node.left_child) print(str(cur_node.value)) self._print_tree(cur_node.right_child) def height(self): if self.root != None: return self._height(self.root,0) else: return # 我們要在每一次遞迴呼叫時傳入cur_height,如果沒有像parameter # 樣傳入或儲存成global variable會造成 無法儲存cur_height def _height(self, cur_node, cur_height): if cur_node == None: return cur_height #0 # 找一個最高的子樹 left_height = self._height(cur_node.left_child,cur_height+1) right_height = self._height(cur_node.right_child,cur_height+1) return max(left_height, right_height) # returns the node with specified input value def find(self, value): if self.root != None: return self._find(value, self.root) else: return None def _find(self, value, cur_node): if value == cur_node.value: return cur_node elif value < cur_node.value and cur_node.left_child != None: return self._find(value, cur_node.left_child) elif value > cur_node.value and cur_node.right_child != None: return self._find(value, cur_node.right_child) def delete_value(self, value): return self.delete_node(self.find(value)) def delete_node(self, node): #returns the node with min value in tree rooted at input Node #we will pass the single node to treat as the root of a binary search fill_tree def min_value_node(n): current = n # traverse down to the left of the tree until it finds the smallest element returning this value while current.left_child != None: current = current.left_child return current #returns the number of children for the specified node # return the number of the children and attach the input node either 0,1 or two def num_children(n): num_children = 0 if n.left_child != None: num_children +=1 if n.right_child != None: num_children += 1 return num_children #create variable to hold both the parent of the node to delete as well as #the number of children get the parent of the node to be deleted node_parent = node.parent #get the number of children of the node to be deleted node_children = num_children(node) #break operation into different cases based on the #structure of the tree & node to be delete #CASE 1 (node has no children) if node_children == 0: #remove reference to the node from the node_parent if node_parent.left_child == node: node_parent.left_child = None else: node_parent.right_child = None #CASE 2 (node has a single child) if node_children == 1: # get the single child node if node.left_child != None: child = node.left_child else: child = node.right_child # 把目前節點的父節點連到子節點 越過它,所已前面才需要有parent linked #replace the node to be deleted with its child if node_parent.left_child == node: node_parent.left_child = child else: node_parent.right_child = child #correct the parent pointer in node child.parent = node_parent #CASE 3 (node has two children) if node_children == 2: # get the inorder successor of the deleted # 找右邊子樹的左子樹最底層leaf(整個右邊子樹中最小的), #所以我們才要放入right_child 然後在min_value_node中卻是travel left_child successor = min_value_node(node.right_child) #copy the inorder successor's value to the node formerly #holding the value we wished th delete node.value = successor.min_value_node #delete the inorder successor now that it's value was #copied into the other node self.delete_node(successor) def search(self, value): if self.root != None: return self._search(value, self.root) else: return False def _search(self, value, cur_node): if value == cur_node.value: return True elif value < cur_node.value and cur_node.left_child != None: return self._search(value, cur_node.left_child) elif value > cur_node.value and cur_node.right_child != None: return self._search(value, cur_node.right_child) else: return False def fill_tree(tree, num_elems=10, max_int=50): from random import randint for _ in range(num_elems): #10個 value cur_elem = randint(0, max_int) #隨機0~50(不含50)的值 tree.insert(cur_elem) return tree #============================================================ #建立1~9的樹 tree = Binary_search_tree() for num in range(10): tree.insert(num) #delete node 5 tree.delete_value(5) #印出樹 tree.print_tree() ```