平衡二叉树:一颗空树,或者是具有以下性质的二叉树

  • 左子树和右子树都是平衡二叉树
  • 左子树和右子树的深度只差不超过1

把二叉树节点的平衡因子BF(Balance Factor)定义为该节点的左子树深度减去右子树深度,则平衡二叉树所有结点的平衡因子只能是-1,0,1。只要有一个结点的平衡因子绝对值大于一就是不平衡的;

平衡二叉树的构造

对二叉树结点做一下定义,bf用来记录结点的平衡因子

1 typedef struct BSTNode{
2     int val;
3     int bf;
4     struct BSTNode *lchild, *rchild;
5 }BSTNode, *BSTree;

在插入新结点的过程中,会出现平衡因子绝对值大于2的情况,这时就需要进行一定的条件,让二叉树保持平衡。失去平衡后进行的调整规律可以归纳为以下四种

  1. 单项右旋处理
  2. 单项左旋处理
  3. 双向(先左后右)旋转处理
  4. 双向(先右后左)旋转处理

单项右旋处理, p为失去平衡的结点。右旋的思路就是

1 void R_Roate(BSTree& p){
2     BSTree temp = p->lchild;
3     p->lchild = temp->rchild;
4     temp->rchild = p;
5     p = temp;
6 }

向二叉树中插入结点:先找到结点插入的位置,建立该结点。调整相关结点的平衡因子。若导致结点失去平衡则需要进行选择,让二叉树恢复平衡。 如何找到新结点插入位置? 如果val的值比当前结点的值小,则继续在当前结点的左子树中寻找插入位置。 如果val的值比当前结点的值大,则继续在当前结点的右子树中寻找插入位置。直到找到一个空的位置位置。当然如果发现存在相同的val,则表示已经存在于二叉树中, 插入失败;  那么又如何判断二叉树是否失去平衡呢? 当当前结点的平衡因子是0的时候,表示该节点左右两边的高度一致,插入一个结点并不会改变当前结点的平衡性,但是会改变当前结点的平衡因子; 当当前结点的平衡因子为1的时候,表示当前节点的左子树比右子树高, 若在当前结点左边插入结点, 必定会导致当前结点的左子树高度和右子树高度相差大于2. 引起不平衡。需要进行旋转来让二叉树恢复平衡, 如果在右子树插入结点,又会让当前结点的的平衡因子变为0;平衡因子为-1的分析过程和前面类似。 参数taller用来标志插入新结点是否让二叉树高度增加, 可以减少程序的计算量

 1 bool InsertAVL(BSTree& T, int val, bool& taller){
 2     if(!T){//插入新结点,树变高
 3         T = (BSTree) malloc(sizeof(BSTNode));
 4         T->val = val; T->bf = EH; T->lchild = T->rchild = NULL;
 5         taller = true;
 6     }else{
 7         if(val==T->val){taller = false; return false;} //如果val存在于二叉树中, 则插入失败
 8         if(val<T->val){ //若果val比当前结点的值小,则把新结点插入到当前结点的左子树中
 9             if(!InsertAVL(T->lchild, val, taller)) return false;
10             if(taller){
11             switch(T->bf){    //插入新结点后要对当前结点的平衡因子做出相应的修改
12             case LH:{LeftBalance(T); taller=false; break;}
13             case EH:{taller = true; T->bf = LH; break;}
14             case RH:{taller = false; T->bf = EH; break;}
15             }}
16         }else{
17             if(!InsertAVL(T->rchild, val, taller)) return false;
18             if(taller){
19             switch(T->bf){
20             case LH:{T->bf = EH; taller = false; break;}
21             case EH:{T->bf = RH; taller = true; break;}
22             case RH:{RightBalance(T); taller = false; break;}
23             }}
24         }
25     }
26     return true;
27 }

