1. 程式人生 > >二叉樹的儲存結構和實現

二叉樹的儲存結構和實現

一、二叉樹儲存結構 

1)二叉樹的順序儲存結構 

 二叉樹的順序儲存結構中節點的存放次序是:對該樹中每個節點進行編號,其編號從小到大的順序就是節點存放在連續儲存單元的先後次序

 若把二叉樹儲存到一維陣列中,則該編號就是下標值加1(注意C/C++語言中陣列的起始下標為0)。

樹中各節點的編號與等高度的完全二叉樹中對應位置上節點的編號相同。 

定義為:typedef ElemType SqBTree[MaxSize];

順序二叉樹,如下圖:


字串:SqBTree bt="#ABD#C#E######F";

2)二叉樹的鏈式儲存結構

     在二叉樹的連結儲存中,節點的結構如下:

      typedef struct node
   {   ElemType data;
       struct node *lchild,*rchild;

   } BTNode;

其中,data表示值域,用於儲存對應的資料元素,lchild和rchild分別表示左指標域和右指標域,用於分別儲存左孩子節點和右孩子節點(即左、右子樹的根節點)的儲存位置。

二、二叉樹的基本運算及其實現

歸納起來,二叉樹有以下基本運算:

(1)建立二叉樹CreateBTNode(*b,*str):根據二叉樹括號表示法的字串*str生成對應的鏈式儲存結構。

用ch掃描採用括號表示法表示二叉樹的字串。

分以下幾種情況:

① 若ch='(':則將前面剛建立的節點作為雙親節點進棧,並置k=1,表示其後建立的節點將作為這個節點的左孩子節點;

② 若ch=')':表示棧中節點的左右孩子節點處理完畢,退棧;

③ 若ch=‘,’:表示其後建立的節點為右孩子節點,置k=2;

④ 其他情況:

當k=1時,表示這個節點作為棧中節點的左孩子節點;

 當k=2時,表示這個節點作為棧中節點的右孩子節點。如此迴圈直到str處理完畢。

演算法中使用一個棧St儲存雙親節點,top為其棧指標,k指定其後處理的節點是雙親節點(儲存在棧中)的左孩子節點(k=1)還是右孩子節點(k=2)。

void CreateBTNode(BTNode * &b,char *str)
{  BTNode *St[MaxSize],*p=NULL;
   int top=-1,k,j=0;  
   char ch;
   b=NULL;//建立的二叉樹初始時為空
   ch=str[j];
   while (ch!='\0')        //str未掃描完時迴圈
   {  switch(ch) 
      {
case '(':top++;St[top]=p;k=1; break;                  
//為左孩子節點
case ')':top--;break;
case ',':k=2; break;  

         //為孩子節點右節點、

    default:
       p=(BTNode *)malloc(sizeof(BTNode));
p->data=ch;p->lchild=p->rchild=NULL;
if (b==NULL)    //p為二叉樹的根節點
     b=p;
else    //已建立二叉樹根節點
       {  switch(k) 
          {
    case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
    }
       }
     }
     j++;ch=str[j];
   }

}

(2)查詢節點FindNode(*b,x):在二叉樹b中尋找data域值為x的節點,並返回指向該節點的指標。

採用先序遍歷遞迴演算法查詢值為x的節點。找到後返回其指標,否則返回NULL。演算法如下: 

BTNode *FindNode(BTNode *b,ElemType x) 
{  BTNode *p;
   if (b==NULL) return NULL;
   else if (b->data==x) return b;
   else
   {   p=FindNode(b->lchild,x);
if (p!=NULL) return p;
else return FindNode(b->rchild,x);
   }

}

(3)找孩子節點LchildNode(p)和Rchild-Node(p):分別求二叉樹中節點*p的左孩子節點和右孩子節點。

直接返回*p節點的左孩子節點或右孩子節點的指標。演算法如下:

    BTNode *LchildNode(BTNode *p)
  {
      return p->lchild;

  }

  BTNode *RchildNode(BTNode *p)
  {
      return p->rchild;
  } 

(4)求高度BTNodeDepth(*b):求二叉樹b的高度。若二叉樹為空,則其高度為0;否則,其高度等於左子樹與右子樹中的最大高度加l。

求二叉樹的高度的遞迴模型f()如下:

 f(b) = 0                 b=NULL

     f(b) = MAX{f(b->lchild),f(b->rchild)}+1     其他情況

int BTNodeDepth(BTNode *b) 
{  int lchilddep,rchilddep;
   if (b==NULL) return(0); //空樹的高度為0
   else  
   {  lchilddep=BTNodeDepth(b->lchild);
//求左子樹的高度為lchilddep
  rchilddep=BTNodeDepth(b->rchild);
//求右子樹的高度為rchilddep
return(lchilddep>rchilddep)?
           (lchilddep+1):(rchilddep+1));
   }
}

(5)輸出二叉樹DispBTNode(*b):以括號表示法輸出一棵二叉樹。

用括弧表示法輸出二叉樹。對於非空二叉樹b,先輸出其元素值,當存在左孩子節點或右孩子節點時,輸出一個“(”符號,然後遞迴處理左子樹,輸出一個“,”符號,遞迴處理右子樹,最後輸出一個“)”符號。

void DispBTNode(BTNode *b) 
{  if (b!=NULL)
   {  printf("%c",b->data);
if (b->lchild!=NULL || b->rchild!=NULL)
{  printf("(");
    DispBTNode(b->lchild);
//遞迴處理左子樹
    if (b->rchild!=NULL) printf(",");
    DispBTNode(b->rchild);
//遞迴處理右子樹
    printf(")");
}
   }
}