一颗AVL树是其每个节点的左子树与右子树的高度最多差1的二叉查找树。

在插入过程中,利用旋转的办法保持这个性质。

共分四种情形:

1、  树T的左孩子的左子树上新插入节点导致破坏平衡性:

如下图左边所示,因为在子树X中新加入一个节点,导致k2处的平衡性被破坏

通过如右边所示的旋转,可以使得整棵树重新变得平衡。

2、 树T的右孩子的右子树上新插入节点导致破坏平衡性

这种情形跟上面那种情形是对称的。

3、树T的左孩子的右子树上新插入节点导致破坏平衡性

此时照搬情形1的旋转方法已经不能奏效了。

考虑将Y这部分散开来看:

可经由两次旋转解决问题:

可以发现,经过第一次旋转之后,问题已经变成了情形1,可再进行一次单旋转解决:

4、树T的右孩子的左子树上新插入结点,这时与情形3完全对称,可类似解决。

以下是实现部分。

仅实现插入操作,删除一般是惰性的。还有一点假设相同元素不出现在树结构中。

avl.h

#pragma once
using Elemtype = int;
struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree; //AvlTree MakeEmpty(AvlTree T);
//Position Find(Elemtype X, AvlTree T);
//Position FindMin(AvlTree T);
//Position FindMax(AvlTree T); AvlTree Insert(Elemtype X, AvlTree T);
//AvlTree Delete(Elemtype X, AvlTree T); //Elemtype Retrieve(Position P);

avl.cpp

#include "avl.h"
#include<cstdio>
#include<cstdlib>
#include<cassert>
#include<algorithm>
struct AvlNode{
Elemtype Element;
AvlTree Left;
AvlTree Right;
int Height;
}; static int Height(Position p){
if (p == nullptr)
return -1;
else
return p->Height;
}
static Position SingleRotateWithLeft(Position K2){
Position K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2; K2->Height = std::max(Height(K2->Left), Height(K2->Right)) + 1;
K1->Height = std::max(Height(K1->Left), Height(K1->Right)) + 1; return K1; /*New root*/
}
static Position SingleRotateWithRight(Position K2){
Position K1;
K1 = K2->Right;
K2->Right = K1->Left;
K1->Left = K2; K2->Height = std::max(Height(K2->Left), Height(K2->Right)) + 1;
K1->Height = std::max(Height(K1->Left), Height(K1->Right)) + 1; return K1; /*New root*/
}
static Position DoubleRotateWithLeft(Position K3){
K3->Left = SingleRotateWithRight(K3->Left);
return SingleRotateWithLeft(K3);
}
static Position DoubleRotateWithRight(Position K3){
K3->Right = SingleRotateWithLeft(K3->Right);
return SingleRotateWithRight(K3);
}
AvlTree Insert(Elemtype X, AvlTree T){
if (T == nullptr){
/*Create and return a one-node tree*/
T = (AvlTree)malloc(sizeof(struct AvlNode));
assert(T != nullptr, "Out of Space");
T->Element = X; T->Height = 0;
T->Left = T->Right = nullptr;
}
else if (X < T->Element){
T->Left = Insert(X, T->Left);
if (Height(T->Left) - Height(T->Right) == 2){
if (X < T->Left->Element){
T = SingleRotateWithLeft(T);
}
else{
T = DoubleRotateWithLeft(T);
}
}
}
else if (X > T->Element){
T->Right = Insert(X, T->Right);
if (Height(T->Right) - Height(T->Left) == 2){
if (X > T->Right->Element){
T = SingleRotateWithRight(T);
}
else{
T = DoubleRotateWithRight(T);
}
}
}
/*Else X is in the tree already; we'll do nothing */
T->Height = std::max(Height(T->Left), Height(T->Right)) + 1;
return T;
}