全部代码

  1 #include<iostream>
  2 using namespace std;
  3 /*
  4     author: Lai XingYu
  5       date: 2018/5/18
  6   describe: AVL
  7 */
  8 #define LH +1
  9 #define EH 0
 10 #define RH -1
 11
 12 typedef struct BSTNode{
 13     int val;
 14     int bf;
 15     struct BSTNode *lchild, *rchild;
 16 }BSTNode, *BSTree;
 17
 18 void R_Roate(BSTree& p){
 19     BSTree temp = p->lchild;
 20     p->lchild = temp->rchild;
 21     temp->rchild = p;
 22     p = temp;
 23 }
 24
 25 void L_Roate(BSTree& p){
 26     BSTree temp = p->rchild;
 27     p->rchild = temp->lchild;
 28     temp->lchild = p;
 29     p = temp;
 30 }
 31
 32 void LeftBalance(BSTree& T){
 33     BSTree temp = T->lchild;
 34     switch(temp->bf){
 35     case LH:{T->bf = temp->bf = EH; R_Roate(T); break;}
 36     case RH:{
 37                 BSTree t = temp->rchild;
 38                 switch(t->bf){
 39                 case LH:{temp->bf = EH; T->bf = RH; break;}
 40                 case EH:{temp->bf = EH; T->bf = EH; break;}
 41                 case RH:{temp->bf = LH; T->bf = EH; break;}
 42                 }
 43                 t->bf = EH;
 44                 L_Roate(T->lchild);
 45                 R_Roate(T);
 46             }
 47     }
 48 }
 49
 50 void RightBalance(BSTree& T){
 51     BSTree temp = T->rchild;
 52     switch(temp->bf){
 53     case LH:{
 54                 BSTree t = temp->lchild;
 55                 switch(t->bf){
 56                 case LH:{T->bf = EH; temp->bf = RH; break;}
 57                 case EH:{T->bf = EH; temp->bf = EH; break;}
 58                 case RH:{T->bf = LH; temp->bf = EH; break;}
 59                 }
 60                 t->bf = EH;
 61                 R_Roate(T->rchild);
 62                 L_Roate(T);
 63             }
 64     case RH:{T->bf = temp->bf = EH; L_Roate(T); break;}
 65     }
 66 }
 67
 68 /*
 69     taller标志插入新结点后,树的高度是否变高
 70     如果val在二叉树中,则插入失败
 71     如果插入结点让二叉树失去平衡,则要进行选择处理,让二叉树恢复平衡
 72 */
 73 bool InsertAVL(BSTree& T, int val, bool& taller){
 74     if(!T){//插入新结点,树变高
 75         T = (BSTree) malloc(sizeof(BSTNode));
 76         T->val = val; T->bf = EH; T->lchild = T->rchild = NULL;
 77         taller = true;
 78     }else{
 79         if(val==T->val){taller = false; return false;} //如果val存在于二叉树中, 则插入失败
 80         if(val<T->val){ //若果val比当前结点的值小,则把新结点插入到当前结点的左子树中
 81             if(!InsertAVL(T->lchild, val, taller)) return false;
 82             if(taller){
 83             switch(T->bf){    //插入新结点后要对当前结点的平衡因子做出相应的修改
 84             case LH:{LeftBalance(T); taller=false; break;}
 85             case EH:{taller = true; T->bf = LH; break;}
 86             case RH:{taller = false; T->bf = EH; break;}
 87             }}
 88         }else{
 89             if(!InsertAVL(T->rchild, val, taller)) return false;
 90             if(taller){
 91             switch(T->bf){
 92             case LH:{T->bf = EH; taller = false; break;}
 93             case EH:{T->bf = RH; taller = true; break;}
 94             case RH:{RightBalance(T); taller = false; break;}
 95             }}
 96         }
 97     }
 98     return true;
 99 }
100
101 void inorder(BSTree T){
102     if(!T) return;
103     if(T->lchild) inorder(T->lchild);
104     cout<<T->val<<" ";
105     if(T->rchild) inorder(T->rchild);
106 }
107 int main(){
108     int t[] = {1,2,3,4,5,6,7};
109     int f[] = {1,2,5,3,7,6,4};
110     BSTree T = NULL;
111     bool taller;
112     for(int i=0; i<7; i++) InsertAVL(T, f[i], taller);
113     inorder(T);
114 return 0;}

inorder()遍历一颗二叉树,得到的序列一定是单调的。

通过上面的例子可以看到,用相同的数字,不同顺序的序列来构建平衡二叉树,得到的结果是一样的。

平衡二叉树可以让二叉树的高度保持在Logn; 查找任何一个结点,需要进行的比较次数也不会超过logn。

但是如果构建avl的结点是降序的,会对二叉树进行多次选择,带来的开销也是非常大的。

转载于:https://www.cnblogs.com/mr-stn/p/9058567.html

