数据结构与算法笔记(十六)—— 二叉搜索树
生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法笔记(十六)—— 二叉搜索树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、二叉搜索樹定義
二叉搜索樹(Binary Search Tree),又名二叉排序樹(Binary Sort Tree)。
二叉搜索樹是具有有以下性質的二叉樹:
- 若左子樹不為空,則左子樹上所有節點的值均小于或等于它的根節點的值。
- 若右子樹不為空,則右子樹上所有節點的值均大于或等于它的根節點的值。
- 左、右子樹也分別為二叉搜索樹。
二、二叉搜索樹的操作
2.1、結點創建
class Node(object):"""節點類"""def __init__(self, elem=-1, lchild=None, rchild=None,parent=None):self.elem = elemself.lchild = lchildself.rchild = rchildself.parent = parent2.2、樹的創建
class BTree(object):def __init__(self):self.root = Nonedef insert(self,node,val):'''為樹添加結點: 遞歸'''if self.root is None:self.root = Node(val)returnif node is None:node = Node(val)return nodeif val < node.elem:node.lchild = self.insert(node.lchild,val)node.lchild.parent = nodeelif val > node.elem:node.rchild = self.insert(node.rchild,val)node.rchild.parent = nodereturn nodedef insert_no_rec(self,val):'''為樹添加結點: 非遞歸'''p = self.rootif not p: #空樹self.root = Node(val)returnwhile True:if val < p.elem:if p.lchild:p = p.lchildelse: #左孩子不存在p.lchild = Node(val)p.lchild.parent = preturnelif val > p.elem:if p.rchild:p = p.rchildelse: #右孩子不存在p.rchild = Node(val)p.rchild.parent = preturnelse:return2.3、遍歷
(即二叉樹遍歷,代碼參考我博客:數據結構與算法筆記(十四)—— 二叉樹)
2.4、查找
def search(self,val):p = self.rootwhile p:if p.elem <val:p = p.rchildelif p.elem > val:p = p.rchildelse:return Truereturn False測試:
print(tree.search(20)) #結果:False print(tree.search(13)) #結果:True2.5、刪除
二叉查找樹的刪除操作分為三種情況:
① 要刪除的節點是葉子節點:直接刪除
代碼:
def delNode_1(self,node):'''情況1:node是葉子結點(即無左子樹又無右子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = Noneelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = Noneelse: #node是它父親的右孩子node.parent.rchild = None② 要刪除的節點只有一個孩子:將此節點的父親與孩子連接,然后刪除該節點
代碼:
def delNode_21(self,node):'''情況2:node只有一個左孩子(只有左子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = node.lchildelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = node.lchildnode.lchild.parent = node.parentelse: #node是它父親的右孩子node.parent.rchild = node.lchildnode.lchild.parent = node.parentdef delNode_22(self,node):'''情況2:node只有一個右孩子(只有右子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = node.rchildelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = node.rchildnode.rchild.parent = node.parentelse: #node是它父親的右孩子node.parent.rchild = node.rchildnode.rchild.parent = node.parent③ 要刪節點既有左子樹也有右子樹:找到該節點右子樹中最小值節點,使用該節點代替待刪除節點,然后在右子樹中刪除最小值節點。
代碼:
def defNode_3(self,node):'''情況3:既有左孩子又有右孩子'''min_node = node.rchildwhile min_node.lchild:min_node = min_node.lchildnode.data = min_node.elem# 刪除min_nodeif min_node.rchild:self.delNode_22(min_node)else:self.delNode_1(min_node)刪除結點完整代碼:
def delNode(self,val):'''刪除二叉搜索樹中值為val的點'''if not self.root:return False_,node = self.search(val)if not node:return Falseif not node.lchild and not node.rchild: #1.葉子結點self.delNode_1(node)elif not node.rchild: #2.1 只有一個左孩子self.delNode_21(node)elif not node.lchild: #2.3 只有一個右孩子self.delNode_22(node)else: #3.兩個孩子都有self.defNode_3(node)測試:
tree.preorder(tree.root) #結果:13 14 94 33 25 82 59 65 tree.delNode(13) tree.preorder(tree.root) #結果:14 94 33 25 82 59 65完整代碼
class Node(object):"""節點類"""def __init__(self, elem=-1, lchild=None, rchild=None,parent=None):self.elem = elemself.lchild = lchildself.rchild = rchildself.parent = parentclass BTree(object):def __init__(self):self.root = Nonedef insert(self,node,val):'''為樹添加結點: 遞歸'''if self.root is None:self.root = Node(val)returnif node is None:node = Node(val)return nodeif val < node.elem:node.lchild = self.insert(node.lchild,val)node.lchild.parent = nodeelif val > node.elem:node.rchild = self.insert(node.rchild,val)node.rchild.parent = nodereturn nodedef insert_no_rec(self,val):'''為樹添加結點: 非遞歸'''p = self.rootif not p: #空樹self.root = Node(val)returnwhile True:if val < p.elem:if p.lchild:p = p.lchildelse: #左孩子不存在p.lchild = Node(val)p.lchild.parent = preturnelif val > p.elem:if p.rchild:p = p.rchildelse: #右孩子不存在p.rchild = Node(val)p.rchild.parent = preturnelse:returndef search(self,val):p = self.rootwhile p:if p.elem <val:p = p.rchildelif p.elem > val:p = p.rchildelse:return True,preturn Falsedef preorder(self,node):'''先序遍歷'''if node is None:returnprint(node.elem, end=' ')self.preorder(node.lchild)self.preorder(node.rchild)def delNode_1(self,node):'''情況1:node是葉子結點(即無左子樹又無右子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = Noneelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = Noneelse: #node是它父親的右孩子node.parent.rchild = Nonedef delNode_21(self,node):'''情況2:node只有一個左孩子(只有左子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = node.lchildelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = node.lchildnode.lchild.parent = node.parentelse: #node是它父親的右孩子node.parent.rchild = node.lchildnode.lchild.parent = node.parentdef delNode_22(self,node):'''情況2:node只有一個右孩子(只有右子樹)'''if not node.parent: #沒有父節點說明是根節點self.root = node.rchildelif node == node.parent.lchild: #node是它父親的左孩子node.parent.lchild = node.rchildnode.rchild.parent = node.parentelse: #node是它父親的右孩子node.parent.rchild = node.rchildnode.rchild.parent = node.parentdef defNode_3(self,node):'''情況3:既有左孩子又有右孩子'''min_node = node.rchildwhile min_node.lchild:min_node = min_node.elemnode.data = min_node.elem# 刪除min_nodeif min_node.rchild:self.delNode_22(min_node)else:self.delNode_1(min_node)def delNode(self,val):'''刪除二叉搜索樹中值為val的點'''if not self.root:return False_,node = self.search(val)if not node:return Falseif not node.lchild and not node.rchild: #1.葉子結點self.delNode_1(node)elif not node.rchild: #2.1 只有一個左孩子self.delNode_21(node)elif not node.lchild: #2.3 只有一個右孩子self.delNode_22(node)else: #3.兩個孩子都有self.defNode_3(node)if __name__ == '__main__':li = [13,14,94,33,82,25,59,94,65]tree = BTree() #=========添加結點============= for i in li:tree.insert(tree.root,i)tree.preorder(tree.root)print('') #=========查找元素============= # print(tree.search(14)) #=========刪除結點============= tree.delNode(13)print('')tree.preorder(tree.root)總結
以上是生活随笔為你收集整理的数据结构与算法笔记(十六)—— 二叉搜索树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构与算法笔记(十五)—— 散列(哈
- 下一篇: 学习笔记Hadoop(一)—— Hado