AVL(二叉平衡树) 的实现的更多相关文章

  1. 数据结构与算法问题 AVL二叉平衡树

    AVL树是带有平衡条件的二叉查找树. 这个平衡条件必须保持,并且它必须保证树的深度是O(logN). 一棵AVL树是其每一个节点的左子树和右子树的高度最多差1的二叉查找树. (空树的高度定义为-1). ...

  2. java项目---用java实现二叉平衡树(AVL树)并打印结果(详)(3星)

    package Demo; public class AVLtree { private Node root; //首先定义根节点 private static class Node{ //定义Nod ...

  3. Algorithms: 二叉平衡树(AVL)

    二叉平衡树(AVL):   这个数据结构我在三月份学数据结构结构的时候遇到过.但当时没调通.也就没写下来.前几天要用的时候给调好了!详细AVL是什么,我就不介绍了,维基百科都有.  后面两月又要忙了. ...

  4. AVL树(二叉平衡树)详解与实现

    AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树.这个平衡条件必 ...

  5. 二叉平衡树AVL的插入与删除(java实现)

    二叉平衡树 全图基础解释参考链接:http://btechsmartclass.com/data_structures/avl-trees.html 二叉平衡树:https://www.cnblogs ...

  6. 从零开始学算法---二叉平衡树(AVL树)

    先来了解一些基本概念: 1)什么是二叉平衡树? 之前我们了解过二叉查找树,我们说通常来讲, 对于一棵有n个节点的二叉查找树,查询一个节点的时间复杂度为log以2为底的N的对数. 通常来讲是这样的, 但 ...

  7. 判断一颗二叉树是否为二叉平衡树 python 代码

    输入一颗二叉树,判断这棵树是否为二叉平衡树.首先来看一下二叉平衡树的概念:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.因此判断一颗二叉平衡树的关键在于 ...

  8. 算法题 19 二叉平衡树检查 牛客网 CC150

    算法题 19 二叉平衡树检查 牛客网 CC150 实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1. 给定指向树根结点的指针TreeNode* ro ...

  9. 各种查找算法的选用分析(顺序查找、二分查找、二叉平衡树、B树、红黑树、B+树)

    目录 顺序查找 二分查找 二叉平衡树 B树 红黑树 B+树 参考文档 顺序查找 给你一组数,最自然的效率最低的查找算法是顺序查找--从头到尾挨个挨个遍历查找,它的时间复杂度为O(n). 二分查找 而另 ...

随机推荐

  1. centos 6.5 安装mysql 5.7.21 community

    Step1: 检测系统是否自带安装mysql # yum list installed | grep mysql Step2: 删除系统自带的mysql及其依赖命令: # yum -y remove ...

  2. 解决linux下/etc/rc.local开机器不执行的原因

    前不久因项目需要写了开机启动其他程序的shell脚本,因工作忙,调试完给了技术支持人员,也没去注意过. 到后来,有几台服务器突然被重启了,这时候领导问,怎么开机启动的脚本没起作用,还被批了一顿,哎,做 ...

  3. 【PM面试题】设计一个股价推送工具

    这一轮面试时间比较短,问题在短时间内不能很全面展开,因此抓住一些关键点变得尤其重要,这里我记录下当时是怎么想这个问题的. 问题解析 子问题1:推送什么?从问题中看出我们需要推送的是股价,用户可以自定义 ...

  4. PHP实现懒加载

    寻常php的加载是通过include(),require()等方法来加载外部文件,之后再通过实例调用方法或直接调用静态方法,而这样子写引入语句实在很麻烦,有的框架会将特定路径的文件全部引入,直接实例化 ...

  5. <!>字体效果

    <h1>...</h1>标题字(最大) <h6>...</h6>标题字(最小) <b>...</b>粗体字 <strong ...

  6. 【BZOJ】2015: [Usaco2010 Feb]Chocolate Giving(spfa)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2015 这种水题真没啥好说的.. #include <cstdio> #include & ...

  7. mac 安装memcache扩展问题

    执行php -i 报错: Warning: PHP Startup: memcached: Unable to initialize module Module compiled with build ...

  8. Docker mysql 连接 “The server requested authentication method unknown to the clien”错误

    查了下,出现这个错误的原因是从mysql 5.6开始,mysql密码加密算法更改了. 我装的mysql 8.* ,那么有两种解决方法: mysql 版本选择 <= 5.6 修改密码 docker ...

  9. github删除已经push到服务器上的commit的方法

    使用两条指令: git reset --hard <commit_id> git push origin HEAD --force 其中commit_id是你想回到的commit的id(即 ...

  10. 网络虚拟化之FlowVisor:网络虚拟层(上)

    概念解释:切片:虚拟网络的一个实例 一. 网络虚拟化(虚拟网络) 人类社会的发展在很大方面得益于自然界,飞机受益于鸟,雷达受益于蝙蝠等等,所以专门有个学科为仿生学就是研究和模仿生物的特殊本质,利用生物 ...