您的位置:首页 > 其它

PAT 1066. Root of AVL Tree (25) 回レ!雪月AVL

2017-09-02 14:48 411 查看

1066. Root of AVL Tree (25)

时间限制100 ms内存限制65536 kB代码长度限制16000 B判题程序Standard作者CHEN, YueAn 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答案正确251066C++(g++ 4.7.2)1308datrilla

测试点

测试点结果用时(ms)内存(kB)得分/满分
0答案正确13084/4
1答案正确13084/4
2答案正确13084/4
3答案正确13084/4
4答案正确13084/4
5答案正确13084/4
6答案正确13081/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).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).value<(*AVLtree)[Root].value &&(*AVLtree).value<(*AVLtree)[child].value  )||(  (*AVLtree).value>=(*AVLtree)[Root].value && (*AVLtree).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.value;AVLtree.left_right = 0;AVLtree.l0_r1[0] = AVLtree.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;}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: