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 NN (\le 20≤20) which is the total number of keys to be inserted. Then NN 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 the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

/*!
* \file 04-树5 Root of AVL Tree.cpp
*
* \author ranjiewen
* \date 2017/04/01 18:54
*
*
*/ #include <stdio.h>
#include <stdlib.h> typedef struct AVLNode *Position;
typedef Position AVLTree;
typedef int ElementType;
struct AVLNode{
ElementType Data;
AVLTree Left;
AVLTree Right;
int Height; //树高
}; int Max(int a, int b)
{
return a > b ? a : b;
} //可将程序中用到的GetTreeHeight()替换掉
int GetHeight(Position p)
{
if (!p)
return -;
return p->Height;
} int GetTreeHeight(AVLTree T)
{
int HL = , HR = ;
int Max_H = ;
if (T)
{
if (T->Left)
{
HL = GetTreeHeight(T->Left);
}
if (T->Right)
{
HR = GetTreeHeight(T->Right);
}
Max_H = (HL > HR) ? (HL + ) : (HR + );
}
return Max_H;
} AVLTree SingleLeftRotation(AVLTree A)
{
//A必须有一个左子结点B
//将A与B做左单旋,更新A,B的高度,返回新的根节点B
AVLTree B = A->Left;
A->Left = B->Right;
B->Right = A;
A->Height = Max(GetTreeHeight(A->Left), GetTreeHeight(A->Right)) + ;
B->Height = Max(GetTreeHeight(B->Left), A->Height) + ;
return B;
} AVLTree SingleRightRotation(AVLTree A)
{
//A必须有一个右子节点B
//将A,B做右单旋,更新A,B的高度,返回新的根节点B
AVLTree B = A->Right;
A->Right = B->Left;
B->Left = A;
A->Height = Max(GetTreeHeight(A->Left),GetTreeHeight(A->Right))+;
B->Height = Max(GetTreeHeight(B->Right), A->Height) + ; return B;
} AVLTree DoubleLeftRightRotation(AVLTree A)
{
//A必须有一个左子节点B,且B必须有一个右子节点C
//将A,B与C做两次单旋,返回新的根节点C //将B,C做右单旋,C被返回
A->Left = SingleRightRotation(A->Left);
//将A与C做左单旋,C被返回
return SingleLeftRotation(A);
} AVLTree DoubleRightLeftRotation(AVLTree A)
{
//A必须有一个右子节点B,且B必须有一个左子节点C //将B,C做左单旋,C被返回
A->Right = SingleLeftRotation(A->Right);
//将A,C做右单旋,C被返回
return SingleRightRotation(A);
} //将x插入到AVL树中,并且返回调整后的AVL树
AVLTree Insert(AVLTree T, ElementType x)
{
if (!T)
{
//若为空树,则新建包含一个结点的树
T = (AVLTree)malloc(sizeof(struct AVLNode));
T->Data = x;
T->Left = T->Right = NULL;
T->Height = ;
}
else if (x<T->Data)
{
//插入T的左子树
T->Left = Insert(T->Left,x);
//如果需要左旋
if (GetTreeHeight(T->Left)-GetTreeHeight(T->Right)==)
{
if (x < T->Left->Data) //需要左单旋
{
T = SingleLeftRotation(T);
}
else
T = DoubleLeftRightRotation(T); //左-右双旋
}
}
else if (x>T->Data)
{
T->Right = Insert(T->Right,x);
//如果需要右旋
if (GetTreeHeight(T->Left)-GetTreeHeight(T->Right)==-)
{
if (x>T->Right->Data) //右单旋
{
T = SingleRightRotation(T);
}
else
{
T = DoubleRightLeftRotation(T); //右-左双旋
}
}
}
// else x==T->Data 无需插入 //别忘了更新树高
T->Height = Max(GetTreeHeight(T->Left), GetTreeHeight(T->Right)) + ;
return T;
} static int FindMin(AVLTree T){
if (T == NULL){
return -;
}
while (T->Left != NULL){
T = T->Left;
}
return T->Data;
} //返回-1表示,树中没有该数据,删除失败,
int Delete(AVLTree *T, ElementType D){ //指针的指针
static Position tmp;
if (*T == NULL){
return -;
}
else{
//找到要删除的节点
if (D == (*T)->Data){
//删除的节点左右子支都不为空,一定存在前驱节点
if ((*T)->Left != NULL && (*T)->Right != NULL){ D = FindMin((*T)->Right);//找后继替换
(*T)->Data = D;
Delete(&(*T)->Right, D);//然后删除后继节点,一定成功 //在右子支中删除,删除后有可能左子支比右子支高度大2
if (GetHeight((*T)->Left) - GetHeight((*T)->Left) == ){
//判断哪一个左子支的的两个子支哪个比较高
if (GetHeight((*T)->Left->Left) >= GetHeight((*T)->Left->Right)){
*T=SingleRightRotation(*T);
}
else{
*T = DoubleLeftRightRotation(*T);
/*LeftRotate(&(*T)->left);
RightRotate(T);*/
}
}
}
else
if ((*T)->Left == NULL){//左子支为空
tmp = (*T);
(*T) = tmp->Right;
free(tmp);
return ;
}
else
if ((*T)->Right == NULL){//右子支为空
tmp = (*T);
(*T) = tmp->Right;
free(tmp);
return ;
}
}
else
if (D > (*T)->Data){//在右子支中寻找待删除的节点
if (Delete(&(*T)->Right, D) == -){
return -;//删除失败,不需要调整,直接返回
}
if (GetHeight((*T)->Left) - GetHeight((*T)->Right) == ){
if (GetHeight((*T)->Left->Left) >= GetHeight((*T)->Left->Right)){
*T=SingleRightRotation(*T);
}
else{
*T = DoubleLeftRightRotation(*T);
/*LeftRotate(&(*T)->left);
RightRotate(T);*/
}
}
}
else
if (D < (*T)->Data){//在左子支中寻找待删除的节点
if (Delete(&(*T)->Left, D) == -){
return -;
}
if (GetHeight((*T)->Right) - GetHeight((*T)->Right) == ){
if (GetHeight((*T)->Right->Right) >= GetHeight((*T)->Right->Left)){
*T=SingleLeftRotation(*T);
}
else{
*T = DoubleRightLeftRotation(*T);
/*RightRotate(&(*T)->right);
LeftRotate(T);*/
}
}
}
}
//更新当前节点的高度
(*T)->Height = Max(GetHeight((*T)->Left), GetHeight((*T)->Right)) + ;
//printf("%d\n", (*T)->Data);
return ;
} int main()
{
int N,data;
AVLTree root=nullptr;
scanf("%d", &N);
for (int i = ; i < N;i++)
{
scanf("%d", &data);
root = Insert(root, data);
}
printf("%d\n",root->Data); Delete(&root, );
printf("%d\n", root->Data); return ;
}
AVL树原理及实现 +B树
 

