二叉树递归遍历+非递归(前序、中序、后序遍历)

递归遍历二叉树

#include <iostream>
#include <stack>
using namespace std;
struct tree
{
	int val;
	tree * left;
	tree * right;
};

//前序遍历
void RecursivePreTraverse(tree * root)
{
	//指明递归终止条件
	if (!root)
		return;
	printf("%d ", root->val);
	RecursivePreTraverse(root->left);
	RecursivePreTraverse(root->right);
}

//中序遍历
void RecursiveInterTraverse(tree * root)
{
	//指明递归终止条件
	if (!root)
		return;
	RecursiveInterTraverse(root->left);
	printf("%d ", root->val);
	RecursiveInterTraverse(root->right);
}

//后序遍历
void RecursivePostTraverse(tree * root)
{
	//指明递归终止条件
	if (!root)
		return;
	RecursivePostTraverse(root->left);
	RecursivePostTraverse(root->right);
	printf("%d ", root->val);
}

非递归后序遍历二叉树

#include <iostream>
#include <stack>
using namespace std;
struct tree
{
	int val;
	tree * left;
	tree * right;
};

void nonRecursivePostTraverse(tree * root)
{
	if (root == nullptr)
		return;
	stack<tree*>s;
	tree * last=nullptr; //last记录的是上一个出栈的元素(对应后序遍历而言,每一个出栈的元素都代表其左右子树都已处理完毕)

	//1 将从根节点开始的所有非空左子节点都入栈
	while (root != nullptr)
	{
		s.push(root);
		root = root->left;
	}

	//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点。如果右子节点为不空,重复1
	while (!s.empty())
	{
		tree* top = s.top();
		//后序遍历和前序、中序遍历的出栈时机不同,前、中是处理完左子树即可出栈,后是必须左右子树都处理完才能出栈
		//后序遍历,元素出栈的要求必须是左右子树都已经处理完毕,有三种情况
		//1 该节点的左子树、右子树均为空,都不需要处理,可以直接输出根节点
		//2 上一个出栈的元素(即左右子树已经处理完毕的元素)是该节点的右子节点,因为左节点处理在右节点之前,所以意味着当前节点的左右子树都已经处理完毕,可以直接输出
		//3 上一个出栈的元素是该节点的左子节点且右子节点为空时,说明当前节点的左子树已经处理完毕,右子树为空不需要处理,可以直接输出
		if (top->left == nullptr && top->right == nullptr
			|| last == top->right
			|| last == top->left && top->right == nullptr)
		{
			//后序遍历打印元素也是在元素出栈时
			printf("%d ",top->val);
			//判定符合出栈条件后,记得更新前一个出栈元素last
			last = top;
			s.pop();
		}
		else
		{
			//不满足出栈条件(即左右子树还未处理完毕),栈顶元素不出栈,获取其右子节点,重复1
			tree *t = top->right;
			while (t)
			{
				s.push(t);
				t = t->left;
			}
		}
	}
}

非递归前序遍历二叉树

#include <iostream>
#include <stack>
using namespace std;
struct tree
{
	int val;
	tree * left;
	tree * right;
};

void nonRecursivePreTraverse(tree * root)
{
	if (root == nullptr)
		return;
	stack<tree*>s;

	//1 将从根节点开始的所有非空左子节点都入栈
	while (root)
	{
		//前序遍历是在元素入栈前打印
		printf("%d ", root->val);
		s.push(root);
		root = root->left;
	}

	//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点,将该元素出栈。如果右子节点为不空,重复1
	while (!s.empty())
	{
		tree* top = s.top();
		tree *t = top->right;
		s.pop();
		while (t)
		{
			//前序遍历是在元素入栈前打印
			printf("%d ", root->val);
		    s.push(t);
			t = t->left;
		}
	}
}

非递归中序遍历二叉树

#include <iostream>
#include <stack>
using namespace std;
struct tree
{
	int val;
	tree * left;
	tree * right;
};

void nonRecursiveInterTraverse(tree * root)
{
	if (root == nullptr)
		return;
	stack<tree*>s;

	//1 将从根节点开始的所有非空左子节点都入栈
	while (root)
	{
		s.push(root);
		root = root->left;
	}

	//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点,将该元素出栈。如果右子节点为不空,重复1
	while (!s.empty())
	{
		tree* top = s.top();
		//中序遍历是在元素弹出时打印
		printf("%d ", top->val);
		tree *t = top->right;
		s.pop();
		while (t)
		{
		    s.push(t);
			t = t->left;
		}
	}
}
发布了90 篇原创文章 · 获赞 8 · 访问量 8240

猜你喜欢

转载自blog.csdn.net/weixin_43854189/article/details/103002709