平衡二叉树(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. CentOS7 Hadoop 3.1.0 编译安装

    1.配置环境变量 JAVA_HOME=/jdk1..0_131 ANT_HOME=/apache-ant- MAVEN_HOME=/apache-maven- FINDBUGS_HOME=/findb ...

  2. excel 中批量生成mysql的脚本

    一.假设你的表格有A.B.C三列数据,希望导入到你的数据库中表格table,对应的字段分别是col1.col2.col3 二.在你的表格中增加一列,利用excel的公式自动生成sql语句,具体方法如下 ...

  3. (转)解决 TortoiseGit 诡异的 Bad file number 问题

    此问题,请不要使用 rebase, 下载最新的 TortoiseGit 即可: TortoiseGit-2.3中文版与Git安装包_手册: http://download.csdn.net/detai ...

  4. SHELL脚本--read命令

    bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 1.1 shell read简介 要与Linux交互,脚本获取 ...

  5. Ansible基础认识及安装使用详解(week5_day1_part1)--技术流ken

    Ansible简介 ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)的优点,实现了批量系统配置.批量 ...

  6. [React] react.js的一些库和用法

    React性能优化 记录一次利用 Timeline/Performance工具进行 React性能优化的真实案例 http://www.jianshu.com/p/9b0e9ef0a607 React ...

  7. zepto中的属性设置

    上次看zepto的init方法时,有一段属性设置的代码,先来看看其表现: if (isPlainObject(properties)) { nodes = $(dom) $.each(properti ...

  8. mysql循环插入数据、生成随机数及CONCAT函数

    实现目标:一年12个月,每个月插入一条数据,score为1-5的随机数 循环语句: WHILE -- DO -- END WHILE DELIMITER ; CREATE PROCEDURE test ...

  9. c#金额转换成中文大写金额

    2018-08-24 转别人 c#金额转换成中文大写金额 /// <summary> /// 金额转换成中文大写金额 /// </summary> /// <param ...

  10. 【微服务No.1】Consul服务发现在windows下简单使用

    基本介绍: 安装: 下载地址:https://www.consul.io/downloads.html 运行: consul agent -dev 显示这个界面说明已经开启成功. 页面显示: 然后访问 ...