刷题笔记27——栈实现二叉树的非递归先序、中序、后序遍历

题目描述

利用栈实现二叉树的非递归先序、中序、后序遍历
在这里插入图片描述

为什么使用栈呢?
因为一个二叉树只有从上到下的路径,没有回去的路径
于是要想一个结构,让这个路径能从下到上往回走
那么栈就很适合这样的问题

为什么一个递归版本改非递归版本这么难改?
原因是你不能把所有的东西都压栈,自己做栈的话只能放一个结点类型,
很多信息会丢掉,这就是难改的原因

1. 非递归先序遍历

二叉树根结点先进栈,如果栈不为空则弹出栈顶并打印
然后先压右再压左,如此遍历就是中->左->右
在这里插入图片描述

2. 非递归中序遍历

如果当前结点为空,从栈拿一个打印,然后往右走
如果当前结点不空,当前结点进栈,然后往左走,一压压一溜
在这里插入图片描述

3. 非递归后序遍历

根据前序遍历的非递归写法,我们知道
要想实现前序遍历:中 -> 左 -> 右 顺序的遍历,可以先压右再压左
现要实现后序遍历:左 -> 右 -> 中 顺序的遍历,
我们不妨先实现 中 -> 右 -> 左 顺序的这样一个后序遍历的逆序,
那么根据前序遍历,我们可以先压左再压右,来实现这个 中 -> 右 -> 左 顺序
在打印的时候,我们不打印,而是添加到栈中。
又因为栈依次弹出栈顶可以实现某种顺序的逆序,这样,我们就实现了左 -> 右 -> 中 顺序

在这里插入图片描述

测试结果及代码

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
	void pre(TreeNode *head) {
		if (head == NULL)
			return;
		stack<TreeNode*> stk;
		stk.push(head);
		while (!stk.empty()) {
			head = stk.top();
			cout << head->val << " ";
			stk.pop();
			if (head->right != NULL)
				stk.push(head->right);
			if (head->left != NULL)
				stk.push(head->left);
		}
	}

	void in(TreeNode *head) {
		if (head != NULL) {
			stack<TreeNode*> stk;
			while (!stk.empty() || head != NULL) {
				if (head != NULL) {
					stk.push(head);
					head = head->left;	// 当前结点会把自己的左边全部压栈
				}
				else {
					head = stk.top();
					stk.pop();
					cout << head->val << " ";
					head = head->right;
				}
			}
		}
	}

	void pos(TreeNode *head) {
		if (head != NULL) {
			stack<TreeNode*> stk1;
			stack<TreeNode*> stk2;
			stk1.push(head);
			while (!stk1.empty()) {
				head = stk1.top();
				stk1.pop();
				stk2.push(head);
				if (head->left != NULL)
					stk1.push(head->left);
				if (head->right != NULL)
					stk1.push(head->right);
			}
			while (!stk2.empty()){
				cout << stk2.top()->val << " ";
				stk2.pop();
			}
		}
	}

	void preOrder(TreeNode *head) {
		if (head != NULL) {
			cout << head->val << " ";
			preOrder(head->left);
			preOrder(head->right);
		}
	}
	void inOrder(TreeNode *head) {
		if (head != NULL) {
			inOrder(head->left);
			cout << head->val << " ";
			inOrder(head->right);
		}
	}
	void posOrder(TreeNode *head) {
		if (head != NULL) {
			posOrder(head->left);
			posOrder(head->right);
			cout << head->val << " ";
		}
	}
};

int main(int argc, char* argv[]){

	TreeNode *head = new TreeNode(3);
	head->left = new TreeNode(2);
	head->left->left = new TreeNode(1);
	head->right = new TreeNode(4);
	head->right->left = new TreeNode(5);
	head->right->right = new TreeNode(6);

	Solution s;
	cout << "递归前序遍历  :";
	s.preOrder(head);
	cout << endl;
	cout << "非递归前序遍历:";
	s.pre(head);
	cout << endl;

	cout << "递归中序遍历  :";
	s.inOrder(head);
	cout << endl;
	cout << "非递归中序遍历:";
	s.in(head);
	cout << endl;

	cout << "递归后序遍历  :";
	s.posOrder(head);
	cout << endl;
	cout << "非递归后序遍历:";
	s.pos(head);
	cout << endl;
	return 0;
}```


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值