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

左旋转、右旋转

 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

右→左旋转、左→右旋转

 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

插入

 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

原文地址:https://www.cnblogs.com/steven2020/p/10687170.html

时间: 2024-10-14 05:36:02

AVL树插入(Python实现)的相关文章

AVL树插入和删除

一.AVL树简介 AVL树是一种平衡的二叉查找树. 平衡二叉树(AVL 树)是一棵空树,或者是具有下列性质的二叉排序树:    1它的左子树和右子树都是平衡二叉树,    2且左子树和右子树高度之差的绝对值不超过 1. 定义平衡因子(BF)为该结点左子树的高度减去右子树的高度所得的高度差:AVL 树任一结点平衡因子只能取-1,0,1: 二.AVL树插入 插入:先查找被插入元素,如果存在,则不操作:如果不存在,则插入. 插入后就是调整和选择的问题. 我们先看一下我们会面临怎么样的问题: 离插入点最

AVL树插入删除

写了好久,感觉插入和删除麻烦些,插入也就4种情况,但只要写两个函数,左左和右右的,左右的情况是以根节点的左子树为头进行一次右右旋转,使它变成左左的情况,再左左旋转下就下,右左的也一样: 另外就是删除,先是判断要删除的节点右儿子是否为空,是空,直接删,否则找到它最左边的儿子来替代它,然后就是高度的更新,重新的旋转... 哎,真实花了我好长时间,不过终于写完了.大致感觉没啥问题了吧,有的话以后再改吧. #include <iostream> #include <cstdio> #inc

AVL树插入操作InsertAVL的实现

AVL树是非常重要的一种数据结构,这里实现了在AVL树中的插入操作,包括插入后整个树的自平衡. 这里有几点值得注意的地方: 1).左旋L_Rotate与右旋R_Rotate操作: 这两个操作传递进来的参数是以TreeNode*&的形式传递进来的,也就是说传递的是指针的引用,效果等价于传递二级指针 如果不加入&,则在函数内部更改的是形参的指向,因为实际上函数调用时,如果不采用引用传递,则会构造一个与原T指向同一个地方的临时变量指针,在X_Rotate的内部也是对这个临时变量进行操作,等到返回

AVL树非递归插入删除思路

AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树.AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文<An algorithm for the organization of information>中发表了它. 节点的平衡因子是它的左子树的高度减去它的右子树的

AVL树的插入与删除

AVL 树要在插入和删除结点后保持平衡,旋转操作必不可少.关键是理解什么时候应该左旋.右旋和双旋.在Youtube上看到一位老师的视频对这个概念讲解得非常清楚,再结合算法书和网络的博文,记录如下. 1.1 AVL 的旋转 一棵AVL树是其每个节点的左子树和右子树的高度差最多为1的二叉查找树(空树高度定义为-1).AVL树插入和删除时都可能破坏AVL的特性,可以通过对树进行修正来保证特性,修正方法称为旋转. 下面以4个插入操作为例,说明不同旋转对应的场景. 1.1.1 LL-R 插入结点为6,沿着

python常用算法(5)——树,二叉树与AVL树

1,树 树是一种非常重要的非线性数据结构,直观的看,它是数据元素(在树中称为节点)按分支关系组织起来的结构,很像自然界中树那样.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形象表示.树在计算机领域中也得到了广泛应用,如在编译源程序时,可用树表示源程序的语法结构.又如在数据库系统中,树型结构也是信息的重要组织形式之一.一切具有层次关系的问题都可以用树来描述. 树(Tree)是元素的集合.树的定义是递归的,树是一种递归的数据结构.比如:目录结构.树是由n个结点组成的集合:如

AVL树 冲突链表

;红黑树只不过是AVL树的变种而已 ,平衡方式耕地,意味着比AVL旋转的次数少,长应用于关联数组 红黑树和AVL树在实际开发中比较常用 ;AVL树二叉平衡树 适合在内存中使用速度会达到最优化,要是在文件中那么速度大大降低 ;文件中适合用b+树,B+树读文件一次读的孩子结点比较多,一次read读取尽量多的结点到内存中缓存起来,下次直接从内存中返回. ;百万级别的数据存文件用c库函数利用缓冲区一次不要读两个缓冲区的内容(<4096)设计树的结构,超过就自己设计fopen喽自己做大的缓冲区,降低文件访

平衡二叉树之AVL树

AVL树(命名来源于作者姓名,Adelson-Velskii和Landis),即平衡二叉树,满足以下的条件: 1)它的左子树和右子树都是AVL树 2)左子树和右子树的高度差不能超过1 从条件1可能看出是个递归定义. AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树. AVL树插入节点的步骤,分为2类: 第1类:外侧插入,单旋转 第2类:内侧插入,双旋转(先旋转成外侧插入的情况,再单旋转) 由于调整以后,树高与插入前是相同的,所以无需再向上查看balance情况 代码实

My集合框架第三弹 AVL树

旋转操作: 由于任意一个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情况造成的: 1. 对该结点的左儿子的左子树进行了一次插入. 2. 对该结点的左儿子的右子树进行了一次插入. 3. 对该结点的右儿子的左子树进行了一次插入. 4. 对该结点的右儿子的右子树进行了一次插入. 向AVL树插入节点后,需要让AVL树重新平衡 step1:从插入节点向根节点溯源,观察是否存在不平衡节点(左右子树高度差),    if(不存在),return    else  step2step2:标记不平衡