二叉树的遍历(递归,非递归实现)
二叉树的遍历(递归,非递归实现)
二叉树的遍历是一些动态查找的基础,也是数据结构中的重要知识点。最近有时间重新回顾一个这几种常见的遍历方式。若有不对之处,请批评指正。
0.什么是二叉树
二叉树其实不难理解,有这官方的定义。要是你对普通的树型结构有所了解的话,二叉树其实是一颗特殊的树,它有着自己的特别。
- 每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。
- 左右子树都是有顺序的,且次序不能颠倒。
1.二叉树的遍历(递归)
最基本的二叉树的遍历,有前序,中序,后序遍历。而递归的实现方式也是大家最常见的一种实现方式。面对递归对于一些初学者来说还是有一些困难的。但是只要你宏观的逻辑是上走同即可。
下面看看前序遍历。所谓的前序遍历则是,根,左节点,右节点。
像上图上的二叉树,前序遍历的结果是 A B D E C
这样写一个递归的遍历则就是,先访问根节点,再访问左节点,再试右节点
public void perOrder(BtNode p){
//判断二叉树是否空
if(p!=null){
visit(p);
perOrder(p->lchild);
perOrder(p->rchild);
}
}
剩下的中序和后序遍历则就比较好理解了。
下面直接附代码:
//中序遍历
public void inOrder(BtNode p){
//判断二叉树是否空
if(p!=null){
inOrder(p->lchild);
visit(p);
inOrder(p->rchild);
}
}
//后序遍历
public void postOrder(BtNode p){
//判断二叉树是否空
if(p!=null){
postOrder(p->lchild);
postOrder(p->rchild);
visit(p);
}
}
2.二叉树的遍历(非递归)
非递归的遍历呢,则就是自己实现系统栈所做的工作。上面讲的递归遍历其实还是有问题的,要是二叉树比较深,在递归的时候就容易出现栈的溢出。非递归的算法相比于递归的算法来讲,效率上也是好一些的。
先说一个前序遍历吧。
再来回顾一个啥是前序遍历呀,就是根,左节点,右节点。现在做的是非递归,显然,我们需要一个其他的数据结构那就是栈。该如何利用栈呢。
是这么操作的。先将根节点入栈。当栈不空的时候,栈顶节点出栈,若存在右节点,让右节点入栈。若左节点存在,让左节点入栈。往复循环这个过程。这样就可以。代码如下:
public void preOrderNorRecun(BtNode p){
BTNode* stack[maxSize] ;
int top = -1;
BtNode q;
if(P!=null){
stack[++top] = p;
while(top!=-1){
q = stack[top--];
if(p->rchild != null){
stack[++top] = p->rchild;
}
if(p->lchild != null){
stack[++top] = p->lchild;
}
}
}
}
在就是中序遍历。其实操作上都是通过栈来进行的,只是在步骤上有所不同罢了。
步骤是这样子的。先将根节点入栈,然后若左节点一直不为空的话,就一直入栈。当没有左节点就让这个节点指向右节点。继续进行上面的步骤。
public void inOrderNorRecu(BtNode p){
BtNode* stack[maxSize];
int top = -1;
while(top!= -1 || p != null){
while(p->lchild != null){
stack[++top] = p;
p = p->lchild;
}
if(top != -1){
q = stack[top--];
visit(q);
p = p->rchild;
}
}
}
最后就是后序遍历的非递归了,其实后序遍历的非递归还是比较复杂的,这里采用一种双栈的方式简化一下这个算法。
要是你比较细心就会发现这么一个规律。后序遍历的倒序和把左右子树颠倒的前序遍历是一致的
上面的二叉树的后序遍历是 D E B C A。倒序为 A C B E D。
把上面的二叉树左右子树颠倒,进行前序遍历为,A C B E D。这样就和后序遍历的倒序是一致的。这样我们就是借鉴前序非递归的代码,进行编写了。
思路是这样子的,定义两个栈。一个栈做遍历顺序,一个栈放出第一个栈的结点。这个和前序非递归的非常相似的。先将根节点入栈。当栈不为空的时候,将栈顶结点出栈,并入第二个栈。然后若左节点不是为空,入栈。右节点不为空,入栈。最后将第二个栈的结点依次出栈则为 后序遍历的结果。代码如下:
public void postOrderNorRecu(BtNode p){
BtNode* stack1[maxSize];int top1 = -1;
BtNode* stack2[maxSize];int top2 = -1;
BtNode *q;
if(p!=null){
stack1[++top1] = p;
while(top1 != -1){
q = stack1[top1--];
stack2[++top2] = q;
if(p->lchild != null){
stack1[++top1] = p->lchild;
}
if(p->rchild != null){
stack1[++top1] = p->rchild;
}
}
while(top2 != -1){
q = stack2[top--];
visit(q);
}
}
}
if(p->rchild != null){
stack1[++top1] = p->rchild;
}
}
while(top2 != -1){
q = stack2[top--];
visit(q);
}
}
}

浙公网安备 33010602011771号