PTA 04-树6 Complete Binary Search Tree (30分)

题目地址

https://pta.patest.cn/pta/test/16/exam/4/question/669

5-7 Complete Binary Search Tree   (30分)

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
  • Both the left and right subtrees must also be binary search trees.

    A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.

    Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains a positive integer NN (le 10001000). Then NN distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.

    Output Specification:

    For each test case, print in one line the level order traversal sequence of the corresponding complete binary search 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.

    Sample Input:

    10
    1 2 3 4 5 6 7 8 9 0
    

    Sample Output:

    6 3 8 1 5 7 9 0 2 4
/*
评测结果
时间	结果	得分	题目	编译器	用时(ms)	内存(MB)	用户
2017-06-29 10:45	正在评测	0	5-7	gcc	无	无	
测试点结果
测试点	结果	得分/满分	用时(ms)	内存(MB)
测试点1	答案正确	18/18	1	1
测试点2	答案正确	3/3	2	1
测试点3	答案正确	2/2	1	1
测试点4	答案正确	2/2	1	1
测试点5	答案正确	3/3	1	1
测试点6	答案正确	2/2	3	1


完全二叉搜索树
结构:数组形式存储完全树,可以很方便进行层序遍历 
解法:思考后发现完全二叉搜索树的子树也是完全二叉搜索树。故先将接收到的数据排序,递归计算一个节点的左子树和右子树数量,类似于快排,每次可以确定root的值。
然后按顺序打印数组即可。 
*/

#include<stdio.h>
#define MAXLEN 2000

int workarray[MAXLEN];
int CBST[MAXLEN+1];//0号元素空着,从1号开始左子树2*root,右子树2*root+1;
int NODECOUNT[MAXLEN+1];
int Len;
void swap(int *a,int *b)
{
	int temp;
	temp=*a;
	*a=*b;
	*b=temp;	
}

void InsertionSort(int A[],int N)
{
	int i;
	int k;
	for(i=1;i<N;i++)
	{
		int temp=A[i];
		k=i;
		while(temp < A[k-1])
		{
				swap(&A[k],&A[k-1]);
				k--;
		}
		A[k]=temp;
	}
} 

void GetInput()
{
	int i;
	scanf("%d",&Len);
	for(i=0;i<Len;i++)
	{
		scanf("%d",&workarray[i]);
	}
}

void Output()
{
	int i;
	for(i=1;i<Len+1;i++)
	{
		printf("%d",CBST[i]);
		if(i!=Len)
			printf(" "); 
	}
}
void Outputcount() //调试用函数
{
	int i;
	for(i=1;i<Len+1;i++)
	{
		printf("%d ",NODECOUNT[i]);
	}
}
void Outputraw() //调试用函数
{
	int i;
	for(i=0;i<Len;i++)
	{
		printf("%d ",workarray[i]);
	}
}

void CountNodes() //太懒了,数据量不大,直接让它自己数节点数量得了。 逆序算出此节点之下所有子树节点之和 
{
	int i;
	for(i=0;i<Len+1;i++)
	{
		NODECOUNT[i]=0;//先全体置零 
	}

	for(i=Len;i>0;i--)//在1开头的数组中,有效下标范围应该是1~Len 
	{
		NODECOUNT[i/2] += NODECOUNT[i]+1; //父节点的子树,加上本节点的子树,再加上该节点自身 
	}

}

void CalcTree(int raw[],int calc[],int left,int index)
{
	if (index>Len) return; //越界了,没子树 
	int raw_position=left+(2*index>Len?0:NODECOUNT[2*index]+1);//注,函数首次调用,left最初传入的是0, 判断是否为叶节点,如果没有左子树,那么它自己就是left 
	//此处加个注释说明下,一个坐标的构成。left(此递归段偏移起点)+NODECOUNT[2*index](所求的点的左儿子的全部结点数量)+1(该结点本身,即此递归段的root) 
	calc[index]=raw[raw_position];
	CalcTree(raw,calc,left,2*index);//递归左子树 
	CalcTree(raw,calc,raw_position+1,2*index+1);//递归右子树 
}

int main()
{
	GetInput();
	InsertionSort(workarray,Len);
//	printf("done sort
");
//	Outputraw();
//	printf("
");
	CountNodes();
	CalcTree(workarray,CBST,0,1);
	Output();
	printf("
");
//	Outputcount();
}

  

 

原文地址:https://www.cnblogs.com/gk2017/p/7140616.html