数据结构 平衡二叉树avl c++相关推荐

  1. [ 数据结构 ] 平衡二叉树(AVL)--------左旋、右旋、双旋

    0 引出 数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST), 并分析问题所在 回顾:二叉搜索树 左子树全部为空,从形式上看,更像一个单链表. 插入速度没有影响 查询速度明显降低(因为需 ...

  2. Java数据结构——平衡二叉树(AVL树)

    AVL树的引入 搜索二叉树有着极高的搜索效率,但是搜索二叉树会出现以下极端情况: 这样的二叉树搜索效率甚至比链表还低.在搜索二叉树基础上出现的平衡二叉树(AVL树)就解决了这样的问题.当平衡二叉树(A ...

  3. 数据结构-平衡二叉树(AVL树)

    目录 1,平衡二叉树的介绍 1.1,二叉排序树存在的问题 1.2,平衡二叉树 1.3,平衡二叉树的创建 1.4,平衡二叉树的查找 2,代码实现 2.1,平衡二叉树的节点类型 2.2,LL旋转(单右旋转 ...

  4. 数据结构——平衡二叉树(AVL树)之插入

    文章目录 前言 一.定义 二.基本操作 1.查找, 2.插入(如何调整) 如何调整 代码实现插入 前言 首先我们来思考一下一个普通二叉树保存数据,如果想查找一个数据,由于普通二叉树保存数据是随机的,要 ...

  5. 二叉树(BT)、二叉查找树(BST)、平衡二叉树(AVL)、B-Tree、B+Tree、红黑树(BRT)

    目录 树的概念 树的分类 二叉树 二叉查找树 平衡二叉树(AVL) B-Tree(平衡多路查找树) B树的关键特征 B+Tree B+树关键特征 红黑树(BRT) 左旋 右旋 时间复杂度 树形结构是一 ...

  6. [转]C#与数据结构--树论--平衡二叉树(AVL Tree)

    C#与数据结构--树论--平衡二叉树(AVL Tree) http://www.cnblogs.com/abatei/archive/2008/11/17/1335031.html 介绍 我们知道在二 ...

  7. Python数据结构11:树的实现,树的应用,前中后序遍历,二叉查找树BST,平衡二叉树AVL树,哈夫曼树和哈夫曼编码

    1.概念 树一种基本的"非线性"数据结构. 相关术语: 节点Node:组成树的基本部分.每个节点具有名称,或"键值",节点还可以保存额外数据项,数据项根据不同的 ...

  8. 平衡二叉树平衡因子怎么计算_数据结构PHP 平衡二叉树(AVL)的平衡原理

    这篇文章主要介绍一下 平衡二叉树(AVL),对于 二分搜索树 来说,如果树上的 元素 是顺序 添加的,会导致数据退化成一个 链表,这样就会造成很严重的性能问题,此时就需要在 二分搜索树 的基础上,保证 ...

  9. 数据结构---平衡二叉树

    数据结构-平衡二叉树 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> typedef struct avlTree { ...

最新文章

  1. 347. 前 K 个高频元素(哈希表)
  2. java.io.IOException cannot be resolved
  3. Oracle EBS R12.1.1 应用克隆 - 3
  4. 五一重装WinXP操作系统所遇问题的解决
  5. 2018.03.12、Android知识点-Java篇
  6. 新版 chrome 将原生支持图片懒加载!
  7. 移植最新版libmemcached到VC++的艰苦历程和经验总结(上)
  8. postgresql设置postgres密码_django项目时配置postgresql数据库的方法
  9. ztree 使用教程
  10. 无线Mesh网络技术及其应用
  11. html5 live,HTML5 live streaming
  12. 纪中国庆10.5做题小结
  13. UVALive 4850 Installations——思维
  14. 快递面单隐私保护教程
  15. android的apk加壳工具对比
  16. MYSQL补充SQL语句
  17. Spring(https://www.zhihu.com/question/38597960)
  18. 雅思作文模板.html,雅思作文模板使用分析
  19. 官宣:免费OA办公系统的标准解决方案
  20. 互联网下半场,实体店的转型思考

热门文章

  1. 监控Squid运行脚本
  2. 书写「简历」时,需要规避的错误
  3. 使用 ODP.NET 访问 Oracle(.net如何访问Oracle)详解
  4. RSF 分布式服务框架-传输协议层设计
  5. 虚拟化技术天书:九宫格图解虚拟化——此文多风险,阅读需谨慎
  6. Spring MVC 使用优化建议
  7. PAT 乙级 1005. 继续(3n+1)猜想 (25) Java版
  8. L2-014. 列车调度-PAT团体程序设计天梯赛GPLT
  9. oracle数据库导出和oracle导入数据的二种方法(oracle导入导出数据)
  10. UnityWebform(2):自定义LifetimeManager和TypeConverter使Unity从HttpContext中取值注入WebForm页面...