AVL树模板

  1 ///AVL树模板
  2 typedef struct Node     ///树的节点
  3 {
  4     int val,data;
  5     int h;               ///以当前结点为根结点的数的高度
  6     int bf;             ///平衡因子(左子树高度与右子树高度之差)
  7     Node *left,*right;
  8 }Node;
  9
 10 class AvlTree          ///alv树,树中太多函数,用类来实现容易一些
 11 {
 12 private:
 13     Node *root;        ///树的根节点
 14 public:
 15     void Init()        ///初始化树
 16     {
 17         root=NULL;
 18     }
 19     int Height(Node *T) ///取一个节点的高度
 20     {
 21         if (T==NULL) return 0;
 22         return T->h;
 23     }
 24     int Bf(Node *T)    ///计算一个节点的平衡因子
 25     {
 26         if (T->left==T->right) return 0;
 27         if (T->left==NULL) return -(T->right->h);  ///这里一定取负数(左子树高度与右子树高度之差)
 28         if (T->right==NULL) return T->left->h;
 29         return (T->left->h)-(T->right->h);
 30     }
 31     ///四种旋转,不知为什么,自己多画一下就知道了。
 32     Node *LL_rotate(Node *T)  ///单向右旋平衡处理LL:由于在*T的左子树根结点的左子树上插入结点
 33     {
 34         Node *B=T->left;
 35         T->left=B->right;
 36         B->right=T;
 37         T->h=max(Height(T->left),Height(T->right))+1;
 38         B->h=max(Height(B->left),Height(T->right))+1;
 39         T->bf=Bf(T);
 40         B->bf=Bf(B);
 41         return B;
 42     }
 43     Node *RR_rotate(Node *T) ///单向左旋平衡处理RR:由于在*T的右子树根结点的右子树上插入结点
 44     {
 45         Node *B=T->right;
 46         T->right=B->left;
 47         B->left=T;
 48         T->h=max(Height(T->left),Height(T->right))+1;
 49         B->h=max(Height(B->left),Height(T->right))+1;
 50         T->bf=Bf(T);
 51         B->bf=Bf(B);
 52         return B;
 53     }
 54     Node *LR_rotate(Node *T)   ///双向旋转平衡处理LR:由于在*T的左子树根结点的右子树上插入结点
 55     {
 56         T->left=RR_rotate(T->left);
 57         T=LL_rotate(T);
 58         return T;
 59     }
 60     Node *RL_rotate(Node *T) ///双向旋转平衡处理RL:由于在*T的右子树根结点的左子树上插入结点
 61     {
 62         T->right=LL_rotate(T->right);
 63         T=RR_rotate(T);
 64         return T;
 65     }
 66     void Insert(int v,int e) ///root是private,所以不能从主函数传入
 67     {
 68         Insert(root,v,e);
 69     }
 70     void Insert(Node *&T,int v,int e) ///插入新节点
 71     {
 72         if (T==NULL)
 73         {
 74             T=(Node *)malloc(sizeof(Node));
 75             T->h=1;
 76             T->bf=0;
 77             T->val=v;
 78             T->data=e;
 79             T->left=T->right=NULL;
 80             return ;
 81         }
 82         if (e<T->data) Insert(T->left,v,e);
 83         else Insert(T->right,v,e);
 84         T->h=max(Height(T->left),Height(T->right))+1;  ///计算节点高度
 85         T->bf=Bf(T);                                   ///计算平衡因子
 86         if (T->bf>1||T->bf<-1)                         ///调整平衡,四种调整反法
 87         {
 88             if (T->bf>1&&T->left->bf>0) T=LL_rotate(T);  ///如果T->bf > 1 则肯定有左儿子
 89             if (T->bf<-1&&T->right->bf<0) T=RR_rotate(T); ///如果T->bf < -1 则肯定有右儿子
 90             if (T->bf>1&&T->left->bf<0) T=LR_rotate(T);
 91             if (T->bf<-1&&T->right>0) T=RL_rotate(T);
 92         }
 93     }
 94     void Find(int flag)   ///flag=1为找最大值,否则找最小值
 95     {
 96         if (root==NULL)
 97         {
 98             printf("0\n");
 99             return ;
100         }
101         Node *temp=root;
102         if (flag)     ///最大值一定最右边
103         {
104             while (temp->right)
105             temp=temp->right;
106         }
107         else
108         {
109             while (temp->left)
110             temp=temp->left;
111         }
112         printf("%d\n",temp->val);
113         Delete(root,temp->data);   ///删除相应节点
114     }
115     void Delete(Node *&T,int e)
116     {
117         if (T==NULL) return ;
118         if (e<T->data) Delete(T->left,e);
119         else if (e>T->data) Delete(T->right,e);
120         else    ///找到删除的节点
121         {
122             if (T->left&&T->right)  ///删除的节点左右都还有节点
123             {
124                 Node *temp=T->left; ///把左子树的最大值当做当前节点
125                 while (temp->right) temp=temp->right; ///找最大值
126                 T->val=temp->val;
127                 T->data=temp->data;
128                 Delete(T->left,temp->data);  ///左子树最大值已近改为当前根节点,应该删除原来位置
129             }
130             else
131             {
132                 Node *temp=T;
133                 if (T->left) T=T->left;     ///删除节点只存在左子树
134                 else if (T->right) T=T->right; ///删除节点只有右子树
135                 else             ///删除节点没有孩子
136                 {
137                     free(T);
138                     T=NULL;
139                 }
140                 if (T) free(temp);
141                 return ;
142             }
143         }
144         T->h=max(Height(T->left),Height(T->right))+1;
145         T->bf=Bf(T);
146         if (T->bf>1||T->bf<-1)   ///删除后一定要调整
147         {
148             if (T->bf>1&&T->left->bf>0) T=LL_rotate(T);
149             if (T->bf<-1&&T->right->bf<0) T=RR_rotate(T);
150             if (T->bf>1&&T->left->bf<0) T=LR_rotate(T);
151             if (T->bf<-1&&T->right>0) T=RL_rotate(T);
152         }
153     }
154     void Free()  ///由于内存是malloc出来的,最后一定要释放
155     {
156         FreeNode(root);
157     }
158     void FreeNode(Node *T)
159     {
160         if (T==NULL) return ;
161         if (T->right) FreeNode(T->right);
162         if (T->left) FreeNode(T->left);
163         free(T);
164     }
165 };
时间: 2024-07-30 13:49:15

