二叉树的先序,中序,后序实现(递归/非递归)
了解了二叉树的构造
知道如何遍历树才能满足查找的需求
这里介绍三种遍历:
先序遍历 根-》左-》右
中序遍历 左-》根-》右
后序遍历 左-》右-》根
typedef struct TreeNode * BinTree;
typedef BinTree Position;
typedef int ElementType;
struct TreeNode{
ElementType d;
BinTree Left;
BinTree Right;
};
用递归的方式非常容易实现先序中序后序的遍历
先序–递归
void PreOrderTraversal(BinTree BT){
if(BT){
printf("%d",BT->d);
PreOrderTraversal(BT->Left);
PreOrderTraversal(BT->Right);
}
}
中序–递归
void InOrderTraversal(BinTree BT){
if(BT){
InOrderTraversal(BT->Left);
printf("%d",BT->d);
InOrderTraversal(BT->Right);
}
}
后序–递归
void PostOrderTraversal(BinTree BT){
if(BT){
PostOrderTraversal(BT->Left);
PostOrderTraversal(BT->Right);
printf("%d",BT->d);
}
}
以上是通过递归实现
我们可以发现这种其实很好记
只要记住顺序,在上述口诀的根处打印即可~
然而
我们秉着生存之道还要了解非递归的实现
谁叫面试题考呢。。。
非递归–先序
void PreOrderTraversal(BinTree BT){
BinTree T = BT;
Stack s = CreateStack();
while(T || !IsEmpty(s)){ //树不空或者栈不空
while(T){
printf("%d",T->d); //树不空
Push(T->d,s);
T = T->Left;
}
if(!IsEmpty(s)){ //栈不空
T = Pop(s);
T = T->Right;
}
}
}
非递归–中序
void InOrderTraversal(BinTree BT){
BinTree T = BT;
Stack s = CreateStack();
while(T || !IsEmpty(s)){ //树不空或者栈不空
while(T){ //树不空
Push(T->d,s);
T = T->Left;
}
if(!IsEmpty(s)){ //栈不空
T = Pop(s);
printf("%d",T->d);
T = T->Right;
}
}
}
非递归–后序
void PostOrderTraversal(BinTree BT){
BinTree T = BT,p = NULL;
Stack s = CreateStack();
while(T || !IsEmpty(s)){ //树不空或者栈不空
while(T){ //树不空
Push(T->d,s);
T = T->Left;
}
if(!IsEmpty(s)){ //栈不空
T = Pop(s);
}
if(T->Right == p || T->Right == NULL){
printf("%d",T->d);
p = T;
T = NULL;
}
else{
Push(T->d,s);
T = T->Right;
}
}
}
这里我们可以通过观察
发现先序遍历和中序遍历的非递归代码很相近
其中的差别就是调整了printf的位置
中序遍历在Pop之后
而先序遍历在第一次访问也就是Push之前
所以要背也是很容易的
还是要在理解的基础上啦
而后序遍历时还要判断有无右子树
如果有右子树则仍要入栈,反之才能打印,
因为后序遍历的顺序是左-》右-》根
明天继续学习有关树的知识~
晚安啦~