每次插入新节点,先按普通二叉树的 insertion 方式插入,若树中所有节点都满足 AVL Tree 的规定,则插入完毕;若树中有节点不满足 AVL Tree 的规定,则根据情况作出相应的调整。可能出现的情况有 4 种:
i) left - left:
ii) left - right:
iii) right - right:
iv) right - left:
代码实现如下:
AVL.py
classTreeNode(object):def__init__(self,val): self.val = val self.left =None self.right =None self.height =1classAVLTree(object):definsert(self,root,key):# Step 1 - Perform normal BSTifnot root:returnTreeNode(key)elif key < root.val: root.left = self.insert(root.left, key)else: root.right = self.insert(root.right, key)# Step 2 - Update the height of the ancestor node root.height =1+max(self.getHeight(root.left), self.getHeight(root.right))# Step 3 - Get the balance factor balance = self.getBalance(root)# Step 4 - If the node is unbalanced,# then try out the 4 cases# Case 1 - Left Leftif balance >1and key < root.left.val:return self.rightRotate(root)# Case 2 - Right Rightif balance <-1and key > root.right.val:return self.leftRotate(root)# Case 3 - Left Rightif balance >1and key > root.right.val: root.left = self.leftRotate(root.left)return self.rightRotate(root)# Case 4 - Right Leftif balance <-1and key < root.right.val: self.right = self.rightRotate(root.right)return self.leftRotate(root)return rootdefleftRotate(self,z): y = z.right T = y.left y.left = z z.right = T# Update heights z.height =1+max(self.getHeight(z.left), self.getHeight(z.right)) y.height =1+max(self.getHeight(y.left), self.getHeight(y.right))return ydefrightRotate(self,z): y = z.left T = y.right y.right = z z.left = T# Update heights z.height =1+max(self.getHeight(z.left), self.getHeight(z.right)) y.height =1+max(self.getHeight(y.left), self.getHeight(y.right))return ydefgetHeight(self,root):ifnot root:return0return root.heightdefgetBalance(self,root):ifnot root:return0return self.getHeight(root.left)- self.getHeight(root.right)
Deletion
每次删除节点,先按普通二叉树的 deletion 方式删除,若树中所有节点都满足 AVL Tree 的规定,则删除完毕;若树中有节点不满足 AVL Tree 的规定,则根据情况作出相应的调整。可能出现的情况有 4 种,与 insertion 中的 4 种情况相同,代码实现如下:
classAVLTree(object):defdelete(self,root,key):# Step 1 - Perform standard BST deleteifnot root:return rootelif key < root.val: root.left = self.delete(root.left, key)elif key > root.val: root.right = self.delete(root.right, key)else:if root.left isNone: tmp = root.right root =Nonereturn tmpelif root.right isNone: tmp = root.left root =Nonereturn tmp tmp = self.getMinValueNode(root.right) root.val = tmp.val root.right = self.delete(root.right, tmp.val)# If the tree has only one node, simply return itif root isNone:return root# Step 2 - Update the height of the ancestor node root.height =1+max(self.getHeight(root.left), self.getHeight(root.right))# Step 3 - Get the balance factor balance = self.getBalance(root)# Step 4 - If the node is unbalanced, # then try out the 4 cases # Case 1 - Left Left if balance >1and self.getBalance(root.left)>=0:return self.rightRotate(root)# Case 2 - Right Right if balance <-1and self.getBalance(root.right)<=0:return self.leftRotate(root)# Case 3 - Left Right if balance >1and self.getBalance(root.left)<0: root.left = self.leftRotate(root.left)return self.rightRotate(root)# Case 4 - Right Left if balance <-1and self.getBalance(root.right)>0: root.right = self.rightRotate(root.right)return self.leftRotate(root)return root
Red-Black Tree
Red-Black Tree 与 AVL 一样是自平衡二叉搜索树(self-balancing BST),它的结构要求:
B Tree 是自平衡搜索树 (self-balancing search tree),与 AVL Tree 以及 Red-Black Tree 不同,它不是二叉搜索树,它的使用场景主要在于整棵树无法一次性载入到内存中的场景,当数据需要在 memory 与 disk 之间传输时,各个操作的时间瓶颈就出现在了 disk I/O 上。因此,B Tree 的设计思想是尽可能地矮,使得通往目标 node 的路径尽可能短,从而减少 disk I/O 次数。通常 B Tree 的每个 node 大小为一个 page/block。
B Tree 的主要性质有:
所有的 leaf nodes 都在同一 level
B Tree 的类型由 minimum degree --- t 来定义,t 的取值取决于 page/block 大小