平衡二叉树(AVL树)定义如下:平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树:

  (1)它的左子树和右子树的高度之差绝对值不超过1;

  (2)它的左子树和右子树都是平衡二叉树。

  AVL树避免了平衡二叉树初始序列有序建立的类似单链表情况,提高了查找效率。

  1.AVL树的相关参量定义

  1. #define _CRT_SECURE_NO_DEPRECATE
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<windows.h>
  5. #define DataType int
  6. #define LH 1 //左边高一层
  7. #define EH 0 //左右分支等高
  8. #define RH -1 //右边高一层
  9. const int MAXSIZE = 100;//栈和队列的最大容量
  10. typedef struct BSTNode{
  11. DataType data;
  12. int bf;//平衡因子,值为LH、EH、RH
  13. struct BSTNode *lchild, *rchild;
  14. }BSTNode, *BSTree;

  2.插入函数

  1. bool InsertAVL(BSTree &T,DataType x,boolean &taller)//插入后是否长高,一处修改处处修改,taller为bool类型
  2. {//插入过程伴随着查找过程,没有则插入
  3. if (!T)//如果空树,则直接添加新结点
  4. {
  5. T = (BSTree)malloc(sizeof(BSTNode));
  6. T->data = x;
  7. T->lchild = T->rchild = NULL;
  8. T->bf = EH;
  9. taller = true;//长高了
  10. }
  11. else
  12. {
  13. if (T->data == x)//数据元素已存在,不必插入
  14. {
  15. taller = false;
  16. return false;
  17. }
  18. else if (x < T->data)//数据在树根的左分支
  19. {
  20. if (!InsertAVL(T->lchild, x, taller))//左分支已存在,但即使不存在也返回了taller的值
  21. return false;
  22. if (taller)//如果导致树长高了,则进一步判断及处理
  23. {
  24. switch (T->bf)
  25. {
  26. case LH://左分支本来就比右分支高一层,又加了一层,当然进行左平衡
  27. LeftBalence(T);//左调平衡函数
  28. taller = false;
  29. break;
  30. case EH://本来左右等高,修改标志位即可
  31. T->bf = LH;
  32. taller = true;
  33. break;
  34. case RH://本来右分支高1,修改标志位
  35. T->bf = EH;
  36. taller = false;
  37. break;
  38. }
  39. }
  40. }
  41. else
  42. {
  43. if (!InsertAVL(T->rchild, x, taller))//进行T的右分支,同理
  44. return false;
  45. if (taller)
  46. {
  47. switch (T->bf)
  48. {
  49. case RH:
  50. RightBalence(T);
  51. taller = false;
  52. break;
  53. case EH:
  54. T->bf = RH;
  55. taller = true;
  56. break;
  57. case LH:
  58. T->bf = EH;
  59. taller = false;
  60. break;
  61. }
  62. }
  63. }
  64. }
  65. return true;
  66. }

  3.着重分析左右调平衡函数

  左调平衡

有且仅有两种情况,一定是原本左边比右边高1层,而且在左边加了1层才要左调平衡的。

(1)

                           

  这种情况是在原本的根节点T的左孩子L上加了左孩子,显然此时T和L都无右孩子,所以要调整为L为根节点,也就是T根节点右旋(顺时针旋转)。

  调整完显然平衡因子bf变化为  T->bf = L->bf = EH;

(2)另一种是在原本的根节点T的左孩子L上加了右孩子导致失衡(某一结点的做右分支高度相差大于1)产生。

(A)

             

  对应(1)的情况,在L加了右孩子Lr,且L无左孩子,T无右孩子。先将L左旋(L逆时针旋转)得到类似(1)的情形,然后将T右旋。

  调整完三个结点平衡因子  T->bf = L->bf =Lr->bf= EH;

(B)此种情况为在L的右孩子Lr上加了左孩子

       

  先将L左旋,Lr作为L的双亲结点T的左孩子,L作为Lr的左孩子,Lr的左孩子作为L的右孩子,这也是具体的左旋算法,然后将T右旋。

  调整完三个结点平衡因子    T->bf = RH;   L->bf = EH;   Lr->bf = EH;

(C)此种情况为在L的右孩子Lr上加了右孩子

    

  先将L左旋,然后将T作为Lr的右孩子,且将Lr的右孩子最为T的左孩子,这也是具体的右旋算法。

  调整完三个结点平衡因子 T->bf = EH;  L->bf = LH; Lr->bf = EH;

  注意,此调平衡的规则的代码是递归式的,所以一定是从底层往上层调平衡,也就是说下面先调平衡。

