? 理論部分
成都創(chuàng)新互聯(lián)成立以來(lái)不斷整合自身及行業(yè)資源、不斷突破觀念以使企業(yè)策略得到完善和成熟,建立了一套“以技術(shù)為基點(diǎn),以客戶需求中心、市場(chǎng)為導(dǎo)向”的快速反應(yīng)體系。對(duì)公司的主營(yíng)項(xiàng)目,如中高端企業(yè)網(wǎng)站企劃 / 設(shè)計(jì)、行業(yè) / 企業(yè)門戶設(shè)計(jì)推廣、行業(yè)門戶平臺(tái)運(yùn)營(yíng)、重慶APP開發(fā)公司、手機(jī)網(wǎng)站制作設(shè)計(jì)、微信網(wǎng)站制作、軟件開發(fā)、成都服務(wù)器托管等實(shí)行標(biāo)準(zhǔn)化操作,讓客戶可以直觀的預(yù)知到從成都創(chuàng)新互聯(lián)可以獲得的服務(wù)效果。先補(bǔ)充一個(gè)概念,什么是路徑長(zhǎng)度?
從樹中一個(gè)節(jié)點(diǎn)到另一個(gè)節(jié)點(diǎn)之間的分支構(gòu)成這兩個(gè)節(jié)點(diǎn)之間的路徑,路徑上的分支數(shù)目稱作路徑長(zhǎng)度。而一般不帶權(quán)的單個(gè)路徑長(zhǎng)度默認(rèn)為1,所以可以認(rèn)為節(jié)點(diǎn)數(shù)為n的樹的路徑長(zhǎng)度為n-1。
哈夫曼樹的定義是帶權(quán)路徑長(zhǎng)度最短的樹,也叫最優(yōu)二叉樹。換種更好的理解方式,就是一棵特殊的二叉樹,而這棵樹的葉子節(jié)點(diǎn)到根節(jié)點(diǎn)的帶權(quán)路徑都是盡可能最短的
如下圖:
樹a的路徑長(zhǎng)度就是7*2+5*2+2*2+4*2=36。
樹b的路徑長(zhǎng)度就是7*3+5*3+2*1+4*2=46
樹c的路徑長(zhǎng)度就是7*1+5*2+2*3+4*3=35
明顯,樹c的路徑長(zhǎng)度最小,但它是最優(yōu)二叉樹嗎?
想要驗(yàn)證樹c是不是哈夫曼樹,就得從定義出發(fā)。帶權(quán)路徑長(zhǎng)度最小,那么很容易想到,權(quán)重大的路徑所在的層數(shù)一定偏小,而權(quán)重小的路徑層數(shù)就偏小。那么很容易聯(lián)想到,把權(quán)重小的路徑先找出來(lái)并放在下面。經(jīng)過(guò)總結(jié)可得出以下結(jié)論:
(1)根據(jù)給定的n個(gè)權(quán)值?{w1,w2,?,wn}?構(gòu)成n棵二叉樹的集合?F={T1,T2,?,T?},?其中每棵二叉樹Ti中只有一個(gè)帶權(quán)為wi的根結(jié)點(diǎn),其左右子樹均空。
(2)在F中選取兩棵根結(jié)點(diǎn)的權(quán)值最小的樹作為左右子樹構(gòu)造一棵新的二叉樹,且置新的二叉樹的根結(jié)點(diǎn)的權(quán)值為其左、右子樹上根結(jié)點(diǎn)的權(quán)值之和。
(3)在F中刪除這兩棵樹,同時(shí)將新得到的二叉樹加入F中。
(4)重復(fù)(2)和(3),直到F只含一棵樹為止。這棵樹便是赫夫曼樹。
哈夫曼編碼與前綴編碼:
前綴編碼:如果在一個(gè)編碼方案中, 任一個(gè)編碼都不是其他任何編碼的前綴(最左子串),如稱編碼是前綴編碼。前綴編碼可以保證對(duì)壓縮文件進(jìn)行解碼時(shí)不產(chǎn)生二義性,確保正確解碼。
哈夫曼編碼:對(duì)一棵具有n個(gè)葉子的哈夫曼樹,若對(duì)樹中的每個(gè)左分支賦予0,右分支賦予1,則從根到每個(gè)葉子的路徑上,各分支的賦值分別構(gòu)成一一個(gè)二進(jìn)制串,該二進(jìn)制串就稱為哈夫曼編碼。
哈夫曼編碼是前綴編碼:哈夫曼編碼是根到葉子路徑上的編碼序列,由樹的特點(diǎn)知,若路徑A是另一條路徑B的最左部分,則B經(jīng)過(guò)了A.則A的終點(diǎn)一定不是葉子,而哈夫曼編碼對(duì)應(yīng)路徑的終點(diǎn)一定為葉子,因此,任一哈夫曼碼都不會(huì)與任意其他哈夫曼編碼的前綴部分完全重疊,因此哈夫曼編碼是前綴編碼。
哈夫曼編碼是最優(yōu)前綴編碼:對(duì)于包括n個(gè)字符的數(shù)據(jù)文件,分別以它們的出現(xiàn)次數(shù)為權(quán)值構(gòu)造哈夫曼樹,則利用該樹對(duì)應(yīng)的哈夫曼編碼對(duì)文件進(jìn)行編碼,能使該文件壓縮后對(duì)應(yīng)的二進(jìn)制文件的長(zhǎng)度最短。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
實(shí)踐部分
以數(shù)據(jù)結(jié)構(gòu)哈夫曼樹和哈夫曼編碼基礎(chǔ)題為例
請(qǐng)構(gòu)建夫曼樹和哈夫曼編碼的實(shí)現(xiàn),對(duì)于輸入的(n=8)個(gè)字符和對(duì)應(yīng)的概率,生成其對(duì)應(yīng)的哈夫曼編碼。
參考輸入如下:
"a","b","c","d","e","f","g","h"
0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.1
參考輸出如下:
a:? ? ? ? 1010
b:? ? ? ? 00
c:? ? ? ? 10000
d:? ? ? ? 1001
e:? ? ? ? 11
f:? ? ? ? 10001
g:? ? ? ? 01
h:? ? ? ? 1011
首先是哈夫曼樹的定義,一般要求記錄節(jié)點(diǎn)的權(quán)重,雙親節(jié)點(diǎn),左、右子女節(jié)點(diǎn)。
typedef struct{
int weight;//權(quán)重
int parents, Lchild, Rchlid;
}thnode,HuffmanTree[1000];
再是哈夫曼樹的構(gòu)建,先對(duì)前n個(gè)(葉子)節(jié)點(diǎn)進(jìn)行處理,記錄它們的權(quán)重,其他信息記為0。再對(duì)后面構(gòu)建哈夫曼樹形成的過(guò)程節(jié)點(diǎn)(容易得知哈夫曼樹的節(jié)點(diǎn)個(gè)數(shù)為2*n-1個(gè),所以過(guò)程節(jié)點(diǎn)有n-1個(gè))的所有信息記為0。在根據(jù)理論部分的規(guī)律,進(jìn)行哈夫曼樹的構(gòu)建。
void Huffman_Creat(HuffmanTree ht,int w[],int n)//n為葉子結(jié)點(diǎn)個(gè)數(shù)
{
//先處理前n個(gè)節(jié)點(diǎn)
int m = 2 * n - 1;//樹的總結(jié)點(diǎn)數(shù)
int i,s1,s2;
for (i = 1; i<= n;i++)
{
ht[i].weight = w[i];
ht[i].Lchild = 0;
ht[i].Rchlid = 0;
ht[i].parents = 0;
}
//再處理后面的過(guò)程節(jié)點(diǎn)
for (i = n+1; i<= m;i++)
{
ht[i].weight = 0;
ht[i].Lchild = 0;
ht[i].Rchlid = 0;
ht[i].parents = 0;
}
//最后再按規(guī)律構(gòu)建哈夫曼樹
for (i = n + 1; i<= m;i++)
{
select(ht, i - 1, &s1, &s2);//尋找雙親節(jié)點(diǎn)不為0的權(quán)重最小的2個(gè)節(jié)點(diǎn)
ht[i].weight = ht[s1].weight + ht[s2].weight;
ht[i].Lchild = s1;
ht[i].Rchlid = s2;
ht[s1].parents = i;
ht[s2].parents = i;
}
}
select函數(shù)就是尋找雙親節(jié)點(diǎn)不為0的權(quán)重最小的2個(gè)節(jié)點(diǎn)。
void select(HuffmanTree ht,int end,int*s1,int*s2)
{
int min1, min2;//最小和第二小
int i = 1;
while(ht[i].parents!=0 && i<=end)
i++;
min1 = ht[i].weight;
*s1 = i;
i++;
while(ht[i].parents!=0 && i<=end)
i++;
if(ht[i].weight=min1 && ht[j].weight
哈夫曼樹構(gòu)建完成后,就是哈夫曼編碼的建立。利用定義中的parent,可以從葉子節(jié)點(diǎn)尋找回根節(jié)點(diǎn),跟從根節(jié)點(diǎn)遍歷到葉子節(jié)點(diǎn)的方法相比,不但減少代碼量,還方便記錄過(guò)程編碼。
typedef char* HuffmanCode[1000];
void HuffmanCode_Creat(HuffmanTree ht, HuffmanCode hc,int n)
{
char *s;
int start;
int i, c, p;
s = (char *)malloc(n * sizeof(char));//創(chuàng)建臨時(shí)數(shù)組
s[n - 1] = '\0';//反向存入s數(shù)組中,方便后續(xù)輸出
for (i = 1; i<= n;i++)
{
start = n - 1;
c = i;//存儲(chǔ)當(dāng)前節(jié)點(diǎn)
p = ht[i].parents;//存雙親
while(p!=0)//只有根節(jié)點(diǎn)的雙親節(jié)點(diǎn)為0
{
--start;
if(ht[p].Lchild==c)
s[start] = '0';
else
s[start] = '1';
c = p;
p = ht[p].parents;//向上尋找雙親,直到為根節(jié)點(diǎn)
}
hc[i] = (char *)malloc((n - start) * sizeof(char));
strcpy(hc[i], &s[start]);//將每次的結(jié)果存入hc數(shù)組
}
free(s);
}
結(jié)合本題要求,可得完整代碼為:
請(qǐng)代入個(gè)人思考,本代碼故意改了部分,輸出一定是錯(cuò)誤的!??!
請(qǐng)代入個(gè)人思考,本代碼故意改了部分,輸出一定是錯(cuò)誤的?。?!
請(qǐng)代入個(gè)人思考,本代碼故意改了部分,輸出一定是錯(cuò)誤的?。?!
#includeusing namespace std;
typedef struct{
char id;
double weight;//權(quán)
int parents, Lchild, Rchlid;
}thnode,HuffmanTree[1000];
void select(HuffmanTree ht,int end,int*s1,int*s2)
{
double min1, min2;
int i = 1;
while(ht[i].parents!=0 && i<=end)
i++;
min1 = ht[i].weight;
*s1 = i;
i++;
while(ht[i].parents!=0 && i<=end)
i++;
if(ht[i].weight=min1 && ht[j].weight>n;
for (int i=1;i<=n;i++)
cin>>ppp[i];
for (int i=1;i<=n;i++)
cin>>w[i];
HuffmanTree ht;
Huffman_Creat(ht, w, n);
for (int i=1;i<=n;i++)
ht[i].id=ppp[i];
HuffmanCode hc;
HuffmanCode_Creat(ht,hc, n);
for (i = 1; i<=n; i++)
{
printf("%c: %s\n", ht[i].id,hc[i]);
}
return 0;
}
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
文章題目:C++哈夫曼樹和哈夫曼編碼詳解-創(chuàng)新互聯(lián)
本文來(lái)源:http://jinyejixie.com/article36/ggspg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站制作、靜態(tài)網(wǎng)站、定制網(wǎng)站、App設(shè)計(jì)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容