二叉树遍历的非递归实现
Posted wj_hubei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树遍历的非递归实现相关的知识,希望对你有一定的参考价值。
二叉树的构建使用的是链表的形式,每个节点中既包含了根节点的元素,也包含了指向左右孩子的指针,实际可以看成一个二维的线性结构。
二叉树的遍历实质就是就二维变为一维的过程。
前序遍历的递归思想是:
首先访问根节点
然后以左子树为根节点递归调用遍历函数,(这样就沿着树的最左边的分支遍历到最左边的叶子节点)
接着以右子树为根节点递归调用遍历函数,(这样就逐层回到调用的根节点,然后递归根节点的右节点)
中序与后序的递归遍历思想一样,只是访问根节点的先后顺序不一样
以中序遍历为例实现递归遍历
templte <class T>
void preOrder(binarytTreeNode<T> *t)
{
if(t!=NULL)
{
visit(t); //访问根节点
preOrder(t->leftChild); //前序遍历左子树
preOrder(t->rightChild); //前序遍历右子树
}
}
非递归实现二叉树的思想是使用堆栈来实现的
实际上,无论是前序、中序还是后序遍历,其在树中所走的路劲的顺序都是一样的。都是先指到根节点,然后指到左子树最后指到右子树,只是不同的遍历,在访问左右子树和根节点的顺序不同而已。
那么就可以使用堆栈来实现非递归的遍历
首先当指到根节点时,将其压入堆栈,然后指向其左子树,如果左子树非空,也将其入栈,这样就到达最左边的叶子节点
然后从栈中依次取出每个“根节点”
最后再指向这些“根节点”的右子树
以上根节点打双引号是因为实际上是将左右节点在某个位子看成了根节点,实际上在遍历构成中,不同的根节点也正是这些左右节点,利用堆栈就是使各左右节点在合适的位置成为根节点。
对于不同的遍历,只是访问访问“根节点”的顺序不同,便可得到不同遍历的非递归遍历方法如下:
前序遍历:
当遇到一个节点就访问它并将其压入栈中,然后遍历其左子树
当左子树遍历结束后,从栈顶弹出这个节点
然后指向其右子树再按前序遍历
其实现如下:
void preOrder(binaryTreeNode<T> t)
{
binaryTreeNode tmp=t;
Stack S=CreatStack(size); //伪代码,创建一个长度为size的栈
while(!T.empty || !empty(S)) //只要树和栈非空
{
while(!T.empty) //一直向左并将沿途的节点压入栈中
{
visit(T); //访问T
push(S,T); //将T压入栈
T=T->leftchild;
}
if(empty(S))
{
T=pop(S); //将节点弹出堆栈
T=T->rightchild; //转向右子树
}
}
}
中序遍历:
当遇到一个节点就将其压入栈中,然后遍历其左子树
当左子树遍历结束后,从栈顶弹出这个节点并访问它
然后指向其右子树再按中序遍历
void inOrder(binaryTreeNode<T> t)
{
binaryTreeNode tmp=t;
Stack S=CreatStack(size); //伪代码,创建一个长度为size的栈
while(!T.empty || !empty(S)) //只要树和栈非空
{
while(!T.empty) //一直向左并将沿途的节点压入栈中
{
push(S,T); //将T压入栈
T=T->leftchild;
}
if(empty(S))
{
T=pop(S); //将节点弹出堆栈
visit(T); //访问T
T=T->rightchild; //转向右子树
}
}
}
以上是关于二叉树遍历的非递归实现的主要内容,如果未能解决你的问题,请参考以下文章