7-4 Cartesian Tree (30分)
A Cartesian tree is a binary tree constructed from a sequence of distinct numbers. The tree is heap-ordered, and an inorder traversal returns the original sequence. For example, given the sequence { 8, 15, 3, 4, 1, 5, 12, 10, 18, 6 }, the min-heap Cartesian tree is shown by the figure.
CTree.jpg
Your job is to output the level-order traversal sequence of the min-heap Cartesian tree.
Input Specification:
Each input file contains one test case. Each case starts from giving a positive integer N (≤30), and then N distinct numbers in the next line, separated by a space. All the numbers are in the range of int.
Output Specification:
For each test case, print in a line the level-order traversal sequence of the min-heap Cartesian tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.
Sample Input:
10
8 15 3 4 1 5 12 10 18 6
Sample Output:
1 3 5 8 4 6 15 10 12 18
树是难不倒我的!中序遍历来建树,序列中最小的就是根结点,左边的就是左子树,右边的就是右子树,递归建树。一定一定要搞清楚递归边界,就是啥时候返回空结点
//给定一棵树的中序遍历,求层序遍历,左根右
//这棵树是一个小顶堆
//递归每棵树or子树中最小的结点,左边的就是左子树,右边的就是右子树
#include<iostream>
#include<vector>
#include<unordered_map>
#include<queue>
using namespace std;
const int INF = 1000000000;
struct node{
int val;
node* lchild, *rchild;
};
vector<int> inOrder;
unordered_map<int,int> ma;
node* buildTree(int index,int inL, int inR){//最小值在中序中的下标,左边是左子树,右边是右子树
//不用递归边界,因为我们不会越界
node* root = new node;
root->val = inOrder[index];
root->lchild = root->rchild = nullptr;
if(inL != index){
int lMin = INF;
for(int i = inL; i < index; i++){
if(inOrder[i] < lMin) lMin = inOrder[i];
}
int lIndex = ma[lMin];
root->lchild = buildTree(lIndex,inL,index-1);
}
if(inR != index){
int rMin = INF;
for(int i = index+1; i <= inR; i++){
if(inOrder[i] < rMin) rMin = inOrder[i];
}
int rIndex = ma[rMin];
root->rchild = buildTree(rIndex,index+1,inR);
}
return root;
}
void levelOrderTrave(node* root){
queue<node*> q;
q.push(root);
bool flag = true;
while(!q.empty()){
node* topNode = q.front();
q.pop();
if(flag == true){
cout<<topNode->val;
flag = false;
}
else{
cout<<" "<<topNode->val;
}
if(topNode->lchild != nullptr) q.push(topNode->lchild);
if(topNode->rchild != nullptr) q.push(topNode->rchild);
}
}
int main(){
int n;
cin>>n;
inOrder.resize(n+1);
int minn = INF;
for(int i = 0; i < n; i++){
cin>>inOrder[i];
if(inOrder[i] < minn) minn = inOrder[i];
}
for(int i = 0; i < n; i++){
ma[inOrder[i]] = i;
}
node* root = new node;
root = buildTree(ma[minn],0,n-1);
levelOrderTrave(root);
return 0;
}
//根据中序序列来建最小堆,用map记录下每个值的下标,用于递归建树
//因为是最小堆,所以序列中最小的就是根,中序左边的就是左子树,中序右边的就是右子树
//分别在左边和右边找最小值来当子结点的值
#include<iostream>
#include<vector>
#include<queue>
#include<unordered_map>
using namespace std;
int n;
struct node{
int val;
node* lchild, *rchild;
};
vector<int> inOrder;
unordered_map<int,int> ma;
node* buildTree(int val,int inL, int inR){
//无需递归边界,因为我们在递归建树的时候不会越界
node* root = new node;
root->val = val;
root->lchild = root->rchild = nullptr;
if(inL != ma[val]){
int lMin = 1e9;
for(int i = inL; i < ma[val]; i++){
if(lMin > inOrder[i]){
lMin = inOrder[i];
}
}
root->lchild = buildTree(lMin,inL,ma[val] - 1);
}
if(inR != ma[val]){
int rMin = 1e9;
for(int i = ma[val]+1; i<= inR; i++){
if(rMin > inOrder[i]){
rMin = inOrder[i];
}
}
root->rchild = buildTree(rMin,ma[val]+1,inR);
}
return root;
}
void levelOrderTrave(node* s){
queue<node*> q;
q.push(s);
bool flag = true;
while(!q.empty()){
node* topNode = q.front();
q.pop();
if(flag){
cout<<topNode->val;
flag = false;
}
else{
cout<<" "<<topNode->val;
}
if(topNode->lchild != nullptr){
q.push(topNode->lchild);
}
if(topNode->rchild != nullptr){
q.push(topNode->rchild);
}
}
}
int main(){
cin>>n;
inOrder.resize(n+1);
for(int i = 0; i < n; i++){
cin>>inOrder[i];
}
for(int i = 0; i < n; i++){
ma[inOrder[i]] = i;
}
int minn = 1e9;
for(int i = 0; i < n; i++){
if(inOrder[i] < minn){
minn = inOrder[i];
}
}
node* root = new node;
root = buildTree(minn,0,n-1);
levelOrderTrave(root);
return 0;
}