04-树5 Root of AVL Tree + AVL树操作集的更多相关文章

  1. PAT 1066 Root of AVL Tree[AVL树][难]

    1066 Root of AVL Tree (25)(25 分) An AVL tree is a self-balancing binary search tree. In an AVL tree, ...

  2. 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 sub ...

  3. PAT甲级题解-1066. Root of AVL Tree (25)-AVL树模板题

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6803291.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  4. 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 ...

  5. 04-树5 Root of AVL Tree

    平衡二叉树 LL RR LR RL 注意画图理解法 An AVL tree is a self-balancing binary search tree. In an AVL tree, the he ...

  6. 1066. Root of AVL Tree

    An AVL tree is a self-balancing binary search tree.  In an AVL tree, the heights of the two child su ...

  7. 树的平衡 AVL Tree

    本篇随笔主要从以下三个方面介绍树的平衡: 1):BST不平衡问题 2):BST 旋转 3):AVL Tree 一:BST不平衡问题的解析 之前有提过普通BST的一些一些缺点,例如BST的高度是介于lg ...

  8. A1066. Root of AVL Tree

    An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...

  9. PAT 甲级 1066 Root of AVL Tree

    https://pintia.cn/problem-sets/994805342720868352/problems/994805404939173888 An AVL tree is a self- ...

随机推荐

  1. 测试开发之前端——No7.HTML5中的鼠标事件

    鼠标事件 由鼠标或相似的用户动作触发的事件. 适用于所有 HTML 5 元素: 属性 值 描述 onclick script 当单击鼠标时运行脚本 ondblclick script 当双击鼠标时运行 ...

  2. 【ES】学习3-请求体查询

    1.空查询 GET /index_2014*/type1,type2/_search {} GET /_search { , } 2.查询表达式 DSL只需将查询语句传递给 query 参数 GET ...

  3. 激活函数--(Sigmoid,tanh,Relu,maxout)

    Question? 激活函数是什么? 激活函数有什么用? 激活函数怎么用? 激活函数有哪几种?各自特点及其使用场景? 1.激活函数 1.1激活函数是什么? 激活函数的主要作用是提供网络的非线性建模能力 ...

  4. 7za的压缩与解压

    2.1 解压缩7z文件 7za x phpMyAdmin-3.3.8.1-all-languages.7z -r -o./ 参数含义: x  代表解压缩文件,并且是按原始目录树解压(还有个参数 e 也 ...

  5. Mybatis中的like模糊查询四种方式

    1.  参数中直接加入%% param.setUsername("%CD%"); param.setPassword("%11%"); <select i ...

  6. BZOJ2287【POJ Challenge】消失之物

    题解: 1.以前见过类似的,可以cdq分治 当l=r时就是还有一个剩余 这样时间是nmlogn的 空间是mlogn 2.首先我们可以dp出表示出j的方案数 令g[i][j]表示不能选i,表示出j的方案 ...

  7. c++ primer 笔记 (三)

    标准库类型string 和 vector ,分别定义了大小可变的字符串和集合.                 bitset,提供了一个抽象方法来操作位的集合.提供更方便的处理位的方式(相对于整型值上 ...

  8. 【开源小软件 】Bing每日壁纸 让桌面壁纸保持更新

    发布一个开源小软件,Bing每日壁纸. 该小软件可以自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事. 欢迎大家下载使用,点star!有问题请留言或者提issue. 开源地 ...

  9. python全栈开发day22-常用模块二(hashlib、configparse、logging)

    一.昨日内容回顾 1.钻石继承 #新式类,本身或父类显示继承object #找名字的时候是广度优先顺序 #有mro方法,super方法, # super并不是单纯的找父类,和mro顺序是完全对应的 # ...

  10. 第八章| 2. MySQL数据库|数据操作| 权限管理

    1.数据操作 SQL(结构化查询语言),可以操作关系型数据库 通过sql可以创建.修改账号并控制账号权限:  通过sql可以创建.修改数据库.表:  通过sql可以增删改查数据: 可以通过SQL语句中 ...