总结(2):具体的也分析了左旋右旋的具体算法,每种情况都有Lr->bf=EH,并且算法都符合平衡二叉树的规则要求。

  1. void R_Rotate(BSTree &T)//右旋,T的左孩子可能有右孩子或者为空,一起整
  2. {
  3. BSTree p;
  4. p = T->lchild;
  5. T->lchild = p->rchild;
  6. p->rchild = T;
  7. T=p;
  8. }
  9. void L_Rotate(BSTree &T)//左旋
  10. {
  11. BSTree p;
  12. p = T->rchild;
  13. T->rchild = p->lchild;
  14. p->lchild = T;
  15. T = p;
  16. }
  17. void LeftBalence(BSTree &T)//平衡左分支
  18. {
  19. BSTree L, Lr;
  20. L = T->lchild;
  21. switch (L->bf)
  22. {
  23. case LH://是在根节点T的左孩子L的左孩子上加了结点导致失衡
  24. T->bf = L->bf = EH;//调整后的参数变化
  25. R_Rotate(T);//右旋根节点T
  26. break;
  27. case RH://是在根节点T的左孩子L的左孩子上加了结点导致失衡
  28. Lr = L->rchild;
  29. switch (Lr->bf)//对L的右孩子Lr的参数bf进行判断及进一步分析
  30. {
  31. case LH://Lr的左边加了新结点
  32. T->bf = RH;
  33. L->bf = EH;
  34. break;
  35. case EH://Lr左右等高
  36. T->bf = L->bf = EH;
  37. break;
  38. case RH://Lr的右边边加了新结点
  39. T->bf = EH;
  40. L->bf = LH;
  41. break;
  42. }
  43. //统一改参数,先左旋T的左孩子,再右旋T
  44. Lr->bf = EH;
  45. L_Rotate(T->lchild);
  46. R_Rotate(T);
  47. }
  48. }

  右调平衡与左调平衡类似的分析方法。

  1. void RightBalence(BSTree &T)//平衡右分支
  2. {
  3. BSTree R, Rl;
  4. R = T->rchild;
  5. switch (R->bf)
  6. {
  7. case RH:
  8. T->bf = R->bf = EH;
  9. L_Rotate(T);
  10. break;
  11. case LH:
  12. Rl = R->lchild;
  13. switch (Rl->bf)
  14. {
  15. case RH:
  16. T->bf = LH;
  17. R->bf = EH;
  18. break;
  19. case EH:
  20. T->bf = R->bf = EH;
  21. break;
  22. case LH:
  23. T->bf = EH;
  24. R->bf = RH;
  25. break;
  26. }
  27. Rl->bf = EH;
  28. R_Rotate(T->rchild);
  29. L_Rotate(T);
  30. }
  31. }

  4.创建函数及其他函数

  1. void CreatAVL(BSTree &T,int n)//创建AVL树,用到了插入函数
  2. {
  3. printf("请输入%d个数据:\n", n);
  4. int a;
  5. boolean taller = 0;//初始化
  6. for (int i = 0; i < n; i++)//循环添加
  7. {
  8. scanf("%d", &a);
  9. InsertAVL(T, a,taller);
  10. }
  11. }
  12. void InOrder(BSTree &T)//中序遍历看是否是递增序列
  13. {
  14. if (T)
  15. {
  16. InOrder(T->lchild);
  17. printf("%3d", T->data);
  18. InOrder(T->rchild);
  19. }
  20. }
  21. void TreeDispNode(BSTree bt)//括号表示法,用来看树的构造情况
  22. {
  23. if (bt != NULL)
  24. {
  25. printf("%d", bt->data);
  26. if (bt->lchild != NULL || bt->rchild != NULL)
  27. {
  28. printf("(");
  29. TreeDispNode(bt->lchild);
  30. if (bt->rchild != NULL)printf(",");
  31. TreeDispNode(bt->rchild);
  32. printf(")");
  33. }
  34. }
  35. }

  5.测试代码

  1. int main()//测试代码
  2. {
  3. BSTree mytree=NULL;
  4. CreatAVL(mytree, 10);
  5. InOrder(mytree);
  6. printf("\n");
  7. TreeDispNode(mytree);
  8. printf("\n");
  9. system("pause");
  10. return 0;
  11. }

  注意:代码的相关函数要调整位置,使得被调用的函数在调用其的函数之前,分析调整代码应数形结合。

