数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)

目录

中序遍历

代码实现 

思路图解 

先序遍历 

代码实现 

后序遍历 

思路图解


二叉树的非递归遍历运用到堆栈

中序遍历

循环的思路是

  1. 遇到一个节点,就把它压栈,并去遍历它的左子树。
  2. 当左子树遍历结束之后,从栈顶弹出这个节点并访问它。
  3. 然后按其右指针再去按中序的遍历循环去遍历该节点的右子树。

代码实现 

void InOrderTraversal(BinTree BT)
{
	BinTree T = BT;
	Stack S = CreatStack();  //创建并初始化堆栈S
	while (T || !IsEmpty(S))        //节点和栈都为空时才停止循环
	{
		while (T)                   //一直向左并将沿途节点压入堆栈
		{
			Push(S, T);       
			T = T->Left;
		}
		if (!IsEmpty(S))            //当遇到左子树为空时,进行出栈
		{
			T = Pop(S);             //弹出栈顶元素
			printf("%5d", T->data); //访问栈顶元素
			T = T->Right;           //转向右子树
		}
	}
}

思路图解 

数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)_第1张图片

 

从中序非递归遍历的代码上,可以将压栈时看做是第一次经过节点,将出栈是看做是第二次经过节点。所以结合之前学的递归遍历, 中序的非递归遍历代码中,才会在出栈时(即第二次经过节点时)访问节点。

数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)_第2张图片

所以要写出先序的非递归遍历就比较简单了:

先序遍历 

数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)_第3张图片

将访问放在第一次经过节点时,就变成了先序的非递归遍历代码了。

代码实现 

void PreOrderTrversal(BinTree BT)
{
	BinTree T = BT;
	Stack S = CreatStack();  //创建并初始化堆栈S
	while (T || !IsEmpty(S))        //节点和栈都为空时才停止循环
	{
		while (T)                   //一直向左并将沿途节点压入堆栈
		{
			Push(S, T);
			printf("%5d", T->data); //访问栈顶元素
			T = T->Left;
		}
		if (!IsEmpty(S))            //当遇到左子树为空时,进行出栈
		{
			T = Pop(S);             //弹出栈顶元素
			T = T->Right;           //转向右子树
		}
	}
}

再看后序的非递归遍历,似乎上面的代码中只有第一次经过和第二次经过,没有第三次经过节点的了,所以不能在原来的基础上调整代码来实现后序非递归遍历了。

后序遍历 

要实现后序非递归遍历,可以借助两个堆栈,一个用于存储遍历的序列,另一个用于存储中间节点。

具体实现的思路:

  1. 初始化两个堆栈s1和s2,将根节点压入s1中。
  2. 从s1中弹出栈顶节点,将其压入s2中。
  3. 如果该节点有左子节点,则将左子节点压入s1中。
  4. 如果该节点有右子节点,则将右子节点压入s1中。
  5. 重复步骤2到步骤4,直到s1为空。
  6. 从s2中依次弹出节点并输出,即可得到后序遍历序列。

思路图解

 数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)_第4张图片


end 


学习自:MOOC数据结构——陈越、何钦铭 

你可能感兴趣的:(算法,数据结构,学习)