AVL树模板的相关文章

PTA Root of AVL Tree (AVL树模板+四种旋转+指针)

关于AVL树(平衡二叉搜索树,高度为lgn)的讲解,双手呈上某大佬博客:https://www.cnblogs.com/zhuwbox/p/3636783.html 我从这题get到一个新的结构体写法(姿势): typedef struct treeNode { int val; treeNode *left; treeNode *right; int height; }node, *tree;//node 是treeNode结构体,*tree是结构体指针 我对AVL树的理解: 按照插入节点时旋

C++模板实现的AVL树

1 AVL树的定义 AVL树是一种自平衡二叉排序树,它的特点是任何一个节点的左子树高度和右子树的高度差在-1,0,1三者之间.AVL树的任何一个子树都是AVL树. 2 AVL树的实现 AVL树本质是一种二叉排序树,所以二叉排序树的任何性质AVL树都具有,但是AVL树稍微复杂的地方就是AVL树必须满足平衡条件,具体跟BST不同的地方主要体现在插入,删除操作. 插入操作:当插入之后可能会出现不平衡,所以这时候要通过旋转树来实现平衡.旋转有四种类型,左左,左右,右左,右右.其中左左旋转和右右旋转是镜像

AVL树(自平衡树)——c++实现

AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树). 既然是树,那么就要有节点: template <class T> struct AVLTreeNode{ T data; int height; AVLTreeNod

AVL树

定义:AVL树是每个节点左子树和右子树的高度差最大为1的二叉查找树 不平衡节点:假设在懒惰删除(删除操作时,并不删除节点,只是对节点进行特定标记)的条件下,插入操作有可能破坏AVL树的平衡特性. 如果插入节点导致平衡性被破坏,那么平衡性遭到破坏的节点只可能出现在插入节点到根节点的路径上.因为插入操作只会改变 插入节点的父节点的高度,而这些父节点就再这条路径上. 调整:对于平衡性遭到破坏的节点,需要对其进行调整以恢复平衡性.调整的方法称为旋转,针对不同的插入情况,调整操作稍有不同. 下面先对插入情

数据结构--AVL树

AVL树是高度平衡的二叉搜索树,较搜索树而言降低了树的高度:时间复杂度减少了使其搜索起来更方便: 1.性质: (1)左子树和右子树高度之差绝对值不超过1: (2)树中每个左子树和右子树都必须为AVL树: (3)每一个节点都有一个平衡因子(-1,0,1:右子树-左子树) (4)遍历一个二叉搜索树可以得到一个递增的有序序列 2.结构: 平衡二叉树是对二叉搜索树(又称为二叉排序树)的一种改进.二叉搜索树有一个缺点就是,树的结构是无法预料的.任意性非常大.它仅仅与节点的值和插入的顺序有关系.往往得到的是

poj3630 Phone List (trie树模板题)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26328   Accepted: 7938 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogu

AVL树原理及实现(C语言实现以及Java语言实现)

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是我们无法忍受的.即使是一颗由完全随机的数据构造成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操作,这个搜索二叉树的高度也不能令人满意.这个

HDU 1251 Trie树模板题

1.HDU 1251 统计难题  Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b #define F(i,a,b

数据结构与算法系列----平衡二叉树(AVL树)

一:背景 平衡二叉树(又称AVL树)是二叉查找树的一个进化体,由于二叉查找树不是严格的O(logN),所以引入一个具有平衡概念的二叉树,它的查找速度是O(logN).所以在学习平衡二叉树之前,读者需要了解二叉查找树的实现,具体链接:二叉查找树 那么平衡是什么意思?我们要求对于一棵二叉查找树 ,它的每一个节点的左右子树高度之差不超过1.(对于树的高度的约定:空节点高度是0:叶子节点高度是1.)例如下图: 如果我们的二叉查找树是不平衡该怎么办?进行旋转.经过分析发现,出现不平衡无外乎四种情况,下面我