PAT 1066. Root of AVL Tree (25) 回レ!雪月AVL
1066. Root of AVL Tree (25)
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
数据结构听到AVL就头大,根本不知道这么做的意义;这次看着博文和别人AC的代码写了这个。以前很喜欢用链表的;但是现在有点不喜欢,比如地址空间会很大的。然后就用int带代替指针;整个数组化。AVL左旋右旋,旋来旋去就那几行代码。重点的是那个有回溯的那段。还有各种细节;
代码中有详细的注释。顺便(PS:我通过tag动态化,直接就弄成看似一种旋转的了)
有四种种情况可能导致二叉查找树不平衡,分别为:(1)LL:插入一个新节点到根节点的左子树(Left)的左子树(Left),导致根节点的平衡因子由1变为2(2)RR:插入一个新节点到根节点的右子树(Right)的右子树(Right),导致根节点的平衡因子由-1变为-2(3)LR:插入一个新节点到根节点的左子树(Left)的右子树(Right),导致根节点的平衡因子由1变为2(4)RL:插入一个新节点到根节点的右子树(Right)的左子树(Left),导致根节点的平衡因子由-1变为-2针对四种种情况可能导致的不平衡,可以通过旋转使之变平衡。有两种基本的旋转:(1)左旋转:将根节点旋转到(根节点的)右孩子的左孩子位置(2)右旋转:将根节点旋转到(根节点的)左孩子的右孩子位置
联动AVL http://dongxicheng.org/structure/avl/
评测结果
时间 | 结果 | 得分 | 题目 | 语言 | 用时(ms) | 内存(kB) | 用户 |
---|---|---|---|---|---|---|---|
8月13日 21:56 | 答案正确 | 25 | 1066 | C++ (g++ 4.7.2) | 1 | 308 | datrilla |
测试点
测试点 | 结果 | 用时(ms) | 内存(kB) | 得分/满分 |
---|---|---|---|---|
0 | 答案正确 | 1 | 308 | 4/4 |
1 | 答案正确 | 1 | 308 | 4/4 |
2 | 答案正确 | 1 | 308 | 4/4 |
3 | 答案正确 | 1 | 308 | 4/4 |
4 | 答案正确 | 1 | 308 | 4/4 |
5 | 答案正确 | 1 | 308 | 4/4 |
6 | 答案正确 | 1 | 308 | 1/1 |
#include <iostream> #include<vector> using namespace std; struct List {int value;int left_right;int l0_r1[2]; }; int Height(vector<List>*AVLtree, int node,int tag)/*如果node的child【左tag=0】【右tag=1】不存在那么返回高度-1 */ { /*如果node存在,那么必然返回对应结点child的|left-right|>=0*/int child = (*AVLtree)[node].l0_r1[tag]; /*PS:本来一直样例不行,原来是存在时错误返回node前一轮的了*/if (child == -1)return -1;else return (*AVLtree)[child].left_right; } int returnmax(int a, int b)/*对于root返回他的左右结点高度最高的*/ {if (a > b)return a; else return b; } int rotate(vector<List>*AVLtree,int tag,int Root,int child)/*tag=0,左旋:带入的child为Root的右。[1-tag]→;[tag]←*/ { /*tag=1,右旋:带入的child为Root的左。[1-tag]←;[tag]→*/(*AVLtree)[Root].l0_r1[1-tag] = (*AVLtree)[child].l0_r1[tag];(*AVLtree)[child].l0_r1[tag] = Root;(*AVLtree)[Root].left_right = returnmax(Height(AVLtree, Root, tag), Height(AVLtree, Root, 1-tag))+1;(*AVLtree)[child].left_right = returnmax(Height(AVLtree, child, tag), Height(AVLtree, child, 1 - tag))+1; return child; /*旋转以后Root和Child身份互换了,并且稳定,需要更新此时他们的高度,一遍回溯的时候由其他Root使用*/ } int insertnew(vector<List>*AVLtree, int Root,int N) { int tag;int child;if (Root == N) return Root; /*只有一个结点,显然这个结点就是Root【PS第一次的Root,在主函数有初始化为最开始的N-1】*/else{if ((*AVLtree)[N].value < (*AVLtree)[Root].value)/*本来已经存在结点,这里用来判断是往左走tag=0,或者往右走tag=1*/tag = 0;else tag = 1;if ((*AVLtree)[Root].l0_r1[tag] != -1)/*如果此次走的Root的该方向还有下个结点,DFS走下去;否则截止*/{child = (*AVLtree)[Root].l0_r1[tag] = insertnew(AVLtree, (*AVLtree)[Root].l0_r1[tag], N); /*这里出来以后的child为新数往当前Root走的方向稳定后的【左tag=0】【右tag=1】结点*/if (Height(AVLtree, Root, tag) - Height(AVLtree, Root, 1 - tag) == 2){ if (( (*AVLtree)[N].value<(*AVLtree)[Root].value &&(*AVLtree)[N].value<(*AVLtree)[child].value )||( (*AVLtree)[N].value>=(*AVLtree)[Root].value && (*AVLtree)[N].value>=(*AVLtree)[child].value)){Root=rotate(AVLtree,1-tag, Root, child); }/*R L 如果新放入的在这个child和root的同一边左左(右右),那么只要一次对应左(右)旋*/ else { child = rotate(AVLtree,tag, child, (*AVLtree)[child].l0_r1[1-tag]);Root = rotate(AVLtree,1-tag, Root, child);/**/}/*LR RL 否则在Root左,child右;左旋后右旋;在Root右,在child左,右旋后左旋*/} }else child=(*AVLtree)[Root].l0_r1[tag] = N; /*这里是截止的,即新进的位置*/ } (*AVLtree)[Root].left_right = returnmax(Height(AVLtree, Root, tag), Height(AVLtree, Root, 1 - tag)) + 1;return Root; } int main() {int N,Root;cin >> N; vector<List>AVLtree(N);Root = N - 1;while (N--){cin >> AVLtree[N].value;AVLtree[N].left_right = 0;AVLtree[N].l0_r1[0] = AVLtree[N].l0_r1[1] = -1;Root = insertnew(&AVLtree, Root, N); }cout<< AVLtree[Root].value << endl;system("pause");return 0; }
上面这种思路用[tag]的,有点反人类,很难理清。其实个人觉得分开写或许会更便于理解和书写。
再转一个大佬们的。
#include <cstdio>
#define max(a, b) (((a) > (b)) ? (a) : (b))
struct node {int val;struct node *left, *right;
};
node *rotateLeft(node *root) {node *t = root->right;root->right = t->left;t->left = root;return t;
}
node *rotateRight(node *root) {node *t = root->left;root->left = t->right;t->right = root;return t;
}
node *rotateLeftRight(node *root) {root->left = rotateLeft(root->left);return rotateRight(root);
}
node *rotateRightLeft(node *root) {root->right = rotateRight(root->right);return rotateLeft(root);
}
int getHeight(node *root) {if(root == NULL) return 0;return max(getHeight(root->left), getHeight(root->right)) + 1;
}
node *insert(node *root, int val) {if(root == NULL) {root = new node();root->val = val;root->left = root->right = NULL;} else if(val < root->val) {root->left = insert(root->left, val);if(getHeight(root->left) - getHeight(root->right) == 2)root = val < root->left->val ? rotateRight(root) : rotateLeftRight(root);} else {root->right = insert(root->right, val);if(getHeight(root->left) - getHeight(root->right) == -2)root = val > root->right->val ? rotateLeft(root) : rotateRightLeft(root);}return root;
}
int main() {int n, val;scanf("%d", &n);node *root = NULL;for(int i = 0; i < n; i++) {scanf("%d", &val);root = insert(root, val);}printf("%d", root->val);return 0;
}
PAT 1066. Root of AVL Tree (25) 回レ!雪月AVL相关推荐
- PAT甲级1066 Root of AVL Tree (25分):[C++题解]建立平衡树(AVL树)
文章目录 题目分析 题目链接 题目分析 图片来源:acwing 分析 平衡树(AVL树)是平衡二叉搜索树的简称,当然需要满足二叉搜索树的性质,左子树小于根,根小于等于右子树:然后还要满足平衡树的基本特 ...
- pat04-树4. Root of AVL Tree (25)
04-树4. Root of AVL Tree (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue An A ...
- 1066 Root of AVL Tree (25 分)【难 / 知识点: 平衡树 未完成】
https://pintia.cn/problem-sets/994805342720868352/problems/994805404939173888 平衡树之前学过,不过有忘完了,有时间补吧
- PAT1066 Root of AVL Tree (25)(AVL树)
题意: 给出一系列要插入平衡搜索二叉树的数,要求输出最后的根节点 思路: 没其他办法,完完全全是AVL树的插入节点模拟,这题就不会写,看别人代码写的. #include<iostream> ...
- PAT甲级1123 Is It a Complete AVL Tree (30分):[C++题解]建立平衡树、bfs,判完全二叉树
文章目录 题目分析 题目链接 题目分析 来源:pat网站 本题作为进阶题,它的基础知识点如下几题. PAT甲级1066 Root of AVL Tree (25分):[C++题解]建立平衡树(AVL树 ...
- 1066 Root of AVL Tree——PAT甲级 | 参考mooc实现完整代码
Root of AVL Tree 2013年浙江大学计算机学院免试研究生上机考试真题,是关于AVL树的基本训练. 原题链接:PTA | 程序设计类实验辅助教学平台 题目描述 AVL 树是一种自平衡的 ...
- PAT A1066 Root of AVL Tree ——春水碧于天,画船听雨眠
PAT A1066 Root of AVL Tree AVL这东西记一次忘一次,每次看就像披着初恋外衣的旧情人(or reverse) 以下应该是较为标准的模板方法,只是好久没有用过指针了,所以写了个 ...
- 【PAT A1066】Root of AVL Tree
#include <cstdio> #include <algorithm> using namespace std;struct node {int v, height; / ...
- PAT (Advanced Level) Practice 1043 Is It a Binary Search Tree (25 分) 凌宸1642
PAT (Advanced Level) Practice 1043 Is It a Binary Search Tree (25 分) 凌宸1642 题目描述: A Binary Search Tr ...
最新文章
- 理解Android进程创建流程
- 再转弯曲评论上的一篇关于SOC的文章
- php pdo参数化,php – 如何正确地使用PDO对象的参数化SELECT查询
- oa服务器怎么修改域名,oa域名服务器配置
- 程序员会写诗是怎样的体验
- 30万条数据,搜索文本字段的各种方式对比
- 【Day13】说一下 Vue 组件的通信方式都有哪些?(父子组件,兄弟组件,多级嵌套组件等等)
- 漫步线性代数二十三——行列式公式
- 洛谷 P2622 关灯问题II (状态压缩+BFS)
- indexed true mysql_一行代码,搞定浏览器数据库 IndexedDB
- 【BIEE】由于排序顺序不兼容,集合操作失败
- 用C语言编写贪吃蛇小游戏
- 串口服务器通讯协议,串口服务器的组成和应用实例
- 我的网关、子网掩码、DNS1、DNS2是什么
- VTK 三维 重建 切割 三维点云
- 祝福我的家人朋友永远平安健康
- 基于Swing的Java学生成绩管理系统
- mocha 测试 mysql_GitHub - nodejs-xx/lei: 整合Express mysql ioredis ejs 的一开发框架,使用mocha对api进行测试...
- 关于我国电子商务立法的思考
- 服务一直处于‘启动中‘,无法关闭(已解决)