AVL树

Posted happyknockoncode

tags:

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

AVL树

AVL树是平衡二叉搜索树,比普通二叉搜索树多了一个平衡功能;

当一个节点的左子树与右子树的高度差超过1时 ,就被认为是不平衡的。然后通过旋转二叉树维持平衡。

插入操作

左节点的左子树插入操作(单旋转)插入5号

技术图片

左节点的右子树插入操作(双旋转)插入5号:

技术图片
]

删除操作:

需要删除一个节点时,若只有一个子节点或无子节点,直接替换即可,若有两个子节点,则要判断左右子树的高度,用最高的子树去覆盖要删除的节点,然后释放子树上的节点空间,调整平衡即可。

当删除一个节点后,判断树的高度,若破坏了平衡,则调整平衡;

撸代码:

  1/**
2把二叉树的任何节点的左子树高度减去右子树高度定义为
3该节点的平衡因子。二叉平衡树的平衡因子只能是1、0或者-1。
4
5一、单旋转
61.左节点的左子树插入操作 右旋转
72.右节点的右子树插入操作 左旋转
8
9二、双旋转
101.左节点的右子树插入操作 先左后右旋转
112.右节点的左子树插入操作 先右后左旋转
12*/

13
14#include<stdio.h>
15#include<iostream>
16#include<algorithm>
17using namespace std;
18typedef struct AvlNode
19{

20    int data;
21    AvlNode *m_pLeft;
22    AvlNode *m_pRight;
23    int height;
24}*AvlTree,*Position,AvlNode;
25int Height(AvlTree T)
26
{
27    if(NULL==T)
28        return -1;/**为了使差==2 直线情况*/
29    else
30        return T->height;
31}
32/**单旋转右旋*/
33AvlTree Right(AvlTree T)
34
{
35    AvlTree L=T->m_pLeft;
36    T->m_pLeft=L->m_pRight;
37    L->m_pRight=T;
38    T->height=max(Height(T->m_pLeft),Height(T->m_pRight))+1;
39    L->height=max(Height(L->m_pLeft),Height(L->m_pRight))+1;
40    return L;/**L成为根节点*/
41}
42/**单旋转左旋*/
43AvlTree Left(AvlTree T)
44
{
45    AvlTree R=T->m_pRight;
46    T->m_pRight=R->m_pLeft;
47    R->m_pLeft=T;
48    T->height=max(Height(T->m_pLeft),Height(T->m_pRight))+1;
49    R->height=max(Height(R->m_pLeft),Height(R->m_pRight))+1;
50    return R;/**R成为根节点*/
51}
52/**双旋转 先左旋后右旋*/
53AvlTree doubleRight(AvlTree T)
54
{
55    T->m_pLeft=Left(T->m_pLeft);
56    return Right(T);
57}
58/**双旋转 先右后左*/
59AvlTree doubleLeft(AvlTree T)
60
{
61    T->m_pRight=Right(T->m_pRight);
62    return Left(T);
63}
64AvlTree AvlTreeInsert(AvlTree T,int x)
65
{
66    if(T==NULL)/**设立根节点*/
67    {
68        T=(AvlNode *)malloc(sizeof(struct AvlNode));
69        if(T)
70        {
71            T->data=x;
72            T->m_pLeft=T->m_pRight=NULL;
73            T->height=0;
74        }
75        else
76        {
77            printf("ERROR ");
78            exit(0);
79        }
80    }
81    else if(x<T->data)/**插入左子树*/
82    {
83        T->m_pLeft=AvlTreeInsert(T->m_pLeft,x);/**先插入,后旋转*/
84
85        /**不平衡*/
86        if(Height(T->m_pLeft)-Height(T->m_pRight)==2)
87        {
88            if(x<T->m_pLeft->data)/**左节点的左子树插入操作 右旋转*/
89            {
90                T=Right(T);
91            }
92            else
93            {
94                T=doubleLeft(T);
95            }
96        }
97    }
98    else if(x>T->data)
99    {
100        T->m_pRight=AvlTreeInsert(T->m_pRight,x);
101        if(Height(T->m_pRight)-Height(T->m_pLeft)==2)
102        {
103            if(x>T->m_pRight->data)/**右节点的右子树 左旋*/
104            {
105                T=Left(T);
106            }
107            else
108            {
109                T=doubleRight(T);
110            }
111        }
112    }
113    T->height=max(Height(T->m_pLeft),Height(T->m_pRight))+1;
114    return T;
115}
116AvlTree AvlTree_min(AvlTree T)
117
{
118    if(T->m_pLeft==NULL)
119        return T;
120    else return AvlTree_min(T->m_pLeft);
121}
122AvlTree AvlTree_max(AvlTree T)
123
{
124    if(T->m_pRight==NULL)
125        return T;
126    else return AvlTree_max(T->m_pRight);
127}
128
129/**删除 z 节点,返回根节点*/
130AvlTree deleteNode(AvlTree tree,AvlNode *z)
131
{
132    if(tree==NULL||z==NULL)
133        return NULL;
134    /**待删除节点在tree的左子树上*/
135    if( z->data < tree->data )
136    {
137        tree->m_pLeft=deleteNode(tree->m_pLeft,z);
138        /**删除tree左子树节点后 ,调节AVL树平衡*/
139        /**在tree树上调整平衡*/
140        if(Height(tree->m_pRight)-Height(tree->m_pLeft)==2)
141        {
142            /**画图即可明白*/
143            AvlNode *r=tree->m_pRight;
144            if(Height(r->m_pLeft)>Height(r->m_pRight))
145                tree=doubleLeft(tree);
146            else
147                tree=Left(tree);
148        }
149    }
150    else if( z->data > tree->data )
151    {
152        /**删除tree右子树,调整平衡*/
153        tree->m_pRight=deleteNode(tree->m_pRight,z);
154        if(Height(tree->m_pLeft)-Height(tree->m_pRight)==2)
155        {
156            AvlNode *l=tree->m_pLeft;
157            if(Height(l->m_pRight)>Height(l->m_pLeft))
158                tree=doubleRight(tree);
159            else
160                tree=Right(tree);
161        }
162    }
163    else /**当前删除节点*/
164    {
165        /**左右孩子都有*/
166        if((tree->m_pLeft)&&(tree->m_pRight))
167        {
168            if(Height(tree->m_pLeft)>Height(tree->m_pRight))
169            {
170                /**若左子树较高
171                1 找出左子树最大节点
172                2 最大节点覆盖tree节点
173                3 删除这个叶子最大节点
174                这样尽量可保持平衡
175                */

176                AvlNode *Max =AvlTree_max(tree->m_pLeft);
177                tree->data=Max->data;
178                tree->m_pLeft=deleteNode(tree->m_pLeft,Max);
179            }
180            else
181            {
182                /**同理:找到右子树最小节点覆盖即可*/
183                AvlNode *Min=AvlTree_min(tree->m_pRight);
184                tree->data=Min->data;
185                tree->m_pRight=deleteNode(tree->m_pRight,Min);
186            }
187        }
188        else
189        {
190            /**只有一个孩子节点,直接接上即可*/
191            AvlNode *temp=tree;
192            tree=tree->m_pLeft?tree->m_pLeft:tree->m_pRight;
193            free(temp);
194        }
195    }
196    return tree;
197}
198
199void Find(AvlTree p)
200
{
201    if(p)
202    {
203        printf("根节点 %d ",p->data);
204        if(p->m_pLeft)
205            printf("左儿子:%d ",p->m_pLeft->data);
206        if(p->m_pRight)
207            printf("右儿子:%d ",p->m_pRight->data);
208        printf(" ");
209        Find(p->m_pLeft);
210
211        Find(p->m_pRight);
212    }
213}
214AvlTree getNode(AvlTree T,int x)
215
{
216    while(T&&T->data!=x)
217    {
218        if(T->data>x)
219            T=T->m_pLeft;
220        else
221            T=T->m_pRight;
222    }
223    return T;
224}
225int main()
226
{
227    AvlTree root = NULL;
228    for(int i=1;i<=5;i++)
229    {
230        root = AvlTreeInsert(root,i);
231    }
232    Find(root);
233    printf(" ***************** ");
234    root=deleteNode(root,getNode(root,1));
235    Find(root);
236    return 0;
237}

学习博客:https://www.cnblogs.com/skywang12345/p/3576969.html
https://www.cnblogs.com/zhuwbox/p/3636783.html















































































































































































































































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

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

[算法] 数据结构之AVL树

树:AVL树

徒手写的AVL竟然比STL中的红黑树效率更高?✨

AVL树

C++ AVL树