数据结构之平衡二叉树(AVL树)的更多相关文章

  1. 【数据结构】平衡二叉树—AVL树

    (百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...

  2. 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)

    二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...

  3. 数据结构与算法——AVL树类的C++实现

    关于AVL树的简单介绍能够參考:数据结构与算法--AVL树简单介绍 关于二叉搜索树(也称为二叉查找树)能够參考:数据结构与算法--二叉查找树类的C++实现 AVL-tree是一个"加上了额外 ...

  4. Java 树结构实际应用 四(平衡二叉树/AVL树)

    平衡二叉树(AVL 树) 1 看一个案例(说明二叉排序树可能的问题) 给你一个数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST), 并分析问题所在.  左边 BST 存在的问题分析: ...

  5. 平衡二叉树,AVL树之图解篇

    学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...

  6. 数据结构(三)实现AVL树

    AVL树的定义 一种自平衡二叉查找树,中面向内存的数据结构. 二叉搜索树T为AVL树的满足条件为: T是空树 T若不是空树,则TL.TR都是AVL树,且|HL-HR| <= 1 (节点的左子树高 ...

  7. 二叉查找树(BST)、平衡二叉树(AVL树)

    二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点,都满足其左子树上所有结点的数据域均小于或等于根结点的数据域,右 ...

  8. 图解:平衡二叉树,AVL树

    学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...

  9. 数据结构与算法分析-AVL树

    1.AVL树是带有平衡条件的二叉查找树. 2.AVL树的每个节点高度最多相差1. 3.AVL树实现的难点在于插入或删除操作.由于插入和删除都有可能破坏AVL树高度最多相差1的特性,所以当特性被破坏时需 ...

  10. 数据结构——二叉查找树、AVL树

    二叉查找树:由于二叉查找树建树的过程即为插入的过程,所以其中序遍历一定为升序排列! 插入:直接插入,插入后一定为根节点 查找:直接查找 删除:叶子节点直接删除,有一个孩子的节点删除后将孩子节点接入到父 ...

随机推荐

  1. Android开发笔记之《远程控制(MQTT|mosquitto) && (ProtocalBuffer | GRPC)》

    Android推送方案分析(MQTT/XMPP/GCM): http://www.open-open.com/lib/view/open1410848945601.htmlMQTT官网: http:/ ...

  2. Java程序员

    从生存.制胜.发展三个方面入手,为大家展示出程序员求职与工作的一幅3D全景图像.本书中既有在公司中的生存技巧,又有高手达人的进阶策略,既有求职攻略的按图索骥,又有入职后生产环境的破解揭秘. 书中浓缩了 ...

  3. Java学习笔记11

    package welcome; import java.util.Scanner; /* * 代数问题:求解2x2线性方程 */ public class ComputeLinearEquation ...

  4. RSync实现文件备份同步

    [rsync实现网站的备份,文件的同步,不同系统的文件的同步,如果是windows的话,需要windows版本cwrsync] 一.什么是rsync rsync,remote synchronize顾 ...

  5. 二叉树的层序遍历 BFS

    二叉树的层序遍历,或者说是宽度优先便利,是经常考察的内容. 问题一:层序遍历二叉树并输出,直接输出结果即可,输出格式为一行. #include <iostream> #include &l ...

  6. Activiti学习(一) 环境搭建

    原料:Activiti5.4  MyEclipse 10 1.先将activiti文件夹放置myeclipse的安装目录dropins文件夹下2.将activiti文件夹里activiti.link中 ...

  7. LYDSY模拟赛day1 Tourist Attractions

    /* 假设路径是 a − b − c − d,考虑枚举中间这条边 b − c,计 算有多少可行的 a 和 d. 设 degx 表示点 x 的度数,那么边 b − c 对答案的贡献为 (degb − 1 ...

  8. 一些PHP性能优化汇总

    PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...

  9. PHP大数(浮点数)取余

    一般我们进行取余运算第一个想到的就是用百分号%,但当除数是个很大的数值,超出了int范围时,这样取余就不准确了. php大数(浮点数)取余函数 /** * php大数取余 * * @param int ...

  10. make 和 makefile 的关系

    程序的 编译 和 链接 要先总结 make 和 makefile,就需要先了解下面这个过程: 预编译:也叫预处理,进行一些文本替换工作,比如将 #define 定义的内容,在代码中进行替换: 编译:将 ...