二叉树遍历之迭代遍历

前文我们简述了 二叉树遍历之递归遍历

其实用到的是递归中自己的栈来完成的,那么我们要是用迭代的话也是要通过自己的栈来完成

前序遍历:根 左 右

我们在递归遍历时通过前序遍历的原理图示展示了整个过程:

根节点第一次出栈就可以打印了,然后再来分别出栈左右子节点

void preorderIteration(struct TreeNode* root, MyStack *stk)
{
	if(root == NULL)
		return;
		
	myStackPush(stk, root);
	
	while( ! myStackEmpty(stk) )
	{
		root = myStackTop(stk);
		myStackPop(stk);
		printf("val=%d\n", root->val);
		
		if(root->right)
			myStackPush(stk, root->right);
		
		if(root->left)
			myStackPush(stk, root->left);	
	}
}

中序遍历:左 根 右

我们遇见左节点时还要看有没有左子节点,一直要到最左边的叶子为止

所以根节点先入栈,然后持续对左子节点压栈,直到左子节点为NULL,这个时候就可以出栈左子节点,打印其值

左边节点值打印完成,如果其没有右子节点,那么再出栈的话就是其父节点(根)

如果有右子节点,那么该左节点视为子树的根节点,对右子树进行重复逻辑

void inorderIteration(struct TreeNode* root, MyStack *stk)
{
	if(root == NULL)
		return;
	
	while(! myStackEmpty(stk) || root != NULL)
	{
		if(root != NULL)
		{
			myStackPush(stk, root);
			root = root->left;
		}
		else
		{
			root = myStackTop(stk);
			myStackPop(stk);
			printf("val=%d\n", root->val);
			
			root = root->right;
		}
	
	}
}

1. 依次入栈根,左子节点,直到没有左子节点

2. 出栈,节点 4 没有右子节点,再出栈就是其父节点 2,同样节点 2也没有右子节点,再出栈就是节点 1

3. 节点 1 有 右子节点,那么就开始处理右子树,整个过程逻辑一样

 

后序遍历:左,右,根

与前面两种方式不一样,我们在处理完左树后,根节点还不能打印

除非根节点没有右子树,或者右子树已经被打印了,才能打印根节点

所以根节点会进行二次入栈,当第二次出栈的时候通过比较临时节点变量(保存压栈时的根节点)与当前根节点是否一样,一样表示已经处理完,这个时候就能够打印当前根节点

void postorderIteration(struct TreeNode* root, MyStack *stk)
{
	if(root == NULL)
		return;
		
	struct TreeNode* prev = NULL;
	
	while(! myStackEmpty(stk) || root != NULL)
	{
		while(root != NULL)
		{
				myStackPush(stk, root);
				root = root->left;
		}
		
		root = myStackTop(stk);
		myStackPop(stk);
		
		if(root->right == NULL || root->right == prev)
		{
			printf("val=%d\n", root->val);
			prev = root;
			root = NULL;
		}
		else
		{
			myStackPush(stk, root);
			root = root->right;
		}
	}	
	
}

1. 根节点开始压栈,完成左子节点的压栈

2. 出栈,节点 4 没有右子节点,可以打印值,继续出栈节点 2,也没有右子节点打印值

3. 节点 1 出栈后发现右右子节点,并且右子节点还未处理,第二次压栈

4. 处理节点 1 的右子树,逻辑一样。节点 3 同样进行了 二次压栈

5. 继续处理右子节点直至完成后才可以打印 根节点

 

更多数据结构详解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值