程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> 數據結構-二叉樹的遍歷

數據結構-二叉樹的遍歷

編輯:DB2教程

數據結構-二叉樹的遍歷


中序遍歷二叉樹

1 遞歸算法
算法的遞歸定義是:
若二叉樹為空,則遍歷結束;否則
⑴ 中序遍歷左子樹(遞歸調用本算法);
⑵ 訪問根結點;
⑶ 中序遍歷右子樹(遞歸調用本算法)。

中序遍歷的遞歸算法

void  InorderTraverse(BTNode  *T)
{  if  (T==NULL)
         return; 
   InorderTraverse(T->Lchild) ;
visit(T->data) ;       /*   訪問根結點   */
InorderTraverse(T->Rchild) ;
 }  

2 非遞歸算法(略)
設T是指向二叉樹根結點的指針變量,非遞歸算法是:
若二叉樹為空,則返回;否則,令p=T
⑴ 當p不為空,p進棧, p=p->Lchild ;
⑵ 否則(即p為空),退棧到p,訪問p所指向的結點;
⑶ p=p->Rchild ,轉(1);
直到棧空為止。
算法實現:

#define MAX_STACK_SIZE 50
void  InorderTraverse( BTNode  *T)
{  BTNode  *Stack[MAX_STACK_SIZE ] ,*p=T ;
    int  top=0 , bool=1 ;
    if  (T==NULL)  printf(“ Binary Tree is Empty!\n”) ;
   else  { do
                 { while (p!=NULL)
                        {  stack[++top]=p ;  p=p->Lchild ;   }
                     if  (top==0)  bool=0 ;
                     else  {  p=stack[top] ;  top-- ;
                                 visit( p->data ) ;  p=p->Rchild ; }
                 }  while (bool!=0) ;
           }
 }

後序遍歷二叉樹

1 遞歸算法
算法的遞歸定義是:
若二叉樹為空,則遍歷結束;否則
⑴ 後序遍歷左子樹(遞歸調用本算法);
⑵ 後序遍歷右子樹(遞歸調用本算法) ;
⑶ 訪問根結點 。

後序遍歷的遞歸算法
void  PostorderTraverse(BTNode  *T)
{  if  (T!=NULL) 
{  PostorderTraverse(T->Lchild) ;
PostorderTraverse(T->Rchild) ; 
visit(T->data) ;       /*  訪問根結點  */ 
}
}  
        遍歷二叉樹的算法中基本操作是訪問結點,因此,無論是哪種次序的遍歷,對有n個結點的二叉樹,其時間復雜度均為O(n) 。

2 非遞歸算法(略)
在後序遍歷中,根結點是最後被訪問的。因此,在遍歷過程中,當搜索指針指向某一根結點時,不能立即訪問,而要先遍歷其左子樹,此時根結點進棧。當其左子樹遍歷完後再搜索到該根結點時,還是不能訪問,還需遍歷其右子樹。所以,此根結點還需再次進棧,當其右子樹遍歷完後再退棧到到該根結點時,才能被訪問。
因此,設立一個狀態標志變量tag :
其次,設兩個堆棧S1、S2 ,S1保存結點,S2保存結點的狀態標志變量tag 。S1和S2共用一個棧頂指針。
設T是指向根結點的指針變量,非遞歸算法是:
若二叉樹為空,則返回;否則,令p=T;
⑴ 第一次經過根結點p,不訪問:
p進棧S1 , tag 賦值0,進棧S2,p=p->Lchild 。
⑵ 若p不為空,轉(1),否則,取狀態標志值tag :
⑶ 若tag=0:對棧S1,不訪問,不出棧;修改S2棧頂元素值(tag賦值1) ,取S1棧頂元素的右子樹,即p=S1[top]->Rchild ,轉(1);
⑷ 若tag=1:S1退棧,訪問該結點;
直到棧空為止。

算法實現:
#define MAX_STACK_SIZE 50
void  PostorderTraverse( BTNode  *T)
{  BTNode  *S1[MAX_STACK_SIZE ] ,*p=T ;
int S2[MAX_STACK_SIZE ] , top=0 , bool=1 ;
if  (T==NULL)  printf(“Binary Tree is Empty!\n”) ;
else  { do
     {   while (p!=NULL)
              {  S1[++top]=p ; S2[top]=0 ; 
                  p=p->Lchild ;   
              }
         if  (top==0)  bool=0 ;
                               else if  (S2[top]==0)    
                               {   p=S1[top]->Rchild ;  S2[top]=1 ;   }
                               else 
                               {  p=S1[top] ;  top-- ;
                                  visit( p->data ) ; p=NULL ; 
                                 /*  使循環繼續進行而不至於死循環 */                       }
}  while (bool!=0) ;
}}

層次遍歷二叉樹

    層次遍歷二叉樹,是從根結點開始遍歷,按層次次序“自上而下,從左至右”訪問樹中的各結點。
   為保證是按層次遍歷,必須設置一個隊列。
   設T是指向根結點的指針變量,層次遍歷非遞歸算法是:

