1123. Is It a Complete AVL Tree (30)
1123. Is It a Complete AVL Tree (30)
時間限制400 ms內存限制65536 kB
代碼長度限制16000 B
判題程序Standard作者CHEN, Yue
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 output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<= 20). 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, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print "YES" if the tree is complete, or "NO" if not.
Sample Input 1:5 88 70 61 63 65 Sample Output 1:70 63 88 61 65 YES Sample Input 2:8 88 70 61 96 120 90 65 68 Sample Output 2:88 65 96 61 70 90 120 68 NO題意:輸入n個數據,要求創建avl平衡樹,再層序輸出并判斷是否是完全二叉樹
分析:我覺得層序輸出問題不大,主要在于avl的創建和判斷完全二叉樹
? avl的創建分為兩步 1.插入 2.平衡
? ? ? ? ? 插入比較好做,根據值的大小左右走,走到空的時候開始創建節點
? ? ? ? ? 插入節點可能會導致失衡,而平衡的方式根據插入節點與被破壞的節點的位置關系分為四種情況
? ? ? ? ?? 1.插入點是被破壞點左孩子的左孩子,如題目中Figure1,這時候需要左旋,即把88節點順時針旋轉成70節點的右孩子。(LL)
? ? ? ? ? ? ? ? 2.插入點是被破壞點右孩子的右孩子,如題目中Figure2,這時候需要右旋,即把88節點逆時針旋轉成96節點的左孩子(RR)
? ? ? ? ? ? ? ? 3.插入點是被破壞點右孩子的左孩子,如題目中Figure3,你會發現這個似乎有點不一樣,插入節點和被破壞的節點中間隔了兩個,這時候怎么旋轉呢?(RL)? ? RL是LL與RR之和,先對被破壞點的右孩子(96)進行LL,在對被破壞點(70)進行RR.
Figure的中間圖應該是這樣的
可以看出旋轉的時候,88的子節點發生了變化,具體下面講
? ? ? ? ? ? ? ? ? 4.插入點是被破壞點左孩子的右孩子,如題目中Figure4(LR),先對61-65做RR旋轉,在對70-70的左孩子(旋轉后為65) 做左旋
?再對LL做一個解釋,以Figure1 的88-70-61為例,此時的頭為88,我們希望旋轉后的頭的70,并且70的左為61,右為88。 我們假設此時的70節點有值為33的右孩子,那么88占了70的右子樹以后,33該往哪放呢????顯而易見,88的左子樹。 因為原先88的左孩子是70,旋轉以后左孩子就會空出來,那么就把88所占去的33放在空出來的這里。
示例代碼:
struct node* LL(struct node *root) {struct node *p = root->lchild;//p=70,root=88root->lchild = p->rchild;//88的左孩子=33p->rchild = root;//70的右孩子=88root->high = max(get_high(root->lchild), get_high(root->rchild)) + 1;p->high = max(get_high(p->lchild), root->high) + 1;//重新計算高度return p; }struct node *RL(struct node *root) {root->rchild = LL(root->rchild);return RR(root); }? ? ? ? ?RL,LR就是 RR ,LL 的組合。? ? ? ? 接下來是完全二叉樹的判斷,
? ? ? ? 完全二叉樹怎么講呢,比起滿二叉樹的完整金字塔,完全二叉樹允許金字塔底部挖空,并且空之前必須全部填滿,空之后必須全部為空。“偷”了一張百度的圖片,圖1是滿二叉樹,圖2、3是完全二叉樹,圖4 、5就不是完全二叉樹。? ?所以,假設一顆完全二叉樹有n個頂點,如果第x個頂點有左子樹,并且x*2>n,那么我們可以判斷出它不是完全二叉樹。同理,如果第x個頂點有右子樹,并且x*2+1>n,那么我們可以判斷它不是完全二叉樹。
代碼:
#include<iostream> #include<queue> #include<algorithm> using namespace std; struct node {int data;int high;struct node *lchild, *rchild; }; int judge = 1, cnt = 0, n; void level_out(struct node root) {queue<struct node> q;q.push(root);while (q.size()) {if (q.front().lchild) q.push(*q.front().lchild);if (q.front().rchild) q.push(*q.front().rchild);if (q.front().lchild)if ((cnt + 1) * 2 > n) judge = 0;if (q.front().rchild)//判斷是否為 完全二叉樹if ((cnt + 1) * 2 + 1 > n) judge = 0;cnt == 0 ? cout << q.front().data : cout << " " << q.front().data;q.pop();cnt++;}cout << endl;judge == 1 ? cout << "YES" : cout << "NO"; } int get_high(struct node *root) {if (root) return max(get_high(root->lchild), get_high(root->rchild)) + 1;else return 0; } struct node* LL(struct node *root) {struct node *p = root->lchild;root->lchild = p->rchild;p->rchild = root;root->high = max(get_high(root->lchild), get_high(root->rchild)) + 1;p->high = max(get_high(p->lchild), root->high) + 1;return p; } struct node *RR(struct node *root) {struct node *p = root->rchild;root->rchild = p->lchild;p->lchild = root;root->high = max(get_high(root->lchild), get_high(root->rchild)) + 1;p->high = max(root->high, get_high(p->rchild)) + 1;return p; } struct node *RL(struct node *root) {root->rchild = LL(root->rchild);return RR(root); } struct node *LR(struct node *root) {root->lchild = RR(root->lchild);return LL(root); } struct node* insert(struct node* root, int data) {if (!root){root = new struct node();//使用默認的構造函數root->data = data;}else if (data < root->data){root->lchild = insert(root->lchild, data);if (get_high(root->lchild) - get_high(root->rchild) == 2) //失衡 if (data < root->lchild->data) root = LL(root);else root = LR(root);}else if (data >root->data){root->rchild = insert(root->rchild, data);if (get_high(root->rchild) - get_high(root->lchild) == 2)if (data > root->rchild->data) root = RR(root);else root = RL(root);}root->high = max(get_high(root->lchild), get_high(root->lchild)) + 1;return root; } int main() {int tmp;cin >> n;struct node *root = NULL;for (int i = 0; i<n; i++) {cin >> tmp;root = insert(root, tmp);}level_out(*root); }轉載于:https://www.cnblogs.com/childwang/p/8280267.html
總結
以上是生活随笔為你收集整理的1123. Is It a Complete AVL Tree (30)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20170513 Python练习册00
- 下一篇: [游戏开发-学习笔记]菜鸟慢慢飞(14)