二叉树一阶遍历非递归算法的实现

二叉树一阶遍历非递归算法的实现
在前一篇文章中,我们讨论了两叉树的递归遍历算法(两棵树的第一根的改进)。本文主要讨论了两叉树的非递归算法,并使用了堆栈结构。

非递归算法的思想概括如下:

1)堆栈,是节点堆栈,然后是节点访问。

2),循环遍历当前节点,直到左边的子节点没有节点。

3)if节点的右子为true,转为1),并继续遍历,或从当前节点到父节点遍历到1)。

首先看符合这个想法的算法:

复制代码代码如下所示:
Int PreOrderTraverseNonRecursiveEx(const BiTree t,int(* visitnode)(telemtype数据))
{
如果(t = NULL)
{
返回- 1;
}

BiTNode * pbinode = T;
sqstack S;
InitStack(S);
推(S(SElemType)T);

而(!IsStackEmpty(S))
{
而(pbinode)
{
VisitNode(pbinode ->数据);
如果(pbinode!= T)
{
推(S,(SElemType)pbinode);
}
pbinode = pbinode ->左右;
}
如果(pbinode = null)
{
流行(S,(SElemType)pbinode);
}
如果(pbinode -> rchild = null)
{
流行(S(SElemType)pbinode); / /如果栈为空,有一个问题
}
pbinode = pbinode -> rchild;
}

返回0;
}

注意:1)这里使用堆栈结构来查看存储在前一个序列结构中的堆栈。

2)在这里,节省节点的时候,我保存的指针是节点的地址,它是int类型存储在流行时有使用指针,所以pbinode,但不pbinode,为什么指针使用你自己的想法,最好的理解是Bitnode * pbinode;定义BiTree pBiNode容易理解。
上面的算法实际上是错误的!为什么在这里我检查了很长时间。在很长一段时间里,也有一个无限循环。它还表明,当我从左边树离开时,右子树没有显示出来。最后,我修改了第一个判断条件。为什么因为如果堆栈在弹出后是空的,但是右边的子树不能继续,我写这个并没有太多的验证,后来解释说,没有压力进入空指针,看到在一个空指针中的例子是左边的子树是空的,当它被压入堆栈时,如下所示:

复制代码代码如下所示:
Int PreOrderTraverseNonRecursive(const BiTree t,int(* visitnode)(telemtype数据))
{
如果(t = NULL)
{
返回- 1;
}

BiTNode * pbinode = T;
sqstack S;
InitStack(S);
推(S(SElemType)T);

而(!IsStackEmpty(S))
{
GetTop(,(SElemType)pbinode);
而(pbinode)
{
VisitNode(pbinode ->数据);
pbinode = pbinode ->左右;
推(S,(SElemType)pbinode);
}
如果(pbinode = null)
{
流行(S,(SElemType)pbinode);
}
如果(!IsStackEmpty(S))
{
流行(S,(SElemType)pbinode);
pbinode = pbinode -> rchild;
推(S,(SElemType)pbinode);
}
}

返回0;
}
这是第一次,压到根节点,然后确定左子树是空的,不是空栈,或退出而空节点将确定当前栈后,栈为空,如果非空栈将父节点,然后确定合适的儿童,按右子节点,然后确定左孩子的右子树为空,继续循环。

有两个浪费的地方:一是推动空的子节点进栈,和两是公司把栈顶的频繁使用。
看这里回到算法的设计之初,没有压力为空指针或空的子节点,但没有完整的输出,在这里我们认为可以加入判断栈,当前节点是空的,所以不会出现不显示左子树节点出口不能显示右子树节点的尴尬:

复制代码代码如下所示:
第一次遍历非递归二叉树
Int PreOrderTraverseNonRecursiveEx(const BiTree T,
Int(* visitnode)(telemtype数据))
{
如果(t = NULL)
{
返回- 1;
}

BiTNode * pbinode = T;
sqstack S;
InitStack(S);
推(S(SElemType)T);

而(!IsStackEmpty(S)pbinode | |)/主要修改的是这句话
{
而(pbinode)
{
VisitNode(pbinode ->数据);
如果(pbinode!= T)
{
推(S,(SElemType)pbinode);
}
pbinode = pbinode ->左右;
}
如果(pbinode = null)
{
流行(S,(SElemType)pbinode);
}
如果(pbinode -> rchild = null)
{
流行(S(SElemType)pbinode); / /如果栈为空,有一个问题
}
pbinode = pbinode -> rchild;
}
返回0;
}
在第一个while循环连接之后,测试用例类似于两叉树一阶遍历:
输入数据仍然是1234007800,测试结果如下:
---双树-
请输入BiTree Node数据:
十二
请输入BiTree Node数据:
三十四
请输入BiTree Node数据:

请输入BiTree Node数据:

请输入BiTree Node数据:
七十八
请输入BiTree Node数据:

请输入BiTree Node数据:

十二万三千四百七十八

这还不足以测试,看看下面两棵分叉的树。

此时输入的数据应该是:1234240050007837 000,测试结果如下:

---双树-
请输入BiTree Node数据:
十二
请输入BiTree Node数据:
三十四
请输入BiTree Node数据:
二十四
请输入BiTree Node数据:

请输入BiTree Node数据:

请输入BiTree Node数据:
五十
请输入BiTree Node数据:

请输入BiTree Node数据:

请输入BiTree Node数据:
七十八
请输入BiTree Node数据:
三十七
请输入BiTree Node数据:

请输入BiTree Node数据:

请输入BiTree Node数据:

一千二百三十四亿二千四百五十万七千八百三十七

从一阶遍历,我们可以看出该算法是正确的。此外,这些算法不仅是前序遍历。如果我们想成为中间顺序或后序,我们只需要先从上面的算法中删除访问,然后把它添加到正确的位置
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部