一套模板实现二叉树的前中后序非递归遍历(C语言实现)简单易记

     本篇文章适合已经了解非递归前中后序遍历逻辑,且想寻找一个适用于三种遍历代码模板的小猿。 本文着重介绍一个模板对三种遍历的套用,对于遍历逻辑讲解粗略。

     对于二叉树的非递归遍历要比递归遍历复杂许多,但在企业和考研中却深受喜爱。那有没有一套模板可以同时掌握三种非递归遍历呢?其实非递归的前序和中序遍历比较相似,也比较简单,但后序遍历却大相径庭,尤其是在C语言实现后序遍历时,需要对指针进行反复操作,非常复杂。那么今天介绍一种方法,在掌握前序和中序遍历模板的同时,也掌握复杂的后序遍历。话不多说,直接上代码:

前序遍历

//计算树的结点数,目的是为保存遍历结果的数组匹配一个精确大小,该段代码可有可无
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
	int i = 0;
	int size = TreeSize(root);
	*returnSize = size;
	int *a;
	struct TreeNode*stack[100];
	int top = 0;
	a = (int *)malloc(sizeof(int)*size);
	if (root == NULL)
	{
		return NULL;
	}
	do
	{
		while (root)
		{
			a[i++] = root->val;//    标记处####
			stack[top++] = root;
			root = root->left;
		}
		if (top != 0)
		{
			root = stack[--top];
			root = root->right;
		}
	} while (top != 0 || root != NULL);
	return a;
}

中序遍历

//计算树的结点数,目的是为保存遍历结果的数组匹配一个精确大小,该段代码可有可无
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
	int size = TreeSize(root);
	*returnSize = size;
	struct TreeNode* stack[100];
	int *a;
	int i = 0;
	a = (int *)malloc(sizeof(int)*size);
	int top = 0;
	if (root == NULL)
	{
		return NULL;
	}
	do
	{
		while (root != NULL)
		{
			stack[top++] = root;
			root = root->left;
		}
		if (top != 0)
		{
			root = stack[--top];
			a[i++] = root->val;//    标记处###
			root = root->right;
		}
	} while (root != NULL || top != 0);
	return a;

}

         可以看出,前序遍历和中序遍历中只有标记处的代码做了顺序上的调整,其实也很好理解,前序遍历是在压栈时访问节点,而中序遍历是在出栈时访问节点。

后序遍历:

//计算树的结点数,目的是为保存遍历结果的数组匹配一个精确大小,该段代码可有可无
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
	int i = 0;
	int size = TreeSize(root);
	*returnSize = size;
	int *a;
	struct TreeNode*stack[100];
	int top = 0;
	a = (int *)malloc(sizeof(int)*size);
	if (root == NULL)
	{
		return NULL;
	}
	do
	{
		while (root)
		{
			a[i] = root->val;
			i++;
			stack[top++] = root;
			root = root->right;//     交换①
		}
		if (top != 0)
		{
			root = stack[--top];
			root = root->left;//      交换②
		}
	} while (top != 0 || root != NULL);
	for (int j = 0; j < i / 2; j++)//    结果转置操作
	{
		int temp = a[j];
		a[j] = a[i - j - 1];
		a[i - j - 1] = temp;
	}
	return a;
}

   后序遍历是在前序遍历的基础上更改得到的;前序:根左右               后序:左右根;

如果我们在前序遍历时交换左右节点的入栈顺序,前序遍历就从   根左右——>根右左,如果再转置一下,就从根右左——>左右根,也就变成了后序。

这就是将前序遍历代码中的两个入栈顺序颠倒,最后再转置一下结果即可。

总结:①前序遍历调整访问顺序得到中序遍历

           ②前序遍历调整入栈顺序,最后逆置得到后序遍历

也就是,只需记住前序遍历就可以掌握三种遍历顺序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值