平衡二叉树(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

#ifndef __AVLTREE__
#define __AVLTREE__ #include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include "nodestack.h" #define Type int
#define FALSE 0
#define TRUE 1
#define BOOL int typedef struct AVLNode{
Type data;
struct AVLNode* left;
struct AVLNode* right;
int bf;//平衡因子
}AVLNode; typedef struct AVLTree{
struct AVLNode* root;
}AVLTree; void init_avl_tree(AVLTree* avl);
//插入节点
BOOL insert_avl(AVLTree* avl, Type t); #endif

avl_tree.c

#include "avl_tree.h"

void init_avl_tree(AVLTree* avl){
avl->root = NULL;
}
AVLNode* malNode(Type x){
AVLNode* t = (AVLNode*)malloc(sizeof(AVLNode));
assert(NULL != t);
t->data = x;
t->left = NULL;
t->right = NULL;
t->bf = 0;
return t;
}
//右旋转
void rotateR(AVLNode** t){
AVLNode* subR = *t;
*t = (*t)->left;
subR->left = (*t)->right;
(*t)->right = subR;
(*t)->bf = 0;
subR->bf = 0; }
//左旋转
void rotateL(AVLNode** t){
AVLNode* subL = *t;
*t = (*t)->right;
subL->right = (*t)->left;
(*t)->left = subL;
(*t)->bf = 0;
subL->bf = 0; }
//左右旋转
void rotateLR(AVLNode** t){
AVLNode* subR = *t;
AVLNode* subL = subR->left;
*t = subL->right; subL->right = (*t)->left;
(*t)->left = subL;
if((*t)->bf <= 0){///??
subL->bf = 0;
}
else{
subL->bf = -1;
} subR->left = (*t)->right;
(*t)->right = subR;
if((*t)->bf == -1){
subR->bf = 1;//???
}
else{
subR->bf = 0;//???
} (*t)->bf = 0;
}
//右左旋转
void rotateRL(AVLNode** t){
AVLNode* subL = *t;
AVLNode* subR = subL->right;
*t = subR->left; subR->left = (*t)->right;
(*t)->right = subR;
if((*t)->bf >= 0){
subR->bf = 0;
}
else{
subR->bf = 1;
} subL->right = (*t)->left;
(*t)->left = subL;
if((*t)->bf == 1){
subL->bf = -1;
}
else{
subL->bf = 0;
} (*t)->bf = 0;
}
//插入树的节点
BOOL insert_avl_node(AVLNode** t, Type x){
AVLNode* p = *t;
AVLNode* parent = NULL; nodestack st;
init(&st); while(p != NULL){
if(x == p->data)
return FALSE;
parent = p;
push(&st, parent);
if(x < p->data)
p = p->left;
else
p = p->right;
}
p = malNode(x);
//插入节点为root节点
if(parent == NULL){
*t = p;
return TRUE;
}
//插入节点不是root节点
if(x < parent->data)
parent->left = p;
else
parent->right = p; //调整BF
while(length(&st) != 0){
parent = getTop(&st);
pop(&st);
if(parent->left == p){
parent->bf--;
}
else{
parent->bf++;
} if(parent->bf == 0){
break;
}
if(parent->bf == 1 || parent->bf == -1){
p = parent;
}
else{
//旋转树,让树变成平衡树
int flag = (parent->bf < 0) ? -1 : 1;
//符号相同,说明是一条直线,不是折线,所以单旋转
if(p->bf == flag){
//因为是撇/,所以右旋转
if(flag == -1){
rotateR(&parent);
}
//因为是捺\,所以左旋转
else{
rotateL(&parent);
}
}
//符号不同,说明是折线,所以双旋转
else{
//折线的角指向右>
if(flag == 1){
rotateRL(&parent);
}
//折线的角指向左<
else{
rotateLR(&parent);
}
}
break;
}
} if(length(&st) == 0){
*t = parent;
}
else{
AVLNode* q = getTop(&st);
if(q->data > parent->data){
q->left = parent;
}
else{
q->right = parent;
}
} clear(&st);
return TRUE;
}
//插入节点
BOOL insert_avl(AVLTree* avl, Type t){
return insert_avl_node(&avl->root, t);
}

avl_treemain.c

#include "avl_tree.h"

int main(){
AVLTree avl;
init_avl_tree(&avl); //Type ar[] = {13,24,37,90,53};
//Type ar[] = {30,20,10};
//Type ar[] = {30,20,40,10,25,5,22,28,21};
//Type ar[] = {30,20,10};
//Type ar[] = {50,40,60,10,45,70,5,30,20,12};
Type ar[] = {30,20,50,10,40,70,60,80,55}; int n = sizeof(ar) / sizeof(Type);
for(int i = 0; i < n; ++i){
insert_avl(&avl, ar[i]);
}
return 0;
}

完整代码

编译方法: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. mysql列反转Pivoting

    Pivoting是一项可以把行旋转为列的技术.在执行Pivoting的过程中可能会使用到聚合.Pivoting技术应用非常广泛.下面讨论的都是静态的Pivoting查询,即用户需要提前知道旋转的属性和 ...

  2. Spring DAO模块

    Spring的DAO模块提供了对JDBC.Hibernate.Mybatis等DAO层支持,本节介绍DAO模块对JDBC的支持.DAO模块依赖ommons-dbcp.jar.commons-pool. ...

  3. 解读经典《C#高级编程》第七版 Page32-38.核心C#.Chapter2

    前言 接下来讲讲预定义数据类型.关于数据类型,其实是非常值得透彻研究的. 01 预定义数据类型 值类型和引用类型 C#将把数据类型分为两种,值类型和引用类型,值类型存储在堆栈上,引用类型存储在托管堆上 ...

  4. Eureka 2.0 开源流产,真的对你影响很大吗?

    本文首发于 http://blog.didispace.com/Eureka-2-0-discontinued/ 最近连续发烧四天,偶尔刷两下朋友圈都能看到好几条来自不同号的关于<Eureka ...

  5. 如何快速将一个list<a>集合中的部分字段值组合成新的的list<b>部分*

    有的时候,我们只需要从老数据中拿一部分数据作为新的绑定数据,比如说绑定下拉框的时候需要构造我们需要的数据格式可以采用以下的方法 public class SelectDataViewModel { p ...

  6. Java实现Base64加密

    阅读本文约“2.5分钟” Java加解密系列,介绍Java加密解密的基础知识,并使用Base64算法实现加解密. 对于加密在企业中是非常常见的,就如邮件的传输,每个企业都会有自己设置安全方式,设置加密 ...

  7. webpack4 系列教程(十四):Clean Plugin and Watch Mode

    作者按:因为教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十四):Clean Plugin and Watch Mode>原文地址.更欢迎 ...

  8. 清除float影响

    条件: 父元素中有子元素float的话,可能就会影响父元素的高度,从而影响布局: 解决方案: 1.直接给父元素定高: 弊端:必须知道父元素的高: 2. 父元素使用overflow属性值为hidden解 ...

  9. 洛谷P3235 [HNOI2014]江南乐(Multi-SG)

    题目描述 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F,然后游戏系统 ...

  10. python3 os模块

    os模块就是对操作系统进行操作,这个模块提供了一种使用操作系统相关功能的可移植方式.1.系统信息 posix.uname_result(sysname='Linux', nodename='liang ...