1064. 完全二叉搜索树
给定一个数列,要求构造一个完全二叉搜索树,并输出其层序遍历的结果。
思路:
巧妙的思路是利用完全二叉树的的一个特殊属性:
按照层序遍历的顺序给所有节点标号,根节点标1,第二层的左节点标为2,右节点标为3……
记当前节点的下标为i,则其左孩子节点的下标为2i
,右孩子节点的下标为2i+1
。
现在,我们要得到层序遍历的结果,已知的则是排列好的递增序列。
我们注意到,对于一棵完全二叉搜索树,中序遍历可以得到递增序列。反过来,用中序遍历的方法也可以构造出一棵完全二叉搜索树。
在构造的过程中,我们就在tree数组中得到了层序遍历结果。
#include<stdlib.h>
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<limits.h>
#include<cmath>
#include<set>
#include<map>
#include<utility>
#include<algorithm>
using namespace std;
vector<int> node;
vector<int> tree(1005,0);
int pos,n;
void build(int root) {
if(root>n) return;
//计算左子树和右子树的下标位置
int lson = root<<1,rson =(root<<1)+1;
build(lson);
tree[root] = node[pos++];
build(rson);
}
int main() {
int pp;
cin>>n;
for(int i=0;i<n;++i) {
cin>>pp;
node.push_back(pp);
}
sort(node.begin(),node.end());
pos = 0;
build(1);
for(int i=1;i<=n;i++) {
cout<<tree[i];
if(i!=n) cout<<' ';
}
cout<<endl;
return 0;
}
1020. 树的遍历
已知后序遍历和中序遍历的数列,要求构造二叉树,然后按层序输出。
思路:
后序遍历的最后一个元素一定是整棵树的根,从后向前,分别是右、左子树的根。
相应的,中序序列中根结点左边的元素一定属于左子树,右边的元素一定属于右子树。
借鉴BFS层序遍历的思路:
- postorder的最后一个元素即为整棵树的根结点;
- 在inorder中找到该根结点,以它为分界,左边的元素构成左子树,右边的元素构成右子树,将两个范围
[0,i-1] [i+1,n-1]
存入队尾; - 从队首取一个元素(范围),考察inorder中该范围的元素,寻找postorder中从后往前出现的第一个元素,它就是该范围构成的子树的根结点;
- 以该结点为分界,将该范围再细分成两个范围(左、右子树)存入队尾;
- 继续直到队列变空。
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;