PAT Cartesian Tree(2019年冬季考试 )——由二叉排序树到笛卡尔树

原题

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

简单分析

  1. 找到最小的(i)插入到根节点
  2. 从i左边到开头找到最小的插入左孩子
  3. 从i右边到末尾找到最小的插入右孩子
  4. 以此循环2,3
  5. 最后层序输出

进一步分析

  1. 在树的几种遍历算法中与 二叉排序树的插入十分类似
  2. 在全部步骤中都有一步——找到最小-》因此单独拉出来作为模块函数
  3. 如何判断“左边/右边”的问题,通过stl库函数——map记录序号,通过序号大小来定位左右
  4. 对于层序输出,也可采用现成stl库函数——队列进行实现

其实能想到二叉排序树,剩下难点就是如何用程序来量化左右的问题

代码

#pragma warning(disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<map>
#define max 30
using namespace std;

typedef struct BTNode {
	int key;
	struct BTNode* lchild;
	struct BTNode* rchild;
}BiTree;
int FindSmall(int begin1, int end2, int a[]);
BiTree* BstInsert(BiTree* T, int a[], int be, int en, int sm, map<int, int>mp);
void PrintTree(BiTree* T);

int main() {
	map<int, int>mp;
	int number = 0;
	scanf("%d", &number);
	int a[30], i = 0;
	//int* a = (int*)malloc(sizeof(int) * number);用malloc定义变量数组
	for (i = 1; i <= number; i++) {
		scanf("%d", &a[i]);
		mp[a[i]] = i;//对序号进行映射
	}
	int begin, end, small;
	begin = 1, end = number;
	small = FindSmall(begin, end, a);
	BiTree* root = NULL;
	root = BstInsert(root, a, begin,end,small, mp);
	PrintTree(root);
	return 0;
}

int FindSmall(int begin1, int end2, int a[]) {
	int small, i;
	small = a[begin1];
	for (i = begin1 + 1; i <= end2; i++) {
		small = min(small, a[i]);
	}
	return small;
}

BiTree* BstInsert(BiTree * T, int a[],int be ,int en,int sm , map<int, int>mp) {
		if (T == NULL) {
			T = (BiTree*)malloc(sizeof(BiTree));
			T->key = sm;
			T->lchild = T->rchild = NULL;
		}
		int len;
		len = mp[sm] - 1;
		if(len-be>=0) {
			int LeftSmall;
			LeftSmall = FindSmall(be,len, a);
			T->lchild = BstInsert(T->lchild, a, be, len, LeftSmall, mp);
		}
		be = mp[sm] + 1;
		if(en - be >= 0) {
			int RightSmall;
			RightSmall = FindSmall(be, en, a);
			T->rchild = BstInsert(T->rchild, a, be, en, RightSmall, mp);
		}
		return T;
}

void PrintTree(BiTree* T) {
	queue<BiTree*> b;
	if (T != NULL) {
		b.push(T);
		while (b.empty() != true) {
			if (b.front()->lchild != NULL)
				b.push(b.front()->lchild);
			if (b.front()->rchild != NULL)
				b.push(b.front()->rchild);
			printf("%d ", b.front()->key);
			b.pop();
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值