二叉树的四大遍历方法
顺序-先序-中序-后序*
一、顺序:按照二叉树的至上而下,从左至右的顺序依次访问结点。
例:ABCDEFGHI
代码实现
结构体,双链表式,下面同
//二叉链表的存储方式
typedef struct TNode{
int data;
struct TNode *Lchild;
struct TNode *Rchild;
}TNode,*BiTree;
①顺序遍历的实现:用队列来实现,进队后再访问。 通过访问队头并将队头结点的左右孩子依次入队。循环遍历队列。
//顺序遍历实现 入队后访问
void LevelOrder(BiTree T){
//借助队列来实现
/*
根入队,遍历队列:输出队头,如果队头有左孩子那么左孩子入队,如果有右孩子那么右孩子入队。
*/
InitQueue(Q);//初始化空队列
BiTree p = T;//p指向树根
EnQueue(Q,p);//根入队
while(!isEmptyQueue(Q)){
DeQueue(Q,p);//出队
visit(p->data);//访问
if(p->Lchild){//有左孩子 -入队
EnQueue(Q,p->Lchild);
}//end-if
if(p->Rchild){//有右孩子 -入队
EnQueue(Q,p->Rchild);
}//end-if
}//end-while
}//end-function
二、先序遍历: 根-左-右
例:ABDEGHCFI
①先序遍历递归是实现:
//先序遍历的递归实现
void PreOrder2(BiTree T){
//根-左-右
if(T){
visit(T->data);
PreOrder2(T->Lchild);
PreOrder2(T->Rchild);
}//end-if
}//end-function
②先序遍历非递归实现:用栈来过度。先访问再入栈
//先序遍历的非递归实现,入栈前访问
void PreOrder(BiTree T){
//借助栈来实现
/*
访问根结点,并入栈,遍历左并入栈,直到为空,再遍历栈顶的右,-循环
*/
InitStack(S);//初始化空栈
BiTree p = T;//p指向树根,下面对p操作
while(p || !isEmptyStack(S)){
if(p){//如果不为空,将左边的依次入栈
visit(p->data);//访问结点
Push(S,p);//入栈
p = p->Lchild;
}//end-if
else{//没有左孩子的时候
Pop(S,p);//出栈,但不访问
p = p->Rchild;//第一遍是遍历最后一个的右子树
}//end-else
}//end-while
}//end-function
三、中序: 左-根-右
例:DBGEHAFIC
①中序遍历递归实现:
//中序遍历的递归实现
void InOrder2(BiTree T){
//左-根-右
if(T){
InOrder(T->Lchild);
visit(T->data);
InOrder(T->Rchild);
}//end-if
}//end-function
②中序遍历非递归实现:
//中序遍历的非递归实现 入栈后访问
void InOrder(BiTree T){
//左-根-右
InitStack(S);//初始化空栈
BiTree p = T;//p指向树根,下面对p操作
while(p || !isEmptyStack(S)){
if(p){
Push(S,p);//入栈p
p = p->Lchild;//左
}//end-if
else{
Pop(S,p);//出栈p
visit(p->data);//访问之
p = p->Rchild;//右
}//end-else
}//end-while
}//end-function
四、后序: 左-右-根
例:DGHEBIFCA
①后序遍历递归实现:
//后序遍历的递归实现
void PostOrder2(BiTree T){
if(T){
PostOrder2(T->Lchild);
PostOrder2(T->Rchild);
visit(T->data);
}//end-if
}//end-function
②后序遍历非递归实现:需要判断是否右孩子是否已经访问过。
//后序遍历的非递归实现 入栈后访问
void PostOrder(BiTree T){
//
InitStack(S);//初始化空栈
BiTree p = T;//p指向树根,下面对p操作
BiTree r = NULL;//设定一个指针,指向刚访问过的结点
while(p || !isEmptyStack(S)){
if(p){
Push(S,p);//入栈
p = p->Lchild;//左
}//此时p为NULL
else{
GetTop(S,p);//获得栈顶,既是最后一个没有左孩子的结点
if(p->Rchild && p->Rchild != r){
//结点有右孩子,且未访问过
Push(S,p);//入栈
p = p->Rchild;//右-下个循环访问它的左
}//end-if
else{
//没有右孩子或右孩子已经访问过
Pop(S,p);//出栈
visit(p->data);//访问
r = p;//指向刚访问的结点
p = NULL;//置空,下个循环从栈顶开始
}//end-else
}//end-else
}//end-if
}//end-function
非递归时用栈来过度,着实不错!! 当然顺序遍历用队列来操作方便