平衡二叉树(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 ...
随机推荐
- 【杂谈】tocmat是何时写回响应数据报的
疑问的产生 这个疑问是我在写文件下载的时候产生的,我是用HttpServletResponse获取到Outputstream,然后利用OutputStream直接写数据的.当时我就想这个OutputS ...
- 教你一个vue小技巧,一般人我不说的
本文由云+社区发表 1. 需求 最近的项目中,需要实现在vue框架中动态渲染带提示框的单选/多选文本框,具体的效果如下图所示,在输入框聚焦时,前端组件通过接收的kv参数渲染出选项,用户点击选项,可以将 ...
- DynamicProxy系列目录
C# 1.基于Emit实现动态代理 2.Microsoft.CodeAnalysis动态生成代理类 3.castle dynamicproxy + AutoFac 4.DispatchProxy .R ...
- 【Javascript系列】变量作用域
问题描述 本篇文章主要讲解javascript变量及其作用域. 1 内容区 在js中,变量大致可分为全局变量(全局作用域)和局部变量(局部作用域): 用关键字var定义变量(全局变量,可以省略va ...
- Tomcat(三):tomcat处理连接的详细过程
Tomcat系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html tomcat可以处理静态资源的请求,也可以通过servlet处理动态资源的请求 ...
- 关于VUE首屏加载过长的优化,VUE项目开发优化
1. 按需引入UI组件 当下市面上流行的UI组件基本都支持按需加载,本文以Element UI为例: (1) 新建一个elementUI.js文件 (2) 访问地址找到按需引入方式的说 ...
- Linux命令-用户及权限管理
一.权限管理linux系统中对文件权限的描述机制: u g od r w x r w x r - x (r读,w写,x执行)文件 所有者 所属组 其他人可以表示为二进制: 111 111 101也可以 ...
- HTTP状态码分类
前言: 我们经常使用浏览器发出http请求,那么对于请求返回的状态,对于开发人员来讲,我们必须要明白其所代表的含义,如: 常见状态吗:400(请求无效),401(需要权限),500(服务器错误), 今 ...
- Java中枚举的使用
Java中枚举其实就是静态常量,今天发现枚举里面其实还能加方法,学习了下, 代码如下: package org.pine.test; import java.util.HashMap; import ...
- css 表单标签两端对齐
来自:http://demo.doyoe.com/css3/justify/justify-form.htm 侵删 <!DOCTYPE html> <html lang=" ...