若二叉樹為空,則返回;否則,令p=T,p入隊;
⑴ 隊首元素出隊到p;
⑵訪問p所指向的結點;
⑶將p所指向的結點的左、右子結點依次入隊。直到隊空為止。

#define MAX_NODE  50
void  LevelorderTraverse( BTNode  *T)
{  BTNode  *Queue[MAX_NODE] , *p=T ;
int  front=0 , rear=0 ;
if  (p!=NULL) 
{  Queue[++rear]=p;    /*   根結點入隊  */
while (front<rear)
     {  p=Queue[++front];  visit( p->data );
         if (p->Lchild!=NULL)
               Queue[++rear]=p;    /*   左結點入隊  */
         if (p->Rchild!=NULL)
               Queue[++rear]=p;    /*   左結點入隊  */
      }
}
}

二叉樹遍歷算法的應用

    “遍歷”是二叉樹最重要的基本操作,是各種其它操作的基礎,二叉樹的許多其它操作都可以通過遍歷來實現。如建立二叉樹的存儲結構、求二叉樹的結點數、求二叉樹的深度等。

二叉樹的擴充方法是:在二叉樹中結點的每一個空鏈域處增加一個擴充的結點(總是葉子結點,用方框“□”表示)。對於二叉樹的結點值:
◆ 是char類型:擴充結點值為“?”或“#”;
◆ 是int類型:擴充結點值為0或-1;
下面的算法是二叉樹的前序創建的遞歸算法,讀入一棵二叉樹對應的擴充二叉樹的前序遍歷的結點值序列。每讀入一個結點值就進行分析:
◆ 若是擴充結點值:令根指針為NULL;
◆ 若是(正常)結點值:動態地為該指針分配一個結點,將該值賦給根結點,然後遞歸地創建根的左子樹和右子樹。

算法實現:
#define NULLKY  ‘?’
#define MAX_NODE   50
typedef struct BTNode
{  char  data ;
struct BTNode *Lchild , *Rchild ;
}BTNode ;
BTNode  *Preorder_Create_BTree(BTNode  *T)
 /*   建立鏈式二叉樹,返回指向根結點的指針變量  */
{  char ch ; 
ch=getchar() ; 
if  (ch==NULLKY) 
{ T=NULL; return(T) ; }
else
{  
   T=(BTNode *)malloc(sizeof(BTNode)) ;
T–>data=ch ;
Preorder_Create_BTree(T->Lchild) ;
Preorder_Create_BTree(T->Rchild) ;
}
}

求二叉樹的葉子結點數

2 求二叉樹的葉子結點數
可以直接利用先序遍歷二叉樹算法求二叉樹的葉子結點數。只要將先序遍歷二叉樹算法中vist()函數簡單地進行修改就可以。
算法實現:

#define  MAX_STACK_SIZE 50
int  BiTreeleaves( BTNode  *T)
{  BTNode  *stack[MAX_STACK_SIZE] ,*p=T;
int  top=0, num=0;
if  (T!=NULL)
{  stack[++top]=p ; 
while (top>0)
   {  p=stack[top--] ;
       if (p->Lchild==NULL&&p->Rchild==NULL)  num++ ;   
        if  (p->Rchild!=NULL )
             stack[++top]=p->Rchild; 
        if  (p->Lchild!=NULL )
                stack[++top]=p->Lchild; 
     }
}
return(num) ;
}

求二叉樹的深度

3 求二叉樹的深度
利用層次遍歷算法可以直接求得二叉樹的深度。
算法實現:

#define  MAX_NODE  50
int    BiTreedepth( BTNode  *T)
{  BTNode  * Queue[MAX_NODE] ,*p=T;
int  front=0 , rear=0, depth=0, level ;
/*  level總是指向訪問層的最後一個結點在隊列的位置  */
if  (T!=NULL)
{  Queue[++rear]=p;    /*   根結點入隊  */
level=rear ;    /*  根是第1層的最後一個節點  */
while (front<rear)
     {  p=Queue[++front]; 
         if (p->Lchild!=NULL)
               Queue[++rear]=p;    /*   左結點入隊  */
         if (p->Rchild!=NULL)
               Queue[++rear]=p;    /*   左結點入隊  */
          if (front==level)  
             /*  正訪問的是當前層的最後一個結點  */
             {  depth++ ;  level=rear ;  }
      }
}
}

求深度的遞歸算法

/* 初始條件: 二叉樹T存在。操作結果: 返回T的深度 */
int BiTreeDepth(BiTree T)
{
    int i,j;
    if(!T)  return 0;
    if(T->lchild)   
         i=BiTreeDepth(T->lchild);
    else  i=0;
    if(T->rchild)
        j=BiTreeDepth(T->rchild);
    else  j=0;
    return i>j?i+1:j+1;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved