04-树4. Root of AVL Tree-平衡查找树AVL树的实现
对于一棵普通的二叉查找树而言,在进行多次的插入或删除后,容易让树失去平衡,导致树的深度不是O(logN),而接近O(N),这样将大大减少对树的查找效率。一种解决办法就是要有一个称为平衡的附加的结构条件:任何节点的深度均不得过深。有一种最古老的平衡查找树,即AVL树。
AVL树是带有平衡条件的二叉查找树。平衡条件是每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。相比于普通的二叉树,AVL树的节点需要增加一个变量保存节点高度。AVL树的节点声明如下:
typedef struct TreeNode *AvlTree;
typedef struct TreeNode *Position;
struct TreeNode
{
int Data;
AvlTree Left;
AvlTree Right;
int Height; //保存节点高度
};
只有一个节点的树显然是AVL树,之后我们向其插入节点。然而在插入过程中可能破坏AVL树的特性,因此我们需要对树进行简单的修正,即AVL树的旋转。
设a节点在插入下一个节点后会失去平衡,这种插入可能出现四种情况:
1. 对a的左儿子的左子树进行一次插入。(左-左)
2. 对a的左儿子的右子树进行一次插入。(左-右)
3. 对a的右儿子的左子树进行一次插入。(右-左)
4. 对a的右儿子的右子树进行一次插入。(右-右)
情形1和4,情形2和3分别是关于A节点的镜像对称,故在理论上是两种情况,而编程具体实现还是需要考虑四种。
单旋转--情形1和4:

双旋转--情形2和3:
情形2和3就是向上图中的子树Y插入一个节点,由上图可知,无论是左单旋还是右单旋都无法改变子树Y的高度。解决办法是再将子树Y分解成根节点和相应的左子树和右子树,然后对相应的节点做相应的旋转,如下图:

