哈夫曼樹(shù)的構(gòu)造
根據(jù)哈弗曼樹(shù)的定義,一棵二叉樹(shù)要使其WPL值最小,必須使權(quán)值越大的葉子結(jié)點(diǎn)越靠近根結(jié)點(diǎn),而權(quán)值越小的葉子結(jié)點(diǎn)越遠(yuǎn)離根結(jié)點(diǎn)。
哈弗曼依據(jù)這一特點(diǎn)提出了一種構(gòu)造最優(yōu)二叉樹(shù)的方法,其基本思想如下:
下面演示了用Huffman算法構(gòu)造一棵Huffman樹(shù)的過(guò)程:
假設(shè)有n個(gè)權(quán)值,則構(gòu)造出的哈夫曼樹(shù)有n個(gè)葉子結(jié)點(diǎn)。 n個(gè)權(quán)值分別設(shè)為 w1、w2、…、wn,則哈夫曼樹(shù)的構(gòu)造規(guī)則為:
?。?) 將w1、w2、…,wn看成是有n 棵樹(shù)的森林(每棵樹(shù)僅有一個(gè)結(jié)點(diǎn));
(2) 在森林中選出兩個(gè)根結(jié)點(diǎn)的權(quán)值最小的樹(shù)合并,作為一棵新樹(shù)的左、右子樹(shù),且新樹(shù)的根結(jié)點(diǎn)權(quán)值為其左、右子樹(shù)根結(jié)點(diǎn)權(quán)值之和;
(3)從森林中刪除選取的兩棵樹(shù),并將新樹(shù)加入森林;
(4)重復(fù)(2)、(3)步,直到森林中只剩一棵樹(shù)為止,該樹(shù)即為所求得的哈夫曼樹(shù)。
如:對(duì) 下圖中的六個(gè)帶權(quán)葉子結(jié)點(diǎn)來(lái)構(gòu)造一棵哈夫曼樹(shù),步驟如下:
注意:為了使得到的哈夫曼樹(shù)的結(jié)構(gòu)盡量唯一,通常規(guī)定生成的哈夫曼樹(shù)中每個(gè)結(jié)點(diǎn)的左子樹(shù)根結(jié)點(diǎn)的權(quán)小于等于右子樹(shù)根結(jié)點(diǎn)的權(quán)。
具體算法如下:
//2、根據(jù)數(shù)組 a 中 n 個(gè)權(quán)值建立一棵哈夫曼樹(shù),返回樹(shù)根指針
struct BTreeNode* CreateHuffman(ElemType a[], int n)
{
int i, j;
struct BTreeNode **b, *q;
b = malloc(n*sizeof(struct BTreeNode));
for (i = 0; i 《 n; i++) //初始化b指針數(shù)組,使每個(gè)指針元素指向a數(shù)組中對(duì)應(yīng)的元素結(jié)點(diǎn)
{
b[i] = malloc(sizeof(struct BTreeNode));
b[i]-》data = a[i];
b[i]-》left = b[i]-》right = NULL;
}
for (i = 1; i 《 n; i++)//進(jìn)行 n-1 次循環(huán)建立哈夫曼樹(shù)
{
//k1表示森林中具有最小權(quán)值的樹(shù)根結(jié)點(diǎn)的下標(biāo),k2為次最小的下標(biāo)
int k1 = -1, k2;
for (j = 0; j 《 n; j++)//讓k1初始指向森林中第一棵樹(shù),k2指向第二棵
{
if (b[j] != NULL && k1 == -1)
{
k1 = j;
continue;
}
if (b[j] != NULL)
{
k2 = j;
break;
}
}
for (j = k2; j 《 n; j++)//從當(dāng)前森林中求出最小權(quán)值樹(shù)和次最小
{
if (b[j] != NULL)
{
if (b[j]-》data 《 b[k1]-》data)
{
k2 = k1;
k1 = j;
}
else if (b[j]-》data 《 b[k2]-》data)
k2 = j;
}
}
//由最小權(quán)值樹(shù)和次最小權(quán)值樹(shù)建立一棵新樹(shù),q指向樹(shù)根結(jié)點(diǎn)
q = malloc(sizeof(struct BTreeNode));
q-》data = b[k1]-》data + b[k2]-》data;
q-》left = b[k1];
q-》right = b[k2];
b[k1] = q;//將指向新樹(shù)的指針賦給b指針數(shù)組中k1位置
b[k2] = NULL;//k2位置為空
}
free(b); //刪除動(dòng)態(tài)建立的數(shù)組b
return q; //返回整個(gè)哈夫曼樹(shù)的樹(shù)根指針
}
評(píng)論