二叉樹的遍歷

一、二叉樹的遍歷

二叉樹遍歷的概念: 二叉樹的遍歷是指按照一定次序訪問樹中所有節點,並且每個節點僅被訪問一次的過程。它是最基本的運算,是二叉樹中所有其他運算的基礎。

1.  先序遍歷過程

先序遍歷二叉樹的過程是:① 訪問根節點;②先序遍歷左子樹;③先序遍歷右子樹。

2.  中序遍歷過程

中序遍歷二叉樹的過程是: 中序遍歷左子樹; 訪問根節點;中序遍歷右子樹。

3.  後序遍歷過程

後序遍歷二叉樹的過程是: 後序遍歷左子樹;後序遍歷右子樹;訪問根節點。

4.  層次遍歷過程

層次遍歷二叉樹的過程是: ①訪問根節點(第1層)②按照從上到下、從左往右訪問第2到第h層所有節點


二、二叉樹遍歷遞歸算法

1.  先序遍歷的遞歸算法:

       void PreOrder(BTNode *b)
    {  if (b!=NULL)  
       {  printf("%c ",b->data); //訪問根節點
    PreOrder(b->lchild);
    PreOrder(b->rchild);
       }

  }

2.  中序遍歷的遞歸算法:

 void InOrder(BTNode *b)
 {  if (b!=NULL)  
    {  InOrder(b->lchild);
printf("%c ",b->data); //訪問根節點
InOrder(b->rchild);
    }

 }

3.  後序遍歷遞歸算法:

 void PostOrder(BTNode *b) 
 {  if (b!=NULL)  
    {  PostOrder(b->lchild);
PostOrder(b->rchild);
printf("%c ",b->data); //訪問根節點
    }

 }

三、二叉樹遍歷非遞歸算法 

1. 先序遍歷非遞歸算法

void PreOrder(BTNode *b)
{ BTNode *St[MaxSize],*p; int top=-1;
  top++; St[top]=b;      //根節點入棧
   while (top>-1)      //棧不爲空時循環
   {  p=St[top]; top--;    //退棧並訪問該節點
printf("%c ",p->data);
      if (p->rchild!=NULL)  //右孩子節點入棧
{  top++;  St[top]=p->rchild;   }
      if (p->lchild!=NULL)  //左孩子節點入棧
{   top++; St[top]=p->lchild; }
  } 

2. 中序遍歷非遞歸算法   

void InOrder(BTNode *b)
{  BTNode *St[MaxSize],*p; int top=-1;
   p=b;
   while (top>-1 || p!=NULL)
   {  while (p!=NULL) //掃描*p的所有左節點並進棧
{ top++; St[top]=p;
   p=p->lchild;
}
if (top>-1)
{  p=St[top];top--;       //出棧*p節點
          printf("%c ",p->data); //訪問之
    p=p->rchild;            //處理右子樹
    }
   }

3. 後序遍歷非遞歸算法 

void PostOrder(BTNode *b)
{  BTNode *St[MaxSize];BTNode *p;
   int flag,top=-1;  //棧指針置初值
   do
   {  while (b!=NULL)  //將*b的所有左節點進棧
      {  top++; St[top]=b;
    b=b->lchild;
}     
p=NULL;   //p指向棧頂節點的前一個已訪問的節點

flag=1;   //表示*b的左子樹已訪問或爲空  

 while (top!=-1 && flag==1)

   {  b=St[top];      //取出當前的棧頂元素
if (b->rchild==p)
{  printf("%c ",b->data);//訪問*b節點
    top--;p=b; //p指向則被訪問的節點
}
else
       {    b=b->rchild; //b指向右孩子節點
            flag=0; ///b的左子樹未訪問
       }     
   }
  } while (top!=-1);


例如,求一個節點的所有祖先節點假設二叉樹採用二叉鏈存儲結構,設計一個算法輸出從根節點到每個葉子節點的路徑之逆(因爲樹中路徑是從根節點到其他節點的節點序列,這裏就是求從葉子節點及其雙親節點、該雙親節點的雙親節點,直到根節點的序列,或者說求葉子節點及其所有祖先節點的序列)。

解:本例採用後序遍歷非遞歸算法。 

void AllPath(BTNode *b)
{  BTNode *St[MaxSize];
   BTNode *p;
   int flag,i,top=-1; //棧指針置初值
   if (b!=NULL)
   {  do
{ while (b!=NULL)//將*b的所有左節點進棧
   {  top++;
St[top]=b;
b=b->lchild;
   }
  p=NULL;

    flag=1;

    while (top!=-1 && flag)
    {  b=St[top];      //取出當前的棧頂元素
if (b->rchild==p)
{  if (b->lchild==NULL && b->rchild==NULL)
    {   //若爲葉子節點,輸出棧中所有節點值
for (i=top;i>0;i--)
   printf("%c->",St[i]->data);
printf("%c\n",St[0]->data);
    }
    top--;
    p=b; //p指向剛訪問過的節點
  }
  else
  {  b=b->rchild;       //b指向右孩子節點
     flag=0;
    }
}
    } while (top!=-1);
    printf("\n");
   } 

}


四、層次遍歷算法

層次遍歷算法採用一個環形隊列qu來實現

層次遍歷過程是:

先將根節點進隊,在隊不空時循環;

從隊列中出列一個節點*p,訪問它;

若它有左孩子節點,將左孩子節點進隊;若它有左孩子節點,將左孩子節點進隊。

如此操作直到隊空爲止。對應的算法如下:

void LevelOrder(BTNode *b)
{  BTNode *p;
   BTNode *qu[MaxSize]; //定義環形隊列,存放節點指針
   int front,rear; //定義隊頭和隊尾指針
   front=rear=-1; //置隊列爲空隊列
   rear++;
   qu[rear]=b; //根節點指針進入隊列
   while (front!=rear) //隊列不爲空
   {  front=(front+1)%MaxSize;
p=qu[front]; //隊頭出隊列
printf("%c ",p->data); //訪問節點
if (p->lchild!=NULL) //有左孩子時將其進隊
{  rear=(rear+1)%MaxSize;
   qu[rear]=p->lchild;
}
if (p->rchild!=NULL) //有右孩子時將其進隊
{  rear=(rear+1)%MaxSize;
   qu[rear]=p->rchild;
}

   } 



發佈了48 篇原創文章 · 獲贊 47 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章