浙大数据结构第四周之04-树5 Root of AVL Tree

题目详情:

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.

F1.jpg

F2.jpg

F3.jpg

F4.jpg

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 the 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

简单翻译:

就是给一个二叉平衡树的插入序列,依据这个序列构建二叉平衡树,并返回根节点

主要思路:

用插入法构建,即需要在程序里实现左右单旋与左右双旋

要特别注意的是,如果插入一个节点导致树不平衡了,我们要找到从下往上第一个不平衡的地方进行调整,调整完整个树就平衡了,而不是说要返回到最上面进行调整。

举个列子

假设我们在递归的过程中,输入AVLTree是NULL,也就是如下情况:

15这里是一定平衡的(左右都是空),返回给11,11这里肯定也是平衡的,返回给9,但9就不是平衡的了

然后就可以判断让9恢复平衡应该进行哪种操作,即RR还是RL,这里判断为RR。

调整完以后,再返回到9的父节点,这个时候9的父节点再进行判断,以此类推。
 

第一次写错误:

(1)对树的高度的把握,准确求出树高是旋转的关键,本题实现是直接存储在树节点中,通过直接访问节点与计算左右子树高度最大值再加1求得当前节点高度

在每次旋转后都需要求出两个“交换位置”节点的各自树高

插入操作最后再求当前节点树高

(2)

左旋:根节点与左孩子“交换”位置,左孩子右子树挂到根节点左子树

右旋:根节点与右孩子“交换”位置,右孩子左子树挂到根节点右子树

左-右双旋:先根节点左孩子与它的右孩子右旋,再根节点与现在的左孩子左旋

右-左双旋:先根节点右孩子与它的左节点左旋,再根节点与现在的右孩子右旋

代码实现:

/*
定义树的数据结构,其中每个节点保存以当前节点为root的子树高度
读入数据
插入节点以建树
左旋(1)左单旋(2)左-右双旋
右旋(1)右单旋(2)右-左双旋
*/
#include <stdio.h>
#include <stdlib.h>
/*定义树的数据结构*/
typedef struct TreeNode TreeNode;
typedef TreeNode* Position;
typedef Position AVLTree;
struct TreeNode {int Data;Position Leftchild;Position Rightchild;int Height;
};
/*获取树的高度*/
int Max(int a, int b) {return a > b ? a : b;
}
int GetTreeHeight(Position root) { if(root == NULL) {return 0;}else return root->Height;
}
/*每次旋转后都要重新获取以当前节点为根节点的子树高度*/
/*左单旋*/
Position SingleLeftRotation(Position root) {Position initialRoot = root;Position newRoot = root->Leftchild;root->Leftchild = root->Leftchild->Rightchild;newRoot->Rightchild = initialRoot;newRoot->Height = Max(GetTreeHeight(newRoot->Leftchild), GetTreeHeight(newRoot->Rightchild)) + 1;initialRoot->Height = Max(GetTreeHeight(initialRoot->Leftchild), GetTreeHeight(initialRoot->Rightchild)) + 1;return newRoot;
}
/*右单旋*/
Position SingleRightRotation(Position root) {Position initialRoot = root;Position newRoot = root->Rightchild;root->Rightchild = root->Rightchild->Leftchild;newRoot->Leftchild = initialRoot;initialRoot->Height = Max(GetTreeHeight(initialRoot->Leftchild), GetTreeHeight(initialRoot->Rightchild)) + 1;newRoot->Height = Max(GetTreeHeight(newRoot->Leftchild), GetTreeHeight(newRoot->Rightchild)) + 1;return newRoot;
}
/*左-右双旋*/
Position DoubleLeftRightRotation(Position root) {root->Leftchild = SingleRightRotation(root->Leftchild);return SingleLeftRotation(root);
}
/*右-左双旋*/
Position DoubleRightLeftRotation(Position root) {root->Rightchild = SingleLeftRotation(root->Rightchild);return SingleRightRotation(root);
}
/*插入节点*/
Position Insert(Position root, int data) {if(root == NULL) {root = (Position)malloc(sizeof(TreeNode));root->Data = data;root->Leftchild = root->Rightchild = NULL;root->Height = 1;return root;}if(root->Data > data) {root->Leftchild = Insert(root->Leftchild, data);if(GetTreeHeight(root->Leftchild) - GetTreeHeight(root->Rightchild) > 1) {if(root->Leftchild->Data > data) {  //左单旋root = SingleLeftRotation(root);}else {  //左-右双旋root = DoubleLeftRightRotation(root);}}}   else if(root->Data < data) {root->Rightchild = Insert(root->Rightchild, data);if(GetTreeHeight(root->Rightchild) - GetTreeHeight(root->Leftchild) > 1) {if(root->Rightchild->Data < data) {root = SingleRightRotation(root);}else {root = DoubleRightLeftRotation(root);}}}root->Height = Max(GetTreeHeight(root->Leftchild), GetTreeHeight(root->Rightchild)) + 1;return root;
}void DeleteTree(AVLTree root) {if(root == NULL) {return;}DeleteTree(root->Leftchild);DeleteTree(root->Rightchild);free(root);return;
}/*建树*/
int BuildTree() {int N;scanf("%d", &N);AVLTree root = NULL;for(int i = 0; i < N; i++) {int data;scanf("%d", &data);root = Insert(root, data);}int ret = root->Data;DeleteTree(root);return ret;
}int main() {int root = BuildTree();printf("%d", root);return 0;
}

参考文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/28400.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓进程间通信浅谈

Case: /Users/lucas/AndroidStudioProjects/aidldemo-master 一&#xff1a;操作系统 从操作系统原理去看&#xff0c;进程通信主要有三个方法&#xff1a;共享存储、消息传递、管道通信。 二&#xff1a;安卓中的IPC 进程间通信的几种方式&#xff1a;Intent&#xff08;Bu…

计网笔记--应用层

目录 1--网络程序的组织方式和关系 2--动态主机配置协议&#xff08;DHCP&#xff09; 3--域名系统DNS 4--文件传输协议FTP 5--电子邮件 7--万维网WWW 7-1--HTTP的报文格式 7-2--Cookie 7-3--万维网缓存和代理服务器 1--网络程序的组织方式和关系 网络应用程序在各种…

7.12~7.13学习总结

public static void main(String[] args){File dirnew File("D:\\小花花");boolean flag dir.mkdir();System.out.println(flag);File dirsnew File("D:\\小花花\\你爸爸");dirs.mkdirs();String[]adir.list();//列出下一级&#xff1b;字符串数组for(Stri…

【群智能算法改进】一种改进的猎人猎物优化算法 IHPO算法[1]【Matlab代码#49】

文章目录 【获取资源请见文章第5节&#xff1a;资源获取】1. 原始HPO算法2. 改进后的IHPO算法2.1 Cubic映射初始化2.2 透镜成像折射反向学习2.3 强制切换策略 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节&#xff1a;资源获取】 1. 原始HPO算法 此算法…

深入浅出关于网易邮箱开启smtp服务教程

各平台邮箱开启SMTP服务教程 一、QQ邮箱 &#xff08;服务器地址&#xff1a;smtp.qq.com&#xff09; 第一步&#xff1a;复制https://mail.qq.com/ 登录QQ邮箱后电击左上角设置&#xff0c;如图&#xff1a; 第二步&#xff1a;点击进入“帐户”页面 &#xff0c;如图&…

AJAX异步请求JSON数据格式

目录 前言 1.AJAX的实现方式 1.1原生的js实现方式 1.2JQuery实现方式 2.1语法 3.JSON数据和Java对象的相互转换 3.1将JSON转换为Java对象 3.2将Java对象转换为JSON 前言 AJAX&#xff1a;ASynchronous JavaScript And XML 异步的JavaScript 和 XML。 Ajax 是一种在…

016-从零搭建微服务-认证中心(七)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于B…

【软件测试面试】腾讯数据平台笔试题-接口-自动化-数据库

数据库题 答案&#xff1a; Python编程题 答案&#xff1a; 接口参数化题 答案&#xff1a; 接口自动化题 答案&#xff1a; 以下是我收集到的比较好的学习教程资源&#xff0c;虽然不是什么很值钱的东西&#xff0c;如果你刚好需要&#xff0c;可以评论区&#…

spring复习:(40)全注解的spring AOP

零、需要的依赖&#xff1a; <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><arti…

第一百零八天学习记录:C++基础:文件操作

C中对文件操作需要包含头文件<fstream> 操作文件的三大类&#xff1a; 1、ofstream:写擦破自评 2、ifstream:读操作 3、fstream:读写操作 文本文件 写文件 写文件步骤如下&#xff1a; 1、包含头文件 #include <fstream>2、创建流对象 ofstream ofs; 3、打开文…

TCP四次挥手过程

TCP 断开连接是通过四次挥手方式。 双方都可以主动断开连接&#xff0c;断开连接后主机中的「资源」将被释放&#xff0c; 刚开始双方都处于 establised 状态&#xff0c;假如是客户端先发起关闭请求&#xff0c;过程如下图&#xff1a; 第一次挥手&#xff1a;客户端打算关闭…