二叉查找樹或者是一棵空樹,或者是具備下列性質的二叉樹: 若它的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹。
二叉搜索樹不必定是徹底二叉樹,所以不能像堆同樣能夠數組表示。
定義一個TNode類來實例化節點,有key,value,l_child,r_child屬性。其中key,value經過構造函數傳入,l_child,r_child初始化爲None。node
再定義一個BSTree類,根節點初始化爲None。數組
而後給BSTree添加如下方法:
insert(key,value) 插入一個節點
update(key,value) 更新節點的值
search(key) 經過key來找相應節點的value
remove(key) 經過key來刪除樹中相應節點
以及深度優先和廣度優先的遍歷方法。app
insert:
傳入參數key,value,插入一個新的節點。可是若是樹中已經存在key爲key的節點,就將插入操做轉變爲更新操做。函數
def __insert(self, key, value, curr_node): if curr_node is None: return TNode(key, value) if key < curr_node.key: curr_node.l_child = self.__insert(key, value, curr_node.l_child) elif key > curr_node.key: curr_node.r_child = self.__insert(key, value, curr_node.r_child) else: curr_node.value = value return curr_node
噹噹前的節點爲None時,根據參數中的key和value創建新的節點,並返回這個節點。當key值小於當前節點的key時,將新節點插入到當前節點的左子樹的相應位置,而後返回當前節點。同理key值大於當前節點的key時,將新節點插入到當前節點的右子樹的相應位置,返回當前節點。若是key等於當前節點key,將插入操做改變爲更新操做。code
search:排序
def __search(self, node, key): if node: if node.key == key: return node elif node.key > key: return self.__search(node.l_child, key) else: return self.__search(node.r_child, key) return False
在當前node爲根節點的子樹中,查找key爲key的子節點,若是當前node的key值與參數相同,返回當前節點。不然遞歸地到左右子樹中找key爲key的節點,若是沒有找到,最終返回False。遞歸
update:隊列
def __update(self, key, value, node): if node: if node.key == key: node.value = value elif node.key > key: self.__update(key, value, node.l_child) else: self.__update(key, value, node.r_child)
在當前node爲根節點的子樹中,查找key爲key的節點。若是當前node的key值與參數相同,更新當前節點的value。不然遞歸地到左右子樹中找到key爲key的節點,並更新value。rem
remove:get
執行remove操做時,分爲兩種狀況。
1.當前要刪除的節點沒有右子節點,此時將左子節點做爲當前節點,返回。
2.當前要刪除的節點(node_to_delete)有右子節點(r_child),找到右子節點下,最小的節點(r_child_smallest_child),將該節點與要刪除的節點換位置。具體操做爲:先拿到r_child_smallest_child,再將該節點從以r_child爲根的子樹中刪除。再將node_to_delete的左孩子做爲r_child_smallest_child的左孩子,node_to_delete的右孩子做爲r_child_smallest_child的右孩子。最終將r_child_smallest_child賦給node_to_delete,並返回。
代碼以下:
def __remove(self, node, key): if node: if node.key < key: node.r_child = self.__remove(node.r_child, key) elif node.key > key: node.l_child = self.__remove(node.l_child, key) else: if node.r_child is None: node = node.l_child else: node_r_child_smallest_child = self.__get_smallest_child(node.r_child) self.__remove_smallest(node.r_child) node_r_child_smallest_child.r_child = node.r_child node_r_child_smallest_child.l_child = node.l_child node = node_r_child_smallest_child return node return False
其中__remove_smallest和__get_smallest_child含義分別是:刪除當前節點下,最小的節點,以及得到當前節點下最小的節點。
代碼以下:
def __remove_smallest(self, node): if node.l_child: node.l_child = self.__remove_smallest(node.l_child) return node return node.r_child
噹噹前節點有左孩子時,刪除左子樹中最小的節點,而且返回當前節點。沒有左孩子時,返回右孩子。
def __get_smallest_child(self, node): if node.l_child: return self.__get_smallest_child(node.l_child) return node
噹噹前節點有左孩子時,得到左子樹中最小的節點。沒有左孩子時,返回當前節點。
深度優先遍歷,能夠選擇先序遍歷,中序遍歷,後續遍歷,以其中之一爲例:
def __l_m_r(self, node): if node: self.__l_m_r(node.l_child) print(node) self.__l_m_r(node.r_child)
當進行廣度優先遍歷時,須要用到隊列。
def bfs(self): queue = deque() queue.append(self.root) while queue: node = queue.popleft() if node: l_child = node.l_child r_child = node.r_child print(node.value) queue.append(l_child) queue.append(r_child)
以上是我所瞭解的二叉搜索樹的基本功能