树的重构-根据前序遍历和中序遍历推出整颗树

看这个文章需要的前缀知识是树的性质和树的前序遍历和中序遍历以及后续遍历的知识;

我会写一篇文章来介绍这三种遍历,如果不了解这些的话,可以到我的博客里翻翻;

好,话归正题,先看题;

这个题目的意思就是给你树的前序和后续遍历进行重构;

我们要知道给我们两种遍历的顺序里有什么规律;

前序遍历的性质:前一个字符可能是后一个字符的父节点;

后续遍历的性质:一个字符的左边一定是这个字符对应的左子树,右边一定对应的是这棵树的右子树;


我们要准备一个变量cont指向前序遍历的字符,如果找到该字符在树中的位置,那么我们就将这个变量++,指向下一个字符;

且进行操作的递归函数有以下参数;

int l,int r ;代表我们在后续遍历需要查找的区间的左右端点;

int pos;代表该递归层数在树中的位置;

那么根据以上性质,我们可以又以下步骤进行操作;

1:查找区间[l,r],中是否存在cont指向的字符

(1)存在:将其在后续遍历字符串中的位置存到遍历p中,将cont++,并遍历左、右子树,即[l,p-1]和[p+1,r];

(2) 不存在:跳回上一层;

直到所有区间都遍历一遍,这个遍历的时间复杂度是o(n^2)的,但我们也可以用空间换时间,将时间复杂度降到o(n),具体实现方式很简单,即我们记录下每个字符在后续遍历中的位置,如果判断一个字符是否存在于某个区间时,直接将对应的数据拿出来比对即可,这步的操作时间复杂度是o(1)的;

那么接下就是代码了

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;

const int N = 100010;

char a[N], b[N];
char tr[N];
int len;
int cont=1;
string ans;

int get(int l, int r, int pos){//pos表示当前递归层数在树中的位置,cont表示在前序的位置

	if (l > r) return 0;

	int p = -1;

	for (int i = l; i <= r; i++) {//查找对应的字符是否存在于子树中;
		if (b[i] == a[cont]) {
			p = i; break;
		}
	}

	if (p == -1) return 0;//如果不存在于这个区间,那么我们就跳回上一层

	tr[pos] = a[cont],cont++;//存在的话我们就将这个字符打到对应的位置上

	get(l, p - 1, pos * 2);//递归该节点的左子树

	get(p + 1, r, pos * 2 + 1);//右子树

	return 1;

}

void re(int i) {//后序遍历模板

	if (tr[i] == '\0') return;

	re(i * 2);
	re(i * 2 + 1);

	ans += tr[i];
}

int main() {

	cin >> b + 1 >> a + 1;

	len = strlen(b + 1);

	get(1, len, 1);

	re(1);

	cout << ans;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值