資料結構例程——二叉樹的構造
阿新 • • 發佈:2019-01-27
1.由先序序列和中序序列構造二叉樹
- 定理:任何n(n≥0)個不同節點的二叉樹,都可由它的中序序列和先序序列唯一地確定。
- 證明(數學歸納法)
基礎:當n=0時,二叉樹為空,結論正確。
假設:設節點數小於n的任何二叉樹,都可以由其先序序列和中序序列唯一地確定。
歸納:已知某棵二叉樹具有n(n>0)個不同節點,其先序序列是a0a1…an−1 ;中序序列是b0b1…bk−1bkbk+1…bn−1 。
- 先序遍歷“根-左-右”,
a0 必定是二叉樹的根節點 a0 必然在中序序列中出現,設在中序序列中必有某個bk(0≤k≤n−1) 就是根節點a0 。
- 由於
bk 是根節點,中序遍歷“左-根-右”,故中序序列中b0b1…bk−1 必是根節點b 左子樹的中序序列,即bk 的左子樹有k個節點,bk+1…bn−1 必是根節點bk(a0) 右子樹的中序序列,即bk 的右子樹有n−k−1 個節點。 - 對應先序序列,緊跟在根節點
a0 之後的k個節點a1…ak 是左子樹的先序序列,ak+1…an−1 這n−k−1 就是右子樹的先序序列。
- 根據歸納假設,子先序序列
a1…ak 和子中序序列b0b1…bk−1 可以唯一地確定根節點a0 的左子樹,而先序序列ak+1…an−1 和子中序序列bk+1…bn−1 可以唯一地確定根節點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;
}