【ACM】- PAT. A1064 Complete Binary Serach Tree 【BST】

题目链接
题目分析

输入一组整数(不等),要求构造一棵树,满足同时为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;
}

猜你喜欢

转载自blog.csdn.net/qq_26398495/article/details/81813023