03-树3 Tree Traversals Again (25 分)

今天在学习数据结构,刷作业时遇到这个问题,题目隐含条件挖掘出来以后就是根据先序遍历和中序遍历,然后让你推出后序遍历的结果。

一开始我就想到可以用循环,但是写着写着发现有点复杂,为什么不用递归呢?
递归肯定是可以,但是我遇到一个问题,就是思路感觉是对的,但是结果总是不对,后来我换成自己构造的简单测试案例然后一步一步跑,最后发现是由于函数使用的是值传递,在每次递归里面对传进去的东西修改以后,无法传出来,所以果断改用引用,果然对了!
但是提交以后发现递归爆栈了。。果然递归大法好,一直爆栈一直爽。。

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int CountLeft(vector<int>V, int X) {
	int count = 0;
	for (int i = 0; i < V.size(); i++) {
		if (V[i] != X)count++;
		else break;
	}
	return count;
}
int CountRight(vector<int>V, int X) {
	int i=999999, count = 0;
	for (int j = 0; j < V.size(); j++) {
		if (V[j] == X) {
			i = j;
		}
		if (j > i)count++;
	}
	return count;
}
int flag = 1;
vector<int>S;
void Search(vector<int>&V1, vector<int>&V2) {
	int lef = CountLeft(V2, V1[0]);
	int righ = CountRight(V2, V1[0]);
	int root = V1[0];
	V1.erase(V1.begin());
	if (lef != 0) {
		vector<int>tmp1;
		tmp1.insert(tmp1.begin(), V2.begin(), V2.begin() + lef);
		Search(V1, tmp1);
		
	}
	if (righ != 0) {
		vector<int>tmp;
		tmp.insert(tmp.begin(), V2.begin() + lef + 1, V2.end());
		Search(V1, tmp);
	
	}
	if (flag == 1) { cout << root; flag = 0; }
	else { cout << " " << root; }
}
int main() {
	int N;
	string s;
	scanf("%d", &N);
	cin.ignore();
	vector<int>V1, V2, V3;
	for (int i = 0; i < 2*N; i++) {
		getline(cin, s);
		if (s.length() == 6) {
			V1.push_back(s[5] - '0');
			V2.push_back(s[5] - '0');
		}
		else {
			int tmp = V1[V1.size() - 1];
			V3.push_back(tmp);
			V1.pop_back();
		}
	}
	Search(V2, V3);
	return 0;
}

我试着修改成循环吧。。
在这里插入图片描述修改过后的代码

#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<int>V1, V2, V3, V4;
void postorder(int root, int start, int end) {
	if (start >end)return;
	int i = start;
	while (i < end&&V3[i] != V2[root])i++;
	postorder(root + 1, start, i - 1);
	postorder(root + i - start + 1, i + 1, end);
	V4.push_back(V2[root]);
}
int main() {
	int N, value;
	string s;
	scanf("%d", &N);
	cin.ignore();
	for (int i = 0; i < 2 * N; i++) {
		cin >> s;
		if (s.length() == 4) {
			cin >> value;
			V1.push_back(value);
			V2.push_back(value);
		}
		else {
			int tmp = V1[V1.size() - 1];
			V3.push_back(tmp);
			V1.pop_back();
		}
	}
	postorder(0, 0, N - 1);
	for (int i = 0; i < V4.size(); i++) {
		if (i == 0)cout << V4[0];
		else cout << " " << V4[i];
	}
	return 0;
}

得出一个很重要结论就是:尽量减少在递归里面进行计算,不然很容溢出;

好吧还有第三个版本,建立索引,对索引进行操作,膜拜柳神

#include<iostream>
#include<string>
#include<vector>
#include<stack>
using namespace std;
vector<int>V1, V2, V3, V4;
void postorder(int root, int start, int end) {
	if (start >end)return;
	int i = start;
	while (i < end&&V3[i] != V2[root])i++;
	postorder(root + 1, start, i - 1);
	postorder(root + i - start + 1, i + 1, end);
	V4.push_back(V2[root]);
}
int main() {
	int N, value, key = 0;
	string s;
	stack<int>S;
	scanf("%d", &N);
	cin.ignore();
	for (int i = 0; i < 2 * N; i++) {
		cin >> s;
		if (s.length() == 4) {
			cin >> value;
			V1.push_back(value);//顺序值表
			V2.push_back(key);//顺序索引
			S.push(key++);
		}
		else {
			V3.push_back(S.top());//中序索引
			S.pop();
		}
	}
	postorder(0, 0, N - 1);
	for (int i = 0; i < V4.size(); i++) {
		if (i == 0)cout << V1[V4[0]];
		else cout << " " << V1[V4[i]];
	}
	return 0;
}

在此总结一下递归的经验(新手菜鸡,第一天接触递归。)
①:找到宏观写法,意思就是拿分而治之就是把左边看成新的整体,右边看成新的整体,调用本函数处理左边,处理右边。
②:找到边界条件,意思就是合适退出递归,返回上一层。
③:尽量减少递归里调用其他函数,很容易爆栈。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园失物招领系统管理系统按照操作主体为管理员和用户。管理员的功能包括字典管理、论坛管理、公告信息管理、失物招领管理、失物认领管理、寻物启示管理、寻物认领管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 校园失物招领系统管理系统可以提高校园失物招领系统信息管理问题的解决效率,优化校园失物招领系统信息处理流程,保证校园失物招领系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 ,管理员权限操作的功能包括管理公告,管理校园失物招领系统信息,包括失物招领管理,培训管理,寻物启事管理,薪资管理等,可以管理公告。 失物招领管理界面,管理员在失物招领管理界面中可以对界面中显示,可以对失物招领信息的失物招领状态进行查看,可以添加新的失物招领信息等。寻物启事管理界面,管理员在寻物启事管理界面中查看寻物启事种类信息,寻物启事描述信息,新增寻物启事信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值