19年冬季第四题 PAT甲级 1167 Cartesian Tree (30分)

110 篇文章 0 订阅

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值