下面一个题即是考察AVL树的旋转:题目来源:http://www.patest.cn/contests/mooc-ds/04-%E6%A0%914
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.


Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<=20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print ythe root of the resulting AVL tree in one line.
Sample Input 1:
5
88 70 61 96 120
Sample Output 1:
70
Sample Input 2:
7
88 70 61 96 120 90 65
Sample Output 2:
88
题目大意是先输入一个整数N,然后依次输入N个节点的值,以此建立AVL树,最后输出AVL树的根节点的值。
代码如下:
#include <cstdio>
#include <cstdlib> typedef struct TreeNode *AvlTree;
typedef struct TreeNode *Position;
struct TreeNode
{
int Data;
AvlTree Left;
AvlTree Right;
int Height;
}; AvlTree Insert(int x, AvlTree T); //插入新节点,必要时调整
Position SingleRotateWithLeft(Position a); //左单旋
Position SingleRotateWithRight(Position b); //右单旋
Position DoubleRotateWithLeft(Position a); //左右旋
Position DoubleRotateWithRight(Position b); //右左旋 int Max(int x1, int x2); //返回两个int中较大的
int Height(Position P); //返回一个节点的高度 int main()
{
int n, x;
AvlTree T = NULL; scanf("%d", &n);
for (int i = ; i < n; i++)
{
scanf("%d", &x);
T = Insert(x, T);
}
printf("%d\n", T->Data); //打印根节点的值 return ;
} AvlTree Insert(int x, AvlTree T)
{
if (T == NULL)
{
T = (AvlTree)malloc(sizeof(struct TreeNode));
T->Data = x;
T->Left = T->Right = NULL;
T->Height = ;
}
else if (x < T->Data) //向左子树插入
{
T->Left = Insert(x, T->Left);
if (Height(T->Left) - Height(T->Right) == ) //需调整
{
if (x < T->Left->Data)
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
}
else if (x > T->Data) //向右子树插入
{
T->Right = Insert(x, T->Right);
if (Height(T->Right) - Height(T->Left) == ) //需调整
{
if (x > T->Right->Data)
T = SingleRotateWithRight(T);
else
T = DoubleRotateWithRight(T);
}
}
/*else值为x的节点已经存在树中,无需插入*/ /*更新节点高度*/
T->Height = Max(Height(T->Left), Height(T->Right)) + ;
return T;
} Position SingleRotateWithLeft(Position a)
{
Position b = a->Left;
a->Left = b->Right;
b->Right = a;
//更新a, b节点高度
a->Height = Max(Height(a->Left), Height(a->Right)) + ;
b->Height = Max(Height(b->Left), Height(b->Right)) + ; return b; /*新的根节点*/
} Position SingleRotateWithRight(Position b)
{
Position a = b->Right;
b->Right = a->Left;
a->Left = b;
//更新a,b节点高度
a->Height = Max(Height(a->Left), Height(a->Right)) + ;
b->Height = Max(Height(b->Left), Height(b->Right)) + ;
return a; /*新的根节点*/
} Position DoubleRotateWithLeft(Position a)
{
a->Left = SingleRotateWithRight(a->Left);
return SingleRotateWithLeft(a);
} Position DoubleRotateWithRight(Position b)
{
b->Right = SingleRotateWithLeft(b->Right);
return SingleRotateWithRight(b);
} int Max(int x1, int x2)
{
return (x1 > x2) ? x1 : x2;
} int Height(Position P)
{
if (P == NULL) //空节点高度为-1
return -;
return P->Height;
}
需要注意的细节是我们需要快速得到一个节点(包括空节点)的高度,所以我们需要些一个函数来处理空节点(空指针)的情况,而不是简单的Position->Height。
04-树4. Root of AVL Tree-平衡查找树AVL树的实现的更多相关文章
- 【PAT甲级】1066 Root of AVL Tree (25 分)(AVL树建树模板)
题意: 输入一个正整数N(<=20),接着输入N个结点的值,依次插入一颗AVL树,输出最终根结点的值. AAAAAccepted code: #define HAVE_STRUCT_TIMESP ...
- 详解平衡二叉树(AVL tree)平衡操作(图+代码)
* 左左就右旋,右右就左旋 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int max ...
- PAT甲级1066. Root of AVL Tree
PAT甲级1066. Root of AVL Tree 题意: 构造AVL树,返回root点val. 思路: 了解AVL树的基本性质. AVL树 ac代码: C++ // pat1066.cpp : ...
- PTA 04-树5 Root of AVL Tree (25分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/668 5-6 Root of AVL Tree (25分) An AVL tree ...
- PAT 甲级 1066 Root of AVL Tree (25 分)(快速掌握平衡二叉树的旋转,内含代码和注解)***
1066 Root of AVL Tree (25 分) An AVL tree is a self-balancing binary search tree. In an AVL tree, t ...
- PAT甲级1123. Is It a Complete AVL Tree
PAT甲级1123. Is It a Complete AVL Tree 题意: 在AVL树中,任何节点的两个子树的高度最多有一个;如果在任何时候它们不同于一个,则重新平衡来恢复此属性.图1-4说明了 ...
- HDU 2193 AVL Tree
AVL Tree An AVL tree is a kind of balanced binary search tree. Named after their inventors, Adelson- ...
- 数据结构和算法(Golang实现)(28)查找算法-AVL树
AVL树 二叉查找树的树高度影响了查找的效率,需要尽量减小树的高度,AVL树正是这样的树. 一.AVL树介绍 AVL树是一棵严格自平衡的二叉查找树,1962年,发明者Adelson-Velsky和La ...
- 数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树
某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较为简单,容易教学.在这里,我们区分开左倾红黑树和普通红黑树. 红黑树 ...
- PAT Advanced 1066 Root of AVL Tree (25) [平衡⼆叉树(AVL树)]
题目 An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child ...
随机推荐
- mysql 无法启动,错误1067,进程意外终止
在做项目启动mysql数据库时,经常出现 这个错误,今天总结一下 //查看了网上很多的方法,都不适用,但或许对你适用.ps:网上只提供了怎么解决这个问题,但是没有将怎么去发现问题,对症下药才是王道.而 ...
- Git + Gerrit 操作备忘
Git review 作用 可以用来提交代码审核到Gerrit 安装 使用pip 安装 git-review 插件,执行 sudo -H pip install git-review 使用示例 可以参 ...
- 如何使用phpredis连接Redis的方法
本文跟大家介绍使用同一VPC内弹性云服务器ECS上的phpredis连接Redis的方法. 更多的客户端的使用方法,请参考https://redis.io/clients 前提条件 已成功申请Redi ...
- 华为中兴借eBay出海 靠零售渠道撬动市场
在跨境电商领域,大多数中国商家依靠“中国制造”的优势和价格战策略打拼出一条血路,在海外市场占领了自己的一席 之地.不过,山寨货纷纷出海的同时,中国本土的品牌商们也开始了探索海外市场之旅.目前,华为.中 ...
- 阿里巴巴将在美国推出电子商务网站11 Main
新浪科技讯 北京时间2月11日晚间消息,阿里巴巴集团周二向路透社证实,阿里巴巴将通过旗下子公司Vendio和Auctiva在美国推出一个电子商务网站. 该网站的名称为“11 Main”(11main. ...
- 遇到Intel MKL FATAL ERROR: Cannot load libmkl_avx2.so or libmkl_def.so问题的解决方法
运行一个基于tensorflow的模型时,遇到Intel MKL FATAL ERROR: Cannot load libmkl_avx2.so or libmkl_def.so问题. 解决方法:打开 ...
- IP ,路由
ifconfig 命令 ip信息 enp0s3: flags=4163<UP(已经启用),BROADCAST(支持广播),RUNNING,MULTICAST(支持多播)> ...
- php opensll加解密类
<?php $pri = "-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCzJc4RrAqaH2Es02XQ91Cqp/JK0yX893 ...
- laravel获取当前认证用户登录
可以通过Auth门面访问认证用户: 要在方法上面声明 use Auth: 获取当前认证用户使用 $user = Auth::user(); 获取用户认证ID $id = Auth::id;
- js get selected text
js get selected text https://stackoverflow.com/questions/3170648/how-to-get-javascript-select-boxs-s ...