(算法整理)二叉树的递归与非递归遍历算法

树形结构的考察在数据结构预算法中一直占有很重要的地位,二叉树的遍历一直是最基本的算法,众所周知,二叉树的遍历主要分为前序、中序、后序这三种,且三种遍历方式都存在递归与非递归两种形式,这里做一下整理与总结。

这里先定义一下二叉树结点的数据结构:

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

这里我们使用的树的形式如下:


构建这棵二叉树的代码实现如下:

TreeNode* constructBiTree() {
	TreeNode a(1);
	TreeNode b(2);
	TreeNode c(3);
	TreeNode d(4);
	TreeNode e(5);
	TreeNode f(6);

	a.left = &b;
	b.left = &c;
	a.right = &d;
	d.left = &e;
	d.right = &f;
	return &a;
}

(一)先序遍历(Pre-order)

递归定义:

void preorder_recursion(TreeNode* root) {
	if (!root) {
		return;
	}
	printf("%d", root->val);
	preorder_recursion(root->left);
	preorder_recursion(root->right);
}

非递归实现(使用一个栈s,每次遍历结点同时,将其非空右指针压入s):

void preorder_loop(TreeNode* root) {
	std::stack<TreeNode*> s;
	TreeNode* p = root;
	while (p || !s.empty())
	{
		if (p)
		{
			if (p->right) {
				s.push(p->right);
			}
			std::cout << p->val << "";
			p = p->left;
		}
		else
		{
			TreeNode *node = s.top();
			s.pop();
			p = node;
		}
	}
}

编写主程序如下:

int main() {
	TreeNode a(1);
	TreeNode b(2);
	TreeNode c(3);
	TreeNode d(4);
	TreeNode e(5);
	TreeNode f(6);

	a.left = &b;
	b.left = &c;
	a.right = &d;
	d.left = &e;
	d.right = &f;
	TreeNode* biTree = &a;

	printf("preorder: \n");
	preorder_recursion(biTree);
	printf("\n");
	preorder_loop(biTree);
	printf("\n");
	system("pause");
}

运行结果:


(二)中序遍历

递归实现:

void inorder_recursion(TreeNode* root) {
	if (!root)
	{
		return;
	}
	inorder_recursion(root->left);
	std::cout << root->val;
	inorder_recursion(root->right);
}

非递归实现(同样使用一个栈s):

void inorder_loop(TreeNode* root) {
	std::stack<TreeNode*> s;
	if (!root)
	{
		return;
	}
	TreeNode *p = root;
	while (p || !s.empty())
	{
		if (p)
		{
			s.push(p);
			p = p->left;
		}
		else
		{
			TreeNode* node = s.top();
			std::cout << node->val;
			s.pop();
			p = node->right;
		}
	}
}

主程序编写:

int main() {
	TreeNode a(1);
	TreeNode b(2);
	TreeNode c(3);
	TreeNode d(4);
	TreeNode e(5);
	TreeNode f(6);

	a.left = &b;
	b.left = &c;
	a.right = &d;
	d.left = &e;
	d.right = &f;
	TreeNode* biTree = &a;

	printf("inorder: \n");
	inorder_recursion(biTree);
	printf("\n");
	inorder_loop(biTree);
	printf("\n");
	system("pause");
}

运行结果:


(后序遍历)

递归实现:

void postorder_recursion(TreeNode* root) {
	if (!root)
	{
		return;
	}
	postorder_recursion(root->left);
	postorder_recursion(root->right);
	std::cout << root->val;
}

非递归实现:

(1)Push根结点到第一个栈s中。
(2)从第一个栈s中Pop出一个结点,并将其Push到第二个栈output中。
(3)然后Push结点的左孩子和右孩子到第一个栈s中。
(4)重复过程2和3直到栈s为空。
(5)完成后,所有结点已经Push到栈output中,且按照后序遍历的顺序存放,直接全部Pop出来即是二叉树后序遍历结果。

void postorder_loop(TreeNode* root) {
	if (!root)
	{
		return;
	}
	std::stack<TreeNode*> s, output;
	s.push(root);
	while (!s.empty())
	{
		TreeNode *node = s.top();
		s.pop();
		output.push(node);
		if (node->left)
		{
			s.push(node->left);
		}
		if (node->right)
		{
			s.push(node->right);
		}
	}
	while (!output.empty()) {
		TreeNode *node = output.top();
		std::cout << node->val;
		output.pop();
	}
}

主函数实现:

int main() {
	TreeNode a(1);
	TreeNode b(2);
	TreeNode c(3);
	TreeNode d(4);
	TreeNode e(5);
	TreeNode f(6);

	a.left = &b;
	b.left = &c;
	a.right = &d;
	d.left = &e;
	d.right = &f;
	TreeNode* biTree = &a;

	printf("postorder: \n");
	postorder_recursion(biTree);
	printf("\n");
	postorder_loop(biTree);
	printf("\n");
	system("pause");
}

运行结果:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值