C語言實現的求二叉樹的最大寬度(遞迴與非遞迴版本)
阿新 • • 發佈:2019-01-29
一、遞迴
這裡說的遞迴,並非是指整個函式遞迴,而是說其中一個子函式使用了遞迴。整個思路可以如下:要求取最大寬度,可以迴圈求取每一層的寬度,存入一個數組,然後在這個數組裡求最大值即可,陣列下標即層數(或高度)。對於求某一層的寬度,考慮把它寫成一個子函式,引數考慮起始結點以及對應的層數,舉例:對於根節點來說,其第三層的寬度,就是其左孩子的第二層的寬度與其右孩子的第二層的寬度之和。
這樣,我們可以寫出兩個函式,我的如下:子函式LevelWidth函式返回特定起點開始的某個層的寬度,採用遞迴。
int LevelWidth(BT root,int level)//find the width of a level(amounts of nodes in the level). { if(!root)return 0; else { if(level==1)return 1; level=LevelWidth(root->lchild,level-1)+LevelWidth(root->rchild,level-1); } return level; }
主函式Width返回某起點開始的樹的最大寬度,使用迴圈。
int Width(BT root)//find the maximum width of the btree. { int width,i; int w[20]; for(i=0;i<20;i++)w[i]=0; if(!root)width=0; else { for(i=0;i<=Depth(root);i++)w[i]=LevelWidth(root,i+1); } i=0; while(w[i]) { if(w[i]>width)width=w[i]; i++; } return width; }
那麼能不能合二為一寫成一個遞迴函式呢?我覺得不可以。因為最大寬度分成左右子樹最大寬度之和,是不對的,因為未必在同一個層次。當然也許有其它分法,但我未知。
二、非遞迴
非遞迴需要採用佇列,是在層次遍歷一棵樹的基礎上做些改進。我看過C++使用vector寫的,使用swap交換,可以獲得每個層次的結點數目,非常妙。若借鑑這個思路則需要寫可以交換兩個陣列的c子函式,並不難,但我想盡可能在一個函式內完成。和層次遍歷比起來,需要多記錄一個資訊,就是每一層的結點數目,因此在遍歷的程式碼基礎上增加了一個數組,用來記錄每一層的數目(或者每一層以及之前的層的所有結點數之和,我這裡是採用這個的),這樣就可以在掃描佇列頭的時候,根據隊頭的結點序號來判斷該結點處於哪一層,也判斷出了它的孩子處於哪一層(下一層)。此時在對它的每個孩子結點的入隊同時,即每增加一個入隊結點之時,下一層的結點數目也相應增加一個。我的具體實現如下,WidthNR用以表明width not recursive。
int WidthNR(BT root)//find the maximum width without recursive function.
{
int i,j,w,index;
int count[20],width[20];//count array stores the total amounts of nodes before a level(including itself);width array stores every level's amount of nodes.
BT queue[20];//queue array stores the nodes' pointers.
for(i=0;i<20;i++)
{
count[i]=0;
width[i]=0;
queue[i]=NULL;
}
i=0;
j=0;
if(!root)w=0;
else
{
queue[0]=root;
count[0]=1;
count[1]=1;
index=1;
while(queue[i])
{
if(queue[i]->lchild)
{
j++;
queue[j]=queue[i]->lchild;
count[index]++;
}
if(queue[i]->rchild)
{
j++;
queue[j]=queue[i]->rchild;
count[index]++;
}
i++;
if(i>=count[index-1])index++;//if the head of queue exeeds the level's total amount then it indictates it's a node in next level.
if(count[index]==0)count[index]+=count[index-1];//the next level's amount of nodes is the sum of itself's and the amount of nodes whose level are before it.
}
}
width[0]=1;
w=width[0];
i=1;
while(count[i])
{
width[i]=count[i]-count[i-1];
if(width[i]>w)w=width[i];
i++;
}
return w;
}