PAT A1123. 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

#include <iostream> 
#include <cmath> 
#include <fstream>
#include <queue>
#include<algorithm>
using namespace std;
typedef struct AVLTree *ProToTree;
int isfull = 1;
int max1 = -1;
struct AVLTree {//搜索树结构,因为要是AVL树,所以要加一个level项,不同于一般AVL树,我的level是高度而不是AVL值
	int ID;
	int level;
	int t;
	ProToTree father;//因为看到题目里输入量很小,所以就放心的加了father指针便于回溯
	ProToTree left;
	ProToTree right;
};
queue<ProToTree> s;//广度优先搜索所用的队列(先进先出)
AVLTree *tree = new AVLTree;
int flash(ProToTree Head);
void AVLchange(ProToTree b);
void insert(int i, ProToTree Head) {//在AVL树中插入一个节点,注意只是插入而没有进行AVL平衡化
	ProToTree a = NULL;
	int t;
	ProToTree b;
	b = Head;
	//a = (ProToTree)malloc(sizeof(AVLTree));
	while (b != NULL) {
		//b->level++;
		a = b;
		if (i > b->ID) {
			b = b->right;
			t = 1;
		}
		else {
			b = b->left;
			t = 2;
		}
	}
	if (t == 2) {
		a->left = (ProToTree)malloc(sizeof(AVLTree));
		b = a->left;
	}
	else {
		a->right = (ProToTree)malloc(sizeof(AVLTree));
		b = a->right;
	}
	b->ID = i;
	b->left = NULL;
	b->right = NULL;
	b->level = 0;
	b->father = a;
	while (tree->father != NULL)
		tree = tree->father;
	flash(tree);//刷新AVL树的level值
	AVLchange(b);//让AVL树平衡
}
int flash(ProToTree Head) {//刷新AVL树高度值,父=max(子1,子2)+1
	if (Head == NULL)
		return 0;
	Head->level = max(flash(Head->left), flash(Head->right)) + 1;
	return Head->level;
}
int level(ProToTree b) {
	if (b == NULL)
		return 0;
	else
		return b->level;
}
void insert1(ProToTree a, ProToTree b) {//将b插入到a树下面
	if (b->ID < a->ID)
		a = a->left;
	else
		a = a->right;
	if (b->ID < a->ID) {
		a->left = b;
		b->father = a;
	}
	else {
		a->right = b;
		b->father = a;
	}
}
void AVLchange(ProToTree b) {//AVL平衡,我没有讨论RR还是RL,LL,LR,直接把破坏的3个节点找出来然后排序重建树
	ProToTree a = NULL, c = NULL;//然后再把之前与3个节点相连的树分支再重新组合成搜索树
	ProToTree top, t2, t3, t4, t5, temp;
	int left = 0;
	while (1) {
		if (b== NULL)
			break;
		if (abs(level(b->left) - level(b->right)) > 1)
			break;
		c = a;
		a = b;
		b = b->father;
		//cout<<"1";
	}
	if (a == NULL || c == NULL || b== NULL) {
		while (tree->father != NULL)
			tree = tree->father;
		flash(tree);
		return;
	}
	
	top = b->father;
	if (top != NULL)
		if (top->left == b)
			left = 1;
	t2 = a->left;
	if (t2 == c)
		t2 = a->right;
	t5 = b->left;
	if (t5 == a)
		t5 = b->right;
	t3 = c->left;
	t4 = c->right;
	//cout << a->ID << " " << b->ID << " " << c->ID <<"change to" <<endl;
	if (a->ID > b->ID)
		swap(a, b);
	if (a->ID > c->ID)
		swap(a, c);
	if (b->ID > c->ID)
		swap(b, c);
	//cout << a->ID << " " << b->ID << " " << c->ID << endl;
	a->father = b;
	a->left = NULL;
	a->right = NULL;
	c->left = NULL;
	c->right = NULL;
	c->father = b;
	b->left = a;
	b->right = c;
	b->father = top;
	if (top != NULL)
		if (left)
			top->left = b;
		else
			top->right = b;
	if (t2 != NULL)
		insert1(b, t2);
	if (t3 != NULL)
		insert1(b, t3);
	if (t4 != NULL)
		insert1(b, t4);
	if (t5 != NULL)
		insert1(b, t5);
	while (tree->father != NULL)
		tree = tree->father;
	flash(tree);
}
void level_transvers(ProToTree Head) {//层序遍历,也就是广度优先搜索
	ProToTree a;
	Head->t = 1;
	//a = Head;
	s.push(Head);
	while (!s.empty()) {
		a = s.front();
		if (a->father != NULL)
			if (a == a->father->left) {
				a->t = 2 * (a->father->t);
				if (max1 < a->t)
					max1 = a->t;
			}
			else {
				a->t = 2 * (a->father->t) + 1;
				if (max1 < a->t)
					max1 = a->t;
			}
		//if (a->left != NULL)
		//s.push_back(a->left);
		//if (a->right != NULL)
		//s.push_back(a->right);
		if (a->father == NULL)
			cout << a->ID;
		else
			cout << " " << a->ID;//<<"level:"<<a->level ;
		s.pop();
		if (a->left != NULL)
			s.push(a->left);
		if (a->right != NULL)
			s.push(a->right);
	}
}
int main() {
	int N, i;
	cin >> N;
	int temp;
	cin >> temp;
	tree->father = NULL;
	tree->ID = temp;
	tree->left = NULL;
	tree->right = NULL;
	tree->level = 0;
	for (i = 1; i < N; i++) {
		cin >> temp;
		insert(temp, tree);
	}
	while (tree->father != NULL)
		tree = tree->father;
	tree->t = 1;
	level_transvers(tree);
	cout << endl;
	if (max1==N||N==1)//判断是否为完全二叉树,我借用了二叉堆的性质,如果把这棵树放到二叉堆里,定义一个节点下标,根为1
		cout << "YES" << endl;//让子1=父*2,子2=父*2+1,那么最大的节点下标应该和总节点数相同
	else
		cout << "NO" << endl;
}


感想:

1.这是今天考的PAT甲级题目。虽然我考的是乙级,但是一回来就来做甲级了,最终还是花了5个小时才满分,也许实际去考也就80多一点吧

2.这道题难点在于指针的运用,涉及到广度优先搜索,AVL树建立与扩充,完全二叉树判断等许多知识,当然如果熟练的话也可以用二叉堆来做。

3.注意节点只有一个也是完全二叉树,完全二叉树概念不要与满二叉树混乱

4.广度优先搜索使用STL会更简单。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值