AVL樹新增及自旋python實現
阿新 • • 發佈:2020-11-14
from collections import deque from dataStructures.tree.biTree.bst import BiTreeNode, BST class AVLNode(BiTreeNode): def __init__(self, data): BiTreeNode.__init__(self, data) self.bf = 0 #存平衡因子 class AVLTree(BST): def __init__(self, li=None): BST.__init__(self, li) def rotate_left(self, p, c): #c是當前node,p是node.parent s2 = c.lchild p.rchild = s2 if s2: s2.parent = p c.lchild = p p.parent = c p.bf = 0 c.bf = 0 return c def rotate_right(self, p, c): s2 = c.rchild p.lchild = s2 if s2: s2.parent = p c.rchild = p p.parent = c p.bf = 0 c.bf = 0 return c def rotate_right_left(self, p, c): g = c.lchild # 先右旋,變成右右結構 s3 = g.rchild c.lchild = s3 if s3: s3.parent = c g.rchild = c c.parent = g s2 = g.lchild p.rchild = s2 if s2: s2.parent = p g.lchild = p p.parent = g # 更新bf(右邊-左邊) # (1)插入s3 if g.bf > 0: p.bf = -1 c.bf = 0 # (2)插入s2 elif g.bf < 0: p.bf = 0 c.bf = 1 else: # 插入的是g p.bf = 0 c.bf = 0 # 插入的是g(意味著s1、s2、s3、s4為空) return g def rotate_left_right(self, p, c): g = c.rchild s2 = g.lchild c.rchild = s2 if s2: s2.parent = c g.lchild = c c.parent = g s3 = g.rchild p.lchild = s3 if s3: s3.parent = p g.rchild = p p.parent = g # 更新bf if g.bf < 0: # 插入s2 p.bf = 1 c.bf = 0 elif g.bf > 0: # 插入s3 p.bf = 0 c.bf = -1 else: p.bf = 0 c.bf = 0 return g def insert_no_rec(self, val): # 1. 和BST一樣,插入 p = self.root if not p: # 空樹 self.root = AVLNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild # node儲存就是插入的結點 else: # 左孩子不存在 p.lchild = AVLNode(val) p.lchild.parent = p node = p.lchild # node 儲存的就是插入的節點 break elif val > p.data: if p.rchild: p = p.rchild else: p.rchild = AVLNode(val) p.rchild.parent = p node = p.rchild break else: # val == p.data return # 2. 更新balance factor while node.parent: # node.parent不空 if node.parent.lchild == node: # 傳遞是從左子樹來的,左子樹更沉了 #更新node.parent的bf -= 1 if node.parent.bf < 0: # 原來node.parent.bf == -1, 更新後變成-2 # 做旋轉 # 看node哪邊沉 g = node.parent.parent # 為了連線旋轉之後的子樹 x = node.parent # 旋轉前的子樹的根 #從當前node.bf判斷是左邊插入還是右邊 if node.bf > 0: n = self.rotate_left_right(node.parent, node) # n為旋轉之後子樹的頭節點 else: n = self.rotate_right(node.parent, node) # 記得:把n和g連起來 elif node.parent.bf > 0: # 原來node.parent.bf = 1,更新之後變成0 node.parent.bf = 0 break else: # 原來node.parent.bf = 0,更新之後變成-1 node.parent.bf = -1 node = node.parent continue else: # 傳遞是從右子樹來的,右子樹更沉了 #更新node.parent.bf += 1 if node.parent.bf > 0: # 原來node.parent.bf == 1, 更新後變成2 # 做旋轉 # 看node哪邊沉 g = node.parent.parent # 為了連線旋轉之後的子樹 x = node.parent # 旋轉前的子樹的根 #➡由此判斷是父節點的左子樹還是右子樹 if node.bf < 0: # node.bf = -1 #右左結構 n = self.rotate_right_left(node.parent, node) else: # node.bf = 1 #右右結構 n = self.rotate_left(node.parent, node) # 記得連起來 elif node.parent.bf < 0: # 原來node.parent.bf = -1,更新之後變成0 node.parent.bf = 0 break else: # 原來node.parent.bf = 0,更新之後變成1 node.parent.bf = 1 node = node.parent continue # 連結旋轉後的子樹 n.parent = g if g: # g不是空 #判斷原來是在左孩子還是右孩子 if x == g.lchild: g.lchild = n else: g.rchild = n break else: self.root = n break def level_order(self, root): queue = deque() queue.append(root) while len(queue) > 0: node = queue.popleft() print(node.data, end=',') if node.lchild: queue.append(node.lchild) if node.rchild: queue.append(node.rchild) tree = AVLTree([10,5,0])