平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树

(a)和(b)都是排序二叉树,但是查找(b)的93节点就需要查找6次,查找(a)的93节点就需要查找3次,所以(b)的效率不高。

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树。它或者是一颗空树,或者是具有下列性质的二叉树:它的左子树和右子树的深度只差的绝对值不超过1。若将二叉树上节点的平衡因子BF(Balance Factor)定义为该节点的左子树的深度减去它右子树的深度,则平衡二叉树上所有节点的平衡因子只可能是-1,0,1。只要二叉树上有一个节点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

上图(a)是平衡二叉树,(b)不是平衡二叉树,因为有的节点的平衡因子大于1了。

插入节点的大致思路:

  • 首先找到插入节点的位置,插入节点
  • 插入节点后,调整相关节点的平衡因子
  • 调整平衡因子后,如果发现树不平衡了,就要进行节点的调整(单左旋转,或单右旋转,或双旋转(先左后又,或者先右后左)。

avl_tree.h

  1. #ifndef __AVLTREE__
  2. #define __AVLTREE__
  3. #include<stdio.h>
  4. #include<malloc.h>
  5. #include<assert.h>
  6. #include "nodestack.h"
  7. #define Type int
  8. #define FALSE 0
  9. #define TRUE 1
  10. #define BOOL int
  11. typedef struct AVLNode{
  12. Type data;
  13. struct AVLNode* left;
  14. struct AVLNode* right;
  15. int bf;//平衡因子
  16. }AVLNode;
  17. typedef struct AVLTree{
  18. struct AVLNode* root;
  19. }AVLTree;
  20. void init_avl_tree(AVLTree* avl);
  21. //插入节点
  22. BOOL insert_avl(AVLTree* avl, Type t);
  23. #endif

avl_tree.c

  1. #include "avl_tree.h"
  2. void init_avl_tree(AVLTree* avl){
  3. avl->root = NULL;
  4. }
  5. AVLNode* malNode(Type x){
  6. AVLNode* t = (AVLNode*)malloc(sizeof(AVLNode));
  7. assert(NULL != t);
  8. t->data = x;
  9. t->left = NULL;
  10. t->right = NULL;
  11. t->bf = 0;
  12. return t;
  13. }
  14. //右旋转
  15. void rotateR(AVLNode** t){
  16. AVLNode* subR = *t;
  17. *t = (*t)->left;
  18. subR->left = (*t)->right;
  19. (*t)->right = subR;
  20. (*t)->bf = 0;
  21. subR->bf = 0;
  22. }
  23. //左旋转
  24. void rotateL(AVLNode** t){
  25. AVLNode* subL = *t;
  26. *t = (*t)->right;
  27. subL->right = (*t)->left;
  28. (*t)->left = subL;
  29. (*t)->bf = 0;
  30. subL->bf = 0;
  31. }
  32. //左右旋转
  33. void rotateLR(AVLNode** t){
  34. AVLNode* subR = *t;
  35. AVLNode* subL = subR->left;
  36. *t = subL->right;
  37. subL->right = (*t)->left;
  38. (*t)->left = subL;
  39. if((*t)->bf <= 0){///??
  40. subL->bf = 0;
  41. }
  42. else{
  43. subL->bf = -1;
  44. }
  45. subR->left = (*t)->right;
  46. (*t)->right = subR;
  47. if((*t)->bf == -1){
  48. subR->bf = 1;//???
  49. }
  50. else{
  51. subR->bf = 0;//???
  52. }
  53. (*t)->bf = 0;
  54. }
  55. //右左旋转
  56. void rotateRL(AVLNode** t){
  57. AVLNode* subL = *t;
  58. AVLNode* subR = subL->right;
  59. *t = subR->left;
  60. subR->left = (*t)->right;
  61. (*t)->right = subR;
  62. if((*t)->bf >= 0){
  63. subR->bf = 0;
  64. }
  65. else{
  66. subR->bf = 1;
  67. }
  68. subL->right = (*t)->left;
  69. (*t)->left = subL;
  70. if((*t)->bf == 1){
  71. subL->bf = -1;
  72. }
  73. else{
  74. subL->bf = 0;
  75. }
  76. (*t)->bf = 0;
  77. }
  78. //插入树的节点
  79. BOOL insert_avl_node(AVLNode** t, Type x){
  80. AVLNode* p = *t;
  81. AVLNode* parent = NULL;
  82. nodestack st;
  83. init(&st);
  84. while(p != NULL){
  85. if(x == p->data)
  86. return FALSE;
  87. parent = p;
  88. push(&st, parent);
  89. if(x < p->data)
  90. p = p->left;
  91. else
  92. p = p->right;
  93. }
  94. p = malNode(x);
  95. //插入节点为root节点
  96. if(parent == NULL){
  97. *t = p;
  98. return TRUE;
  99. }
  100. //插入节点不是root节点
  101. if(x < parent->data)
  102. parent->left = p;
  103. else
  104. parent->right = p;
  105. //调整BF
  106. while(length(&st) != 0){
  107. parent = getTop(&st);
  108. pop(&st);
  109. if(parent->left == p){
  110. parent->bf--;
  111. }
  112. else{
  113. parent->bf++;
  114. }
  115. if(parent->bf == 0){
  116. break;
  117. }
  118. if(parent->bf == 1 || parent->bf == -1){
  119. p = parent;
  120. }
  121. else{
  122. //旋转树,让树变成平衡树
  123. int flag = (parent->bf < 0) ? -1 : 1;
  124. //符号相同,说明是一条直线,不是折线,所以单旋转
  125. if(p->bf == flag){
  126. //因为是撇/,所以右旋转
  127. if(flag == -1){
  128. rotateR(&parent);
  129. }
  130. //因为是捺\,所以左旋转
  131. else{
  132. rotateL(&parent);
  133. }
  134. }
  135. //符号不同,说明是折线,所以双旋转
  136. else{
  137. //折线的角指向右>
  138. if(flag == 1){
  139. rotateRL(&parent);
  140. }
  141. //折线的角指向左<
  142. else{
  143. rotateLR(&parent);
  144. }
  145. }
  146. break;
  147. }
  148. }
  149. if(length(&st) == 0){
  150. *t = parent;
  151. }
  152. else{
  153. AVLNode* q = getTop(&st);
  154. if(q->data > parent->data){
  155. q->left = parent;
  156. }
  157. else{
  158. q->right = parent;
  159. }
  160. }
  161. clear(&st);
  162. return TRUE;
  163. }
  164. //插入节点
  165. BOOL insert_avl(AVLTree* avl, Type t){
  166. return insert_avl_node(&avl->root, t);
  167. }

avl_treemain.c

  1. #include "avl_tree.h"
  2. int main(){
  3. AVLTree avl;
  4. init_avl_tree(&avl);
  5. //Type ar[] = {13,24,37,90,53};
  6. //Type ar[] = {30,20,10};
  7. //Type ar[] = {30,20,40,10,25,5,22,28,21};
  8. //Type ar[] = {30,20,10};
  9. //Type ar[] = {50,40,60,10,45,70,5,30,20,12};
  10. Type ar[] = {30,20,50,10,40,70,60,80,55};
  11. int n = sizeof(ar) / sizeof(Type);
  12. for(int i = 0; i < n; ++i){
  13. insert_avl(&avl, ar[i]);
  14. }
  15. return 0;
  16. }

完整代码

编译方法:g++ -g nodestack.c avl_tree.c avl_treemain.c

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树的更多相关文章

  1. 数据结构与算法——平衡二叉树(AVL树)

    目录 二叉排序树存在的问题 基本介绍 单旋转(左旋转) 树高度计算 旋转 右旋转 双旋转 完整代码 二叉排序树存在的问题 一个数列 {1,2,3,4,5,6},创建一颗二叉排序树(BST) 创建完成的 ...

  2. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  3. [CareerCup] 4.1 Balanced Binary Tree 平衡二叉树

    4.1 Implement a function to check if a binary tree is balanced. For the purposes of this question, a ...

  4. 平衡二叉树(Balanced Binary Tree)

    平衡二叉树(Balanced Binary Tree)/AVL树:

  5. [Algorithm] Find Max Items and Max Height of a Completely Balanced Binary Tree

    A balanced binary tree is something that is used very commonly in analysis of computer science algor ...

  6. LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15

    110. 平衡二叉树 110. Balanced Binary Tree 题目描述 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点的左右两个子树 ...

  7. AVL平衡二叉树的各种问题(Balanced Binary Tree)

    AVL树或者是一棵空树,或者是具有以下性质的非空二叉搜索树: 1. 任一结点的左.右子树均为AVL树: 2.根结点左.右子树高度差的绝对值不超过1. 1.声明 #include<iostream ...

  8. [LeetCode] 110. Balanced Binary Tree ☆(二叉树是否平衡)

    Balanced Binary Tree [数据结构和算法]全面剖析树的各类遍历方法 描述 解析 递归分别判断每个节点的左右子树 该题是Easy的原因是该题可以很容易的想到时间复杂度为O(n^2)的方 ...

  9. 110. Balanced Binary Tree - LeetCode

    Question 110. Balanced Binary Tree Solution 题目大意:判断一个二叉树是不是平衡二叉树 思路:定义个boolean来记录每个子节点是否平衡 Java实现: p ...

随机推荐

  1. Java中的instanceof和isInstance基础讲解

    1. instanceof 是一个操作符 使用方法: ? 1 2 if(a instanceof B){ } 表示:a 是不是 B 这种类型 2. isInstance是Class类的一个方法 ? 1 ...

  2. Mysql加锁过程详解(1)-基本知识

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  3. Use Generic Replacements of 1.X Framework API Classes 用泛型替换Framework 1.X版本的API类

    第一章,第一节 用泛型替换Framework 1.X版本的API类. 说起来,我是没接触过Framework 1.X版本的程序,12年毕的业(算算时间也一年多了,依旧一事无成,汗),毕业之后到公司实习 ...

  4. 03_SQL server数据类型

    SQL server数据类型 String类型: 数据类型: 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符.定义类型为char(5),那么就表示该类型可以存储5个字符,即使存 ...

  5. ZooKeeper 初体验

    安装Zookeeper Mac OS Mac 用户可以使用 Homebrew 安装和管理 Zookeeper 服务: brew install zookeeper 配置文件地址在: /usr/loca ...

  6. spark集群的简单测试和基础命令的使用

    写此篇文章之前,已经搭建好spark集群并测试成功: spark集群搭建文章链接:http://www.cnblogs.com/mmzs/p/8193707.html 一.启动环境 由于每次都要启动, ...

  7. 1.Linux电源管理-休眠与唤醒

    1.休眠方式 在内核中,休眠方式有很多种,可以通过下面命令查看 # cat /sys/power/state //来得到内核支持哪几种休眠方式. 常用的休眠方式有freeze,standby, mem ...

  8. markdown基础入门

    一.标题 语法:# 文字 注意:1个#号代表标题1,两个代表标题2,依次类推 # 标题1 ## 标题2 ### 标题3 #### 标题4 ##### 标题5 ###### 标题6 二.加粗,斜体 语法 ...

  9. Java设计模式 - 单例模式详解(扩展)

    单例模式引发相关整理 如何破坏单例模式 示例: /** * 如果破坏单例模式 * * @author sunyang * @date 2018/11/13 20:14 */ public class ...

  10. [算法总结] 13 道题搞定 BAT 面试——字符串

    1. KMP 算法 谈到字符串问题,不得不提的就是 KMP 算法,它是用来解决字符串查找的问题,可以在一个字符串(S)中查找一个子串(W)出现的位置.KMP 算法把字符匹配的时间复杂度缩小到 O(m+ ...