pat甲级1064-Complete Binary Search Tree

欢迎访问我的pat甲级题解目录哦https://blog.csdn.net/richenyunqi/article/details/84981078

题目描述

pat甲级1064-Complete Binary Search Tree_第1张图片

题意分析

给定一组序列,求出由该序列构成的完全二叉查找树的层次遍历序列。

通过计算左子树的元素个数确定根节点在序列中的位置

算法设计

将给定的序列从小到大进行排序,得到的序列即为二叉查找树的中根遍历序列,这样的话问题就变成了如何根据完全二叉查找树的中根遍历序列得出其层次遍历序列。

首先由于是完全二叉树,且求层次遍历序列,可以直接按完全二叉树的数组存储方式存储整棵树,即对于存储完全二叉树的数组tree,tree[1]表示的是整棵树的根节点,对于索引位置为i的结点,其左子树的根节点索引位置为2*i;右子树的根节点索引位置为2*i+1。数组中结点的存储顺序即为整棵树的层次遍历序列。

以样例为例解释整个算法:

对于元素个数为N=10的序列0 1 2 3 4 5 6 7 8 9(已进行排序),可知其构成的完全二叉查找树为:

pat甲级1064-Complete Binary Search Tree_第2张图片

如何求出根节点在已排序后的序列中的位置呢?很明显只需计算出左子树的元素个数我们就可以知道根节点在序列中的位置。可知除去最后一层整棵树层数depth=log(N+1)向下取整=3,如果将该树补足成满二叉树最后一层元素个数的一半temp=2^depth/2=2^(depth-1)=4,而实际上该树最后一层的元素总数temp2=N-(2^depth-1)=3,位于根节点的左子树的最后一层元素个数为num=min(temp,temp2)=3,故根节点在序列中的位置为num+temp-1=6。确定了根节点的位置,只需按照上述方法递归处理根节点的左子树和右子树就可重建整棵树。

C++代码

#include
using namespace std;
int N,A[1024],tree[1024];
void createTree(int left,int right,int index){
    if(left>right)
        return;
    int temp=(int)floor(log(right-left+2)/log(2));//除去最后一层的层数
    temp=(int)pow(2,temp-1);//如果是满二叉树最后一层元素个数的一半
    int num=min(right-left+1-(temp*2-1),temp),root=left+num+temp-1;//num表示位于根节点的左子树的最后一层元素个数,root表示根节点在序列中的位置
    tree[index]=A[root];//确定根节点
    createTree(left,root-1,index*2);//递归处理左子树
    createTree(root+1,right,index*2+1);//递归处理右子树
}
int main(){
    scanf("%d",&N);
    for(int i=0;i1?" ":"",tree[i]);
    return 0;
}

通过中根序列“左中右”的顺序重建整棵树

算法设计

在胡凡的算法笔记中提出了更简洁的算法,先将给定的序列从小到大排序,然后对按完全二叉树的数组存储方式存储的整棵树进行中序遍历,遍历过程中将数字从小到大填入数组,最后就能得到一棵完全二叉查找树。

C++代码

#include
using namespace std;
int N,position=0,A[1024],tree[1024];
void inorder(int root){
    if(root>N)
        return;
    inorder(2*root);//先遍历左子树
    tree[root]=A[position++];//填充根节点
    inorder(2*root+1);//遍历右子树
}
int main(){
    scanf("%d",&N);
    for(int i=0;i1?" ":"",tree[i]);
    return 0;
}

 

你可能感兴趣的:(pat甲级)