平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树
平衡二叉树(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树的更多相关文章
- 数据结构与算法——平衡二叉树(AVL树)
目录 二叉排序树存在的问题 基本介绍 单旋转(左旋转) 树高度计算 旋转 右旋转 双旋转 完整代码 二叉排序树存在的问题 一个数列 {1,2,3,4,5,6},创建一颗二叉排序树(BST) 创建完成的 ...
- C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解
剑指offer 面试题39:判断平衡二叉树 提交网址: http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...
- [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 ...
- 平衡二叉树(Balanced Binary Tree)
平衡二叉树(Balanced Binary Tree)/AVL树:
- [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 ...
- LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
110. 平衡二叉树 110. Balanced Binary Tree 题目描述 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点的左右两个子树 ...
- AVL平衡二叉树的各种问题(Balanced Binary Tree)
AVL树或者是一棵空树,或者是具有以下性质的非空二叉搜索树: 1. 任一结点的左.右子树均为AVL树: 2.根结点左.右子树高度差的绝对值不超过1. 1.声明 #include<iostream ...
- [LeetCode] 110. Balanced Binary Tree ☆(二叉树是否平衡)
Balanced Binary Tree [数据结构和算法]全面剖析树的各类遍历方法 描述 解析 递归分别判断每个节点的左右子树 该题是Easy的原因是该题可以很容易的想到时间复杂度为O(n^2)的方 ...
- 110. Balanced Binary Tree - LeetCode
Question 110. Balanced Binary Tree Solution 题目大意:判断一个二叉树是不是平衡二叉树 思路:定义个boolean来记录每个子节点是否平衡 Java实现: p ...
随机推荐
- Java中的instanceof和isInstance基础讲解
1. instanceof 是一个操作符 使用方法: ? 1 2 if(a instanceof B){ } 表示:a 是不是 B 这种类型 2. isInstance是Class类的一个方法 ? 1 ...
- Mysql加锁过程详解(1)-基本知识
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Use Generic Replacements of 1.X Framework API Classes 用泛型替换Framework 1.X版本的API类
第一章,第一节 用泛型替换Framework 1.X版本的API类. 说起来,我是没接触过Framework 1.X版本的程序,12年毕的业(算算时间也一年多了,依旧一事无成,汗),毕业之后到公司实习 ...
- 03_SQL server数据类型
SQL server数据类型 String类型: 数据类型: 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符.定义类型为char(5),那么就表示该类型可以存储5个字符,即使存 ...
- ZooKeeper 初体验
安装Zookeeper Mac OS Mac 用户可以使用 Homebrew 安装和管理 Zookeeper 服务: brew install zookeeper 配置文件地址在: /usr/loca ...
- spark集群的简单测试和基础命令的使用
写此篇文章之前,已经搭建好spark集群并测试成功: spark集群搭建文章链接:http://www.cnblogs.com/mmzs/p/8193707.html 一.启动环境 由于每次都要启动, ...
- 1.Linux电源管理-休眠与唤醒
1.休眠方式 在内核中,休眠方式有很多种,可以通过下面命令查看 # cat /sys/power/state //来得到内核支持哪几种休眠方式. 常用的休眠方式有freeze,standby, mem ...
- markdown基础入门
一.标题 语法:# 文字 注意:1个#号代表标题1,两个代表标题2,依次类推 # 标题1 ## 标题2 ### 标题3 #### 标题4 ##### 标题5 ###### 标题6 二.加粗,斜体 语法 ...
- Java设计模式 - 单例模式详解(扩展)
单例模式引发相关整理 如何破坏单例模式 示例: /** * 如果破坏单例模式 * * @author sunyang * @date 2018/11/13 20:14 */ public class ...
- [算法总结] 13 道题搞定 BAT 面试——字符串
1. KMP 算法 谈到字符串问题,不得不提的就是 KMP 算法,它是用来解决字符串查找的问题,可以在一个字符串(S)中查找一个子串(W)出现的位置.KMP 算法把字符匹配的时间复杂度缩小到 O(m+ ...