题目链接
题目分析
输入一组整数(不等),要求构造一棵树,满足同时为BST和完全二叉树
之后输出层序遍历序列
解题思路
- 思路一:利用
BST
中序遍历为递增序列 - 思路二:利用完全二叉树的性质切分序列
思路一 (简单)
1、开一个数组CBT[]
用来存储完全二叉树;
2、将输入的数值递增排序;
3、对CBT[]
表示的二叉树进行中序遍历,并在遍历过程中将数字从小到大填入数组;
4、由于CBT[]
就是按层序来保存完全二叉树的,直接输出即可。
/**********************************
*@ID: 3stone
*@ACM: PAT.A1064 Complete Binary Serach Tree
*@Time: 18/8/13
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int N, cbt[maxn], seq[maxn];
int key = 1;
void in_order(int root) {
if(root > N) return;
in_order(root * 2); //遍历左子树
cbt[root] = seq[key++]; //赋值
in_order(root * 2 + 1); //遍历右子树
}
int main() {
while(scanf("%d", &N) != EOF) {
key = 1;
for(int i = 1; i <= N; i++ ) //完全二叉树根结点存储在1号结点
scanf("%d", &seq[i]);
//数值递增排序
sort(seq + 1, seq + N + 1);
//中序遍历赋值
in_order(1);
//层序输出(直接顺序输出即可)
for(int i = 1; i < N; i++)
printf("%d ", cbt[i]);
printf("%d\n---", cbt[N]);
}
return 0;
}
参考《算法笔记》
思路二
1、对输入值进行递增排序;
2、由结点数N
计算树高、最底层的结点数,进而找到根节点,划分左右子树;
3、递归操作就行。
/**********************************
*@ID: 3stone
*@ACM: PAT.A1064 Complete Binary Serach Tree
*@Time: 18/8/13
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 1010;
struct node{ //数结点
int data;
node* lchild;
node* rchild;
};
bool flag; //在建树过程中 标记是否能成功
int seq[maxn]; //保存输入的前序序列
int N, cur_num; //结点数,输出时记录输出了多少
node* new_node(int data_x) {
node* root = new node;
root->data = data_x;
root->lchild = root->rchild = NULL;
return root;
}
//计算结点数为n的完全二叉树高度-1
int get_height(int n) {
return (int)(log(n) / log(2)); //换底公式实现
}
int get_root_key(int left, int right) {
if(left == right) return left;
int num_lchild;
int height = get_height(right - left + 1); //返回树高减1
int num_without_last_level = (int)pow(2.0, (double)height) - 1; //k层完全二叉树的结点数 = 2^k - 1
int num_last_level = right - left + 1 - num_without_last_level; //二叉树最后一层的结点数 = 2^(k-1)
int half_last_level = (int)((num_without_last_level + 1) / 2);
if(num_last_level >= half_last_level){ //最后一层填了多于一半
num_lchild = half_last_level * 2 - 1;
} else {
num_lchild = half_last_level + num_last_level - 1;
}
return left + num_lchild; //返回根节点编号
}
//建立正常BST
node* create(int left, int right) {
if(left > right) return NULL; //递归基
//寻找根节点
int root_key = get_root_key(left, right);
node* root = new_node(seq[root_key]);
//递归 建树
root->lchild = create(left, root_key - 1);
root->rchild = create(root_key + 1, right);
return root;
}
void BFS_traversal(node* root) {
queue<node*> Q;
Q.push(root);
int num = 0;
while(!Q.empty()) {
node* front = Q.front();
Q.pop();
num++;
if(num == N)
printf("%d\n", front->data);
else
printf("%d ", front->data);
if(front->lchild) Q.push(front->lchild);
if(front->rchild) Q.push(front->rchild);
}
}
int main() {
while(scanf("%d", &N) != EOF) {
for(int i = 1; i <= N; i++){
scanf("%d", &seq[i]);
}
//递增排序
sort(seq + 1, seq + N + 1);
node* root = create(1, N);
BFS_traversal(root);
}
return 0;
}