PAT 1123. Is It a Complete AVL Tree (30)
给定一个包含N个数的序列,将他们依次插入平衡二叉搜索树中,按照层序遍历的方式输出二叉搜索树中每个节点的值,并判断此是否为完全二叉树。
采用链表方式完成二叉树的存储,在读入新的数并将其插入原始二叉树后,判断此二叉树的平衡是否被破坏,如果二叉树平衡被破坏,需要根据情况完成二叉树的旋转,此部分代码如下:
Tree Insert(Tree tree, int a)
{
if(tree == NULL){
tree = Initialize(a);
return tree;
}
if(a<tree->val){
tree->left = Insert(tree->left, a);
if(FindHeight(tree->left)-FindHeight(tree->right) > 1){ //平衡被破坏
if(a<tree->left->val){
tree = SingleLeft(tree);
}
else{
tree = LeftRight(tree);
}
}
}
else{
tree->right = Insert(tree->right, a);
if(FindHeight(tree->right) - FindHeight(tree->left) > 1){
if(a>tree->right->val)
tree = SingleRight(tree);
else
tree = RightLeft(tree);
}
}
return tree;
}
完成平衡二叉树的构建后,需要对其进行层序遍历,同时判断其是否为完全二叉树。
注意到如果使用数组存储完全二叉树,根节点存储在下标为1的位置,则完全二叉树的父节点与左右儿子节点的存储下标满足 parentIndex = index, leftChildIndex = index*2,
rightChildIndex = index*2+1。因此判断其是否为完全二叉树,我们只需要判断其孩子节点的下标是否越过n 的界限。
采用队列数据结构,树的根节点入队,而后判断队列是否为空,若队列非空,则弹出队首元素,并找到若为完全二叉树,队首元素在数组中的下标。 同时将弹出元素的左右儿子压入队列中,并按照父节点与子节点间下标的关系,进行标记。 判断是否出界,若出界,则不为完全二叉树。
代码如下:
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
struct BinaryTree;
typedef struct BinaryTree *Tree;
struct BinaryTree
{
int val;
Tree left;
Tree right;
};
Tree Initialize(int a)
{
Tree tree = (Tree)malloc(sizeof(struct BinaryTree));
tree->left = NULL;
tree->right = NULL;
tree->val = a;
return tree;
}
int Max(int a, int b)
{
if(a>b)
return a;
else
return b;
}
int FindHeight(Tree tree)
{
int height = 0;
if(tree == NULL)
return 0;
if(tree->left == NULL && tree->right == NULL){
height = 1;
return height;
}
else{
height = Max(FindHeight(tree->left), FindHeight(tree->right)) + 1;
return height;
}
}
Tree SingleLeft(Tree tree)
{
Tree a = tree;
Tree b = a->left;
a->left = b->right;
b->right = a;
return b;
}
Tree SingleRight(Tree tree)
{
Tree a = tree;
Tree b = a->right;
a->right = b->left;
b->left = a;
return b;
}
Tree LeftRight(Tree tree)
{
Tree a = tree;
Tree b = a->left;
Tree c = b->right;
b->right = c->left;
a->left = c->right;
c->left = b;
c->right = a;
return c;
}
Tree RightLeft(Tree tree)
{
Tree a = tree;
Tree b = tree->right;
Tree c = b->left;
b->left = c->right;
a->right = c->left;
c->left = a;
c->right = b;
return c;
}
Tree Insert(Tree tree, int a)
{
if(tree == NULL){
tree = Initialize(a);
return tree;
}
if(a<tree->val){
tree->left = Insert(tree->left, a);
if(FindHeight(tree->left)-FindHeight(tree->right) > 1){
if(a<tree->left->val){
tree = SingleLeft(tree);
}
else{
tree = LeftRight(tree);
}
}
}
else{
tree->right = Insert(tree->right, a);
if(FindHeight(tree->right) - FindHeight(tree->left) > 1){
if(a>tree->right->val)
tree = SingleRight(tree);
else
tree = RightLeft(tree);
}
}
return tree;
}
Tree position;
void FindPosition(Tree tree, int a)
{
Tree result;
if(tree->val == a){
position = tree;
return;
}
else if(a<tree->val)
FindPosition(tree->left, a);
else
FindPosition(tree->right, a);
return;
}
int FindIndex(int* flag, int a, int n)
{
for(int i=1;i<=n;i++){
if(a == flag[i]){
return i;
}
}
}
int main()
{
int n;
cin>>n;
Tree tree = NULL;
int num;
for(int i=0;i<n;i++){
cin>>num;
tree = Insert(tree, num);
}
queue<int> Queue;
int a;
int* flag = (int*)malloc(sizeof(int)*(n+1));
int tag = 1;
Queue.push(tree->val);
int index = 1;
flag[index] = tree->val;
while(!Queue.empty()){
a = Queue.front();
index = FindIndex(flag, a, n);
Queue.pop();
position = NULL;
cout<<a;
FindPosition(tree, a);
if(!Queue.empty() || (Queue.empty() && (position->left != NULL || position->right != NULL)))
cout<<" ";
if(position->left != NULL){
Queue.push(position->left->val);
if(index*2 <=n){
flag[index*2] = position->left->val;
}
else{
tag = 0;
}
}
if(position->right != NULL){
Queue.push(position->right->val);
if(index*2 +1<=n){
flag[index*2+1] = position->right->val;
}
else
tag = 0;
}
}
cout<<endl;
if(tag==1)
cout<<"YES";
else
cout<<"NO";
system("pause");
return 0;
}