1. 程式人生 > >資料結構例程——二叉樹的構造

資料結構例程——二叉樹的構造

1.由先序序列和中序序列構造二叉樹

  • 定理:任何n(n≥0)個不同節點的二叉樹,都可由它的中序序列和先序序列唯一地確定。
  • 證明(數學歸納法)
    基礎:當n=0時,二叉樹為空,結論正確。
    假設:設節點數小於n的任何二叉樹,都可以由其先序序列和中序序列唯一地確定。
    歸納:已知某棵二叉樹具有n(n>0)個不同節點,其先序序列是a0a1an1;中序序列是b0b1bk1bkbk+1bn1
    • 先序遍歷“根-左-右”,a0必定是二叉樹的根節點
    • a0必然在中序序列中出現,設在中序序列中必有某個bk0kn1就是根節點a0
      這裡寫圖片描述
    • 由於bk是根節點,中序遍歷“左-根-右”,故中序序列中b0b1bk1必是根節點b
      k
      (a0)
      左子樹的中序序列,即bk的左子樹有k個節點,bk+1bn1必是根節點bka0右子樹的中序序列,即bk的右子樹有nk1個節點。
    • 對應先序序列,緊跟在根節點a0之後的k個節點a1ak是左子樹的先序序列,ak+1an1nk1就是右子樹的先序序列。
      這裡寫圖片描述
    • 根據歸納假設,子先序序列a1ak和子中序序列b0b1bk1可以唯一地確定根節點a0的左子樹,而先序序列ak+1an1和子中序序列bk+1bn1可以唯一地確定根節點a0的右子樹。
    • 綜上所述,這棵二叉樹的根節點己經確定,而且其左、右子樹都唯一地確定了,所以整個二叉樹也就唯一地確定了。

  • 這裡寫圖片描述

    根據定理的證明,寫出下面的演算法。

    品味:以上構造性證明是突出體現電腦科學的案例。計算機學科的精髓就在於製造,即使在“理論性”味道的定理中,其證明過程,給出的就是“存在的這麼一個東西”的構造方法。

[參考解答](btreee.h見演算法庫

#include <stdio.h>
#include <malloc.h>
#include "btree.h"

BTNode *CreateBT1(char *pre,char *in,int n)
/*pre存放先序序列,in存放中序序列,n為二叉樹結點個數,
本演算法執行後返回構造的二叉鏈的根結點指標*/
{
    BTNode *s;
    char
*p; int k; if (n<=0) return NULL; s=(BTNode *)malloc(sizeof(BTNode)); //建立二叉樹結點*s s->data=*pre; for (p=in; p<in+n; p++) //在中序序列中找等於*ppos的位置k if (*p==*pre) //pre指向根結點 break; //在in中找到後退出迴圈 k=p-in; //確定根結點在in中的位置 s->lchild=CreateBT1(pre+1,in,k); //遞迴構造左子樹 s->rchild=CreateBT1(pre+k+1,p+1,n-k-1); //遞迴構造右子樹 return s; } int main() { ElemType pre[]="ABDGCEF",in[]="DGBAECF"; BTNode *b1; b1=CreateBT1(pre,in,7); printf("b1:"); DispBTNode(b1); printf("\n"); return 0; }

2.由後序序列和中序序列構造二叉樹

  • 定理:任何n(n>0)個不同節點的二叉樹,都可由它的中序序列和後序序列唯一地確定。
  • 證明:(略)
    這裡寫圖片描述

[參考解答](btreee.h見演算法庫

#include <stdio.h>
#include <malloc.h>
#include "btree.h"

BTNode *CreateBT2(char *post,char *in,int n)
/*post存放後序序列,in存放中序序列,n為二叉樹結點個數,
本演算法執行後返回構造的二叉鏈的根結點指標*/
{
    BTNode *s;
    char r,*p;
    int k;
    if (n<=0) return NULL;
    r=*(post+n-1);                          //根結點值
    s=(BTNode *)malloc(sizeof(BTNode));     //建立二叉樹結點*s
    s->data=r;
    for (p=in; p<in+n; p++)                 //在in中查詢根結點
        if (*p==r)
            break;
    k=p-in;                                 //k為根結點在in中的下標
    s->lchild=CreateBT2(post,in,k);         //遞迴構造左子樹
    s->rchild=CreateBT2(post+k,p+1,n-k-1);  //遞迴構造右子樹
    return s;
}

int main()
{
    ElemType in[]="DGBAECF",post[]="GDBEFCA";
    BTNode *b2;
    b2=CreateBT2(post,in,7);
    printf("b2:");
    DispBTNode(b2);
    printf("\n");
    return 0;
}

3.由順序儲存結構轉為二叉鏈儲存結構
這裡寫圖片描述

[參考解答](btreee.h見演算法庫

#include <stdio.h>
#include <malloc.h>
#include "btree.h"
#define N 30
typedef ElemType SqBTree[N];
BTNode *trans(SqBTree a,int i)
{
    BTNode *b;
    if (i>N)
        return(NULL);
    if (a[i]=='#')
        return(NULL);           //當節點不存在時返回NULL
    b=(BTNode *)malloc(sizeof(BTNode)); //建立根節點
    b->data=a[i];
    b->lchild=trans(a,2*i);                 //遞迴建立左子樹
    b->rchild=trans(a,2*i+1);               //遞迴建立右子樹
    return(b);                              //返回根節點
}
int main()
{
    BTNode *b;
    ElemType s[]="0ABCD#EF#G####################";
    b=trans(s,1);
    printf("b:");
    DispBTNode(b);
    printf("\n");
    return 0;
}