PTA_2019春_046_Complete Binary Search Tree

根据给定的非负整数序列,构建一个同时满足二叉搜索树和完全二叉树条件的独特树。输出该树的层次遍历序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 N (≤1000). Then N 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
    

   

/* Complete Binary Search Tree */
/*思路: 对于二叉搜索树,其实是一种动态的查找排序的树。
         对于完全二叉搜索树来说,父节点是左右子节点的相对中间的数
         1.对所给序列(N个数)进行排序从小到大;
		 2.创建完全二叉树节点个数为N个;(层序创建树)
		 3.获得层数K;(K为正整数);
		 4.将序列中的数填入进构造好的树中
		   (1)判断以A为根节点树是否是完全树,如果是,则根节点为,序列中间数,即第N/2+1个树
		        如果不是完全树,则判断其左子树是否是完全树。若是,获得左子树层数K,则A为第2^(k)个数,
				如果不是,则其右子树为完全树,获得右子树层数K,则A为倒数第2^(k)个数
		   (2)左子树插入,更新序列为,第一个到第A-1个数
		   (3)右子树插入,更新序列为,第A+1到N个数*/
   /*判断完全树的方法,获得该树的层数,即获得完全数的节点数,然后遍历其所有节点统计个数,二者进行比较*/
   /*第一次自己用递归解决问题!*/
          
#include<stdio.h> 
#include<stdlib.h>
#include<math.h>
/*树结构*/ 
struct treenode {
	int data;
	struct treenode* left;
	struct treenode* right;
};
typedef struct treenode* Tree;
/*队列结构*/ 
typedef struct Qnode* ptrtoQnode;
struct Qnode {
	Tree* data;/*data数组,*/
	int front, rear;/*队列头尾指针*/
	int maxsize;/*容量*/
};
typedef ptrtoQnode Queue;

void sort(int* array,int N); /*从小到大排序*/ 

int AddQ(Queue Q, Tree x);/*进队列*/ 
Queue CreateQueue(int maxsize); /*创建队列*/ 
int isempty(Queue Q);   /*判断是否为空*/ 
Tree DeleteQ(Queue Q);  /*出队列*/ 
int getheight(Tree T);  /*获得树的高度*/ 
int max(int a, int b);   /*取二者中较大值*/ 
int  insert(Tree T,int* array ,int head,int rear );  /*按照完全二叉树的结构修改原完全树*/ 
int numberoftree(Tree T);   /*树节点数量*/ 
int power(int a, int b);   /*实现a的b次方*/ 
int iscbt(Tree T) ;             /*判断是否是完全树*/ 
void levelorder(Tree T,int N);   /*层序遍历*/ 

int main() {
	int N;/*节点个数*/
	scanf("%d", &N);
	int* array = (int*)malloc(N * sizeof(int));
	for (int i = 0; i < N; i++) {
		scanf("%d", &array[i]);
	}/*输入完毕*/

	sort(array, N);/*排序*/

     /*层序建树*/
	int maxsize = 1000;
	Queue Q = CreateQueue(maxsize);
	Tree cbt, T;
	int k = 1;/*建树时用于标记创建节点的个数*/
	cbt = (Tree)malloc(sizeof(struct treenode));
	cbt->data = 1;/*所有节点的data初始化为1*/
	cbt->left = cbt->right = NULL;
	AddQ(Q, cbt);
	while (!isempty(Q)) {
		if (k == N) break;
		T = DeleteQ(Q);
		T->left = (Tree)malloc(sizeof(struct treenode));
		T->left->data = 1; /*初始化为1,后序插入操作修改即可*/
		T->left->left = T->left->right = NULL;
		AddQ(Q, T->left);
		k++;
		if (k == N) break;
		T->right = (Tree)malloc(sizeof(struct treenode));
		T->right->data = 1; 
		T->right->left = T->right->right = NULL;
		AddQ(Q, T->right);
		k++;
	}/*建树cbt完成*/

	/*将数组的元素填入到建好的树中*/
	int head = 0;  /*指向数组的第一个*/
	int rear = N - 1;/*指向数组的最后一个*/
	cbt->data = insert(cbt, array, head, rear);
	
	/*层序遍历*/
	levelorder(cbt,N);
	return 0;
}
void sort(int* array,int N) {
	int temp;/*临时变量*/
	for (int i = 0; i < N; i++) {
		for (int j = i + 1; j < N; j++) {
			if (array[i] > array[j]) {
				temp = array[i];
				array[i] = array[j];
				array[j] = temp;
			}
		}
	}
}
Queue CreateQueue(int maxsize) {
	Queue Q = (Queue)malloc(sizeof(struct Qnode));
	Q->data = (Tree*)malloc(maxsize * sizeof(struct treenode));
	Q->front = Q->rear = 0;
	Q->maxsize = maxsize;
	return Q;
}
int AddQ(Queue Q, Tree x) {
	Q->rear = (Q->rear + 1) % (Q->maxsize);
	Q->data[Q->rear] = x;
	return 1;
}
int isempty(Queue Q) {
	return(Q->rear == Q->front);
}
Tree DeleteQ(Queue Q) {
	Q->front = (Q->front + 1) % Q->maxsize;
	return Q->data[Q->front];
}
int max(int a, int b) {
	if (a > b) return a;
	else return b;
}
int getheight(Tree T) {
	int height;
	if (T) {
		return (max(getheight(T->left), getheight(T->right)) + 1);
	}
	else return 0; /*空树为0*/
}
int  insert(Tree T,int* array ,int head,int rear ) {  /*递归关键在最终的返回判断*/ 
	int num;
	
	if (head == rear)  return array[head];
	if (iscbt(T) == 1) { /*为完全树*/
		num = ((rear - head) + 1)/2+head;
	}
	else {
		if(iscbt(T->left)==1){   /*左子树为完全树*/
		    num = power(2, getheight(T->left))+head - 1;
		} 
		else {    /*左子树不是完全树,那么右子树一定是完全树*/
			num = rear - power(2, getheight(T->right)) + 1;
		}
	}
	  if(T->left) T->left->data = insert(T->left, array, head, num - 1);       /*之前一直错在此处,没有考虑子树不存在*/ 
	  if(T->right)  T->right->data = insert(T->right, array, num + 1, rear);
	return array[num];
	
}
int numberoftree(Tree T) {
	Queue Q1;
	Tree T1;
	int number = 0;
	Q1 = CreateQueue(1000);
	AddQ(Q1, T);
	while (!isempty(Q1)) {
		T1 = DeleteQ(Q1);
		number++;
		if (T1->left) AddQ(Q1, T1->left);
		if (T1->right) AddQ(Q1, T1->right);
	}
	return number;
}
int power(int a, int b){
	if (b == 0) return 1;
	else if (b == 1) return a;
	else return a * power(a, b - 1);
}
int iscbt(Tree T) {
	if ((power(2, getheight(T)) - 1) == numberoftree(T)) return 1;
	else return 0;
}
void levelorder(Tree T,int N) {  /*N用来控制最后一个数不输出空格*/ 
	int n = 0;
	Queue Q2;
	Tree T2;
	Q2 = CreateQueue(1000);
	AddQ(Q2, T);
	while (!isempty(Q2)) {
		T2 = DeleteQ(Q2);
		printf("%d", T2->data);
		n++;
		if(n!=N) printf(" ");
		if (T2->left)  AddQ(Q2,T2->left);
		if (T2->right) AddQ(Q2,T2->right);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值