AVL树插入(Python实现)

Posted ok代码我改了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVL树插入(Python实现)相关的知识,希望对你有一定的参考价值。

建立AVL树

技术图片
 1 class AVLNode(object):
 2     def __init__(self,data):
 3         self.data = data
 4         self.lchild = None
 5         self.rchild = None
 6         self.parent = None
 7         self.bf = 0
 8 
 9 class AVLTree(object)
10     def __init__(self,li=None)
11         self.root = None
12         if li:
13             for val in li:
14                 self.insert(self.root,val)
15 
16     def insert(self,node,val):
17         if not node:
18             node = AVLNode(val)
19         elif val < node.data:
20             node.lchild = self.insert(node.lchild,val)
21             node.lchild.parent = node
22         elif val > node.data:
23             node.rchild = self.insert(node.rchild,val)
24             node.rchild.parent = node
25         return node
View Code

左旋转、右旋转

技术图片
 1     def rorate_left(self,p,c):
 2         s2 = c.lchild
 3         p.rchild = s2
 4         if s2:
 5             s2.parent = p
 6         c.lchild = p
 7         p.parent = c
 8         p.bf = 0
 9         c.bf = 0
10         return c
11 
12     def rorate_right(self,p,c):
13         s2 = c.rchild
14         p.lchild = s2
15         if s2:
16             s2.parent
17         c.rchild = p
18         p.parent = c
19         p.bf = 0
20         c.bf = 0
21         return c
View Code

右→左旋转、左→右旋转

技术图片
 1     def rotate_right_left(self,p,c):
 2         g = c.lchild
 3 
 4         #右旋
 5         s3 = g.rchild #1.把右孩子拿出来
 6         c.lchild = s3 #2.右孩子交给 C
 7         if s3:
 8             s3.parent = c 
 9         g.rchild = c #3.链接右孩子
10         c.parent = g #4.链接父结点
11 
12         #左旋
13         s2 = g.lchild
14         p.rchild = s2
15         if s2:
16             s2.parent = p
17         g.lchild = p
18         p.parent = g
19 
20         #更新bf
21         if g.bf > 0: #插入到s3 #是指刚插入节点的g的平衡值
22             p.bf = -1
23             c.bf = 0
24         elif g.bf < 0: #插入到s2
25             p.bf = 0
26             c.bf = 1
27         else:  #插入的是G本身
28             p.bf = 0
29             c.bf = 0
30         g.bf = 0
31         return g
32 
33     def rotate_left_right(self,p,c):
34         g = c.rchild
35 
36         #左旋
37         s2 = g.lchild 
38         c.rchild = s2
39         if s2:
40             s2.parent = c
41         g.lchild = c
42         c.parent = g
43 
44         #右旋
45         s3 = g.rchild
46         p.lchild = s3
47         if s3:
48             s3.parent = p
49         g.rchild = p
50         p.parent = g
51 
52         #更新bf 
53         if g.bf < 0: #插入到s2
54             p.bf = 1
55             c.bf = 0 
56         elif g.bf > 0: #插入到s3
57             p.bf = 0
58             c.bf = -1
59         else:  #插入的是G本身
60             p.bf = 0
61             c.bf = 0
62         g.bf = 0
63         return g
View Code

插入

技术图片
 1     def insert_no_rec(self,val):
 2         #1.插入
 3         p = self.root
 4         if not p:
 5             self.root = AVLNode(val)
 6             return
 7         while True:
 8             if val < p.data:
 9                 if p.lchild: #左孩子存在 
10                     p = p.lchild
11                 else:  #左孩子不存在
12                     p.lchild = AVLNode(val)
13                     p.lchild.parent = p
14                     node = p.lchild #node 存储的就是插入的节点
15                     break
16             else val > p.data:
17                 if p.rchild: 
18                     p = p.rchild
19                 else: 
20                     p.rchild = AVLNode(val)
21                     p.rchild.parent = p
22                     node = p.rchild
23                     break
24             else: #等于 #同样的元素不多次插入
25                   #avl尽量不允许两个相同的数插入 
26                 return 
27 
28         #2.更新balance factor
29         while node.parent: #node.parent 不为空时
30             if node.parent.lchild == node: #传递节点是在左子树,左子树更沉了
31                 #第一乱循环,更新node.parent的bf -= 1
32                 if node.parent.bf < 0: #原来node.parent.bf == -1 (更新后会变成-2)
33                     # 做旋转
34                     # 看node哪边沉
35                     head = node.parent.parent #为了链接旋转之后的子树
36                     tmp = node.parent #旋转前的子树的根
37                     if node.bf > 0: 
38                         n = self.rotate_left_right(node.parent,node)
39                     else:
40                         n = self.rorate_right(node.parent,node)
41                 elif node.parent.bf > 0: #原来node.parent.bf == 1 (更新后变成0)
42                     node.parent.bf = 0 #平衡,即可以不需要确认父亲节点
43                     break 
44                 else: #原来node.parent.bf = 0,更新之后变成-1
45                     node.parent.bf = -1
46                     node = node.parent
47                     continue
48             else: #传递节点是在右子树,右子树更沉了
49                 if node.parent.bf > 0:
50                     head = node.parent.parent 
51                     tmp = node.parent 
52                     if node.bf < 0:
53                         n = self.rotate_right_left(node.parent,node)
54                     else:
55                         n = self.rorate_left(node.parent,node)
56                 elif node.parent.bf < 0:
57                     node.parent.bf = 0
58                     break
59                 else:
60                     node.parent.bf = 1
61                     node = node.parent
62                     continue
63 
64             #3.链接旋转后的子树(只有做了旋转之后才会到这一步)
65             n.parent = head
66             if head: #head不是空
67                 if tmp == head.lchild:
68                     head.lchild = n
69                 else:
70                     head.rchild = n
71                 break
72             else:
73                 self.root = n
74                 break
View Code

 

以上是关于AVL树插入(Python实现)的主要内容,如果未能解决你的问题,请参考以下文章

二叉查找树,AVL,红黑树的Python实现

C++AVL树的实现--详细解析旋转细节

C++AVL树的实现--详细解析旋转细节

手撕AVL树(详解插入时的4种旋转)

AVL树/红黑树介绍及插入操作实现

AVL树/红黑树介绍及插入操作实现