遍历二叉树(必背的七个算法)

遍历二叉树(必背的七个算法)

    遍历二叉树是以一定规则将二叉树中结点排列成一个线性序列,实质是对一个非线性结构进行线性化操作。

(1)前序遍历的递归实现

void PreOrder(BiTree bt)/*前序遍历二叉树bt*/

{ if (bt==NULL) return;   /*递归调用的结束条件*/

Visit(bt->data);      /*访问结点的数据域*/

  PreOrder(bt->lchild); /*前序递归遍历bt的左子树*/

PreOrder(bt->rchild); /*前序递归遍历bt的右子树*/  

}

(2)中序遍历的递归实现

void InOrder(BiTree bt) /*中序遍历二叉树bt*/

{ if (bt==NULL) return;   /*递归调用的结束条件*/

InOrder(bt->lchild);  /*中序递归遍历bt的左子树*/

Visit(bt->data);      /*访问结点的数据域*/

InOrder(bt->rchild);  /*中序递归遍历bt的右子树*/  

}

(3)后序遍历的递归实现

void PostOrder(BiTree bt)/*后序遍历二叉树bt*/

{ if (bt==NULL) return;    /*递归调用的结束条件*/

PostOrder(bt->lchild); /*后序递归遍历bt的左子树*/

PostOrder(bt->rchild); /*后序递归遍历bt的右子树*/  Visit(bt->data);       /*访问结点的数据域*/

}

(4)层序遍历的实现

一维数组Queue[MAX_TREE_SIZE]用以实现队列,变量front和rear分别表示当前对队首元素和队尾元素在数组中的位置。

void LevelOrder(BiTree bt)    /*层序遍历二叉树bt*/

{BiTree Queue[MAX_TREE_SIZE];

 int front,rear;

 if (bt==NULL) return;

 front=-1;

 rear=0;

 queue[rear]=bt;

while(front!=rear)

 {Visit(queue[++front]->data); /*访问队首结点数据域*/

  if (queue[front]->lchild!=NULL)  /*将队首结点的左孩子结点入队列*/

{ queue[++rear]=queue[front]->lchild;

}

  if (queue[front]->rchild!=NULL)   /*将队首结点的右孩子结点入队列*/

{queue[++rear]=queue[front]->rchild;

}

  }

}

(5)前序遍历的非递归实现

二叉树以二叉链表存放,一维数组stack[MAX_TREE_SIZE]用以实现栈,变量top用来表示当前栈顶的位置。

void NRPreOrder(BiTree bt)/*非递归先序遍历二叉树*/

{ BiTree stack[MAX_TREE_SIZE],p;

 int top;

 if (bt==NULL) return;

top=0;

p=bt;

while(!(p==NULL&&top==0))

while(p!=NULL)

Visit(p->data);          /*访问结点的数据域*/

   if(top< MAX_TREE_SIZE-1)/*将当前指针p压栈*/

     {stack[top++]=p;

}

   else {printf(栈溢出);

         return;

}

  p=p->lchild;        /*指针指向p的左孩子结点*/

 }

     if (top<=0) return;   /*栈空时结束*/

     else{ p=stack[- -top];/*从栈中弹出栈顶元素*/

p=p->rchild;    /*指针指向p的右孩子结点*/

}

}

}

(6)中序遍历的非递归实现

只需将先序遍历的非递归算法中的Visit(p->data)移到p=stack[- -top]和p=p->rchild之间即可。

(7)后序遍历的非递归实现

后序遍历与先序遍历和中序遍历不同,在后序遍历过程中,结点在第一次出栈后,还需再次入栈,也就是说,结点要入两次栈,出两次栈,而访问结点是在第二次出栈时访问。因此,为了区别同一个结点指针的两次出栈,设置一标志flag,令:

                      

    flag=1  第一次出栈,结点不能访问  ; flag=2  第二次出栈,结点可以访问

当结点指针进、出栈时,其标志flag也同时进、出栈。因此,可将栈中元素的数据类型定义为指针和标志flag合并的结构体类型。定义如下:

typedef struct {

  BiTree  link;

  int  flag;

}stacktype;

后序遍历二叉树的非递归算法如下。在算法中,一维数组stack[MAX_TREE_SIZE]用于实现栈的结构,指针变量p指向当前要处理的结点,整型变量top用来表示当前栈顶的位置,整型变量sign为结点p的标志量。

void NRPostOrder(BiTree bt) /*非递归后序遍历二叉树bt*/

{ stacktype stack[MAX_TREE_SIZE];

BiTree p;

int top,sign;

if (bt==NULL) return;

top=-1;                         /*栈顶位置初始化*/

p=bt;

while (!(p==NULL && top==-1))

{ if (p!=NULL)                 /*结点第一次进栈*/

stack[++top].link=p;

  stack[top].flag=1;

  p=p->lchild;              /*找该结点的左孩子*/

 }

 else{ p=stack[top].link;

    sign=stack[top- -].flag;

    if (sign==1)            /*结点第二次进栈*/

      { stack[++top].link=p;

        stack[top].flag=2;  /*标记第二次出栈*/

        p=p->rchild;

       }

    else { Visit(p->data); /*访问该结点数据域值*/

           p=NULL;

         }

    }

}

}

你可能感兴趣的:(二叉树)