1064 Complete Binary Search Tree (运用搜索二叉树BST的中序遍历输出层序遍历)

1064 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 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

参考大佬博客:https://blog.csdn.net/richenyunqi/article/details/78868563

本题思路

方法一: 利用完全搜索二叉树的性质 

n为结点个数

1.先将输入的n个结点值排序得到中序排列,

2. 通过log(n + 1) 向下取整 (floor() 为向下取整, ceil为向上取整) 得到除去最后一层的高度h eg:n=7的结点高度为3 (因为根节点只有一个值 所以需要 log n+1 除去最后一层高度)

 3.得到最后一层的结点数: n - (pow(2, h) - 1); (可能只存在左结点, 也存在右结点)

 4. 在测试样例1 中序排列中 : 0 1 2 3 4 5 6 7 8 9  只要知道了 左结点的个数 num; 通过(left(中序遍历结点最左边) + num 就能确定 root结点,)找到了根结点后 然后不断递归 先左子树, 后右子树, 设定一个index 记录根的下标 方便 层序输出

使 temp2  = (pow(2,h) - 1 )  / 2

5. 关键就如何求出左子树结点个数 : 此时 temp2 得到最后一层左子树能够存放的最大结点数(最后一层能够存储最大容量的一半), 通过min(temp2  , n - (pow(2, h) - 1)  )得到此时最后一层能够存放的左子树元素, temp2 -1 可以得到除去最后一层的左子树个数 :  因此左结点个数和sum为: sum =temp2 - 1 +    min(temp2  , n - (pow(2, h) - 1)  )                                        

具体代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
int n;
vector<int> in,level;
void levelOrder(int start, int end, int index){
	if(start > end) return;
    int sum = end - start + 1;
	int height = (int)floor(log((sum) + 1) / log(2)); //还没强转 log在cmath库中 
	int temp1 = sum - (int)(pow(2, height) - 1);  //最后一层的结点数量 
	int temp2 = pow(2, height) / 2; 	   //最后一层能够容纳的最大结点数量的一半 
	temp1 = min(temp1, temp2);         //取最小是因为temp1可能包含右结点,现在只需要算出左结点
	temp1 = start + temp1 + temp2 - 1;         //此时左子树结点总数为(temp1 + temp2 - 1) 同时加上start(left)就是中序遍历中根结点的下标
	level[index] = in[temp1];
	levelOrder(start, temp1 - 1, 2 * index + 1);
	levelOrder(temp1 + 1, end, 2 * index + 2);
}	
int main(){
	scanf("%d", &n);
	in.resize(n);    //在全局遍历中 用(n)也不能scanf输入 这里注意 只有用resize容器具有具体长度时 才能用scanf赋值 
	level.resize(n);
	for(int i = 0; i < n; i++){
		scanf("%d", &in[i]);
	}
	sort(in.begin(), in.end());
	levelOrder(0, n-1, 0);	
	for(auto i = 0; i < n; i++){
		if(i != 0) printf(" ");
		printf("%d", level[i]);
	}
	return 0;
}

方法二:

               方法一是通过顺序查找到每个 结点将每个结点的下标索引放入level数组中,

               更简便的方法是 直接通过 中序遍历 将中序遍历中的每个元素都加入到level数组 中 并不需通过求出高度,找到左结点的个数 先序遍历找到每个根结点

    

              具体代码:

           

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,position=0;
vector<int> level, in;
void levelOrder(int index){
	if(index > n-1) return;      //注意这里是n-1 因为根节点的下标是0 那么最后一个结点的下标为n-1 
	levelOrder(index * 2 + 1);   // 完全二叉搜索树中中序遍历中 第一个结点会是最左边的结点 
	level[index] = in[position++];
	levelOrder(index * 2 + 2);
}
int main(){
	scanf("%d", &n);
	level.resize(n);in.resize(n);
	for(int i = 0; i < n; i++){
		scanf("%d", &in[i]);
	}
	sort(in.begin(),in.end());
	levelOrder(0);
	for(int i = 0; i < n; i++){
		if(i != 0) printf(" ");
		printf("%d", level[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41698081/article/details/91046576