版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、<p><b> 課 程 設(shè) 計</b></p><p><b> 課程設(shè)計任務(wù)書</b></p><p> 題 目: Huffman編/譯碼器</p><p><b> 初始條件:</b></p><p> 利用Huffman編碼進行通信可以大大提高信
2、道利用率.縮短信息傳輸時間,降低傳輸成本,這要求在發(fā)送端通過一個編碼系統(tǒng)對待傳數(shù)據(jù)預(yù)先編碼,在接收端將傳來的數(shù)據(jù)進行譯碼(復(fù)原)。對于雙工信道(即可以雙向傳輸信息的信道),每端都需要一個完整的編/譯碼系統(tǒng)。試為這樣的信息收發(fā)站寫一個Huffman碼的編/譯碼系統(tǒng)。</p><p> 要求完成的主要任務(wù): (包括課程設(shè)計工作量及其技術(shù)要求、說明書撰寫等具體要求)</p><p> 一個完
3、整的系統(tǒng)應(yīng)具有以下功能:</p><p> (l)I:初始化。從終端讀入字符集大小n,以及n個字符和n個權(quán)值,建立哈夫曼樹,并將它存于文件hfmTree中。</p><p> (2)E:編碼。利用已建好的Huffman樹(如不在內(nèi)存,則從文件hfmTree中讀入),對文件ToBeTran中的正文進行編碼,然后將結(jié)果存入文件CodeFile中。</p><p>
4、?。?)D:譯碼。利用已建好的Huffman樹將文件CodeFile中的代碼進行譯碼,結(jié)果存入文件TextFile中。</p><p> ?。?)P:印代碼文件。將文件CodeFile以緊湊格式顯示在終端上,每行50 個代碼。</p><p> (5)T:印哈夫曼樹。將已在內(nèi)存中的哈夫曼樹以直觀的方式(樹或凹入表形式)顯示在終端上,同時將此字符形式的哈夫曼樹寫入文件TreePrint中。
5、</p><p><b> 時間安排:</b></p><p><b> 需求分析</b></p><p><b> 程序的任務(wù):</b></p><p> 利用Huffman編碼進行通信可以大大提高信道利用率.縮短信息傳輸時間,降低傳輸成本,這要求在發(fā)送端通過一個編碼
6、系統(tǒng)對待傳數(shù)據(jù)預(yù)先編碼,在接收端將傳來的數(shù)據(jù)進行譯碼(復(fù)原)。對于雙工信道(即可以雙向傳輸信息的信道),每端都需要一個完整的編/譯碼系統(tǒng)。此程序就是為這樣的信息收發(fā)站寫一個Huffman碼的編/譯碼系統(tǒng)。</p><p><b> 程序的輸入和輸出:</b></p><p> 從終端讀入字符集大小n,以及n個字符及各個字符的權(quán)值,建立赫夫曼樹,并將它存儲到文件hf
7、mTree中;利用已建好的赫夫曼樹將文件中的字符編碼,如果赫夫曼樹不在內(nèi)存中,則從文件hfmTree中讀取到內(nèi)存;將譯得的代碼存到文件CodeFile中;利用已建好的赫夫曼樹對CodeFile中的代碼進行譯碼,將結(jié)果存入文件TextFile中;最后將已在內(nèi)存中的哈夫曼樹以直觀的方式(樹或凹入表形式)顯示在終端上,同時將此字符形式的哈夫曼樹寫入文件TreePrint中。</p><p><b> 程序要
8、達到的功能:</b></p><p> 用戶可以利用菜單根據(jù)自己的需要來選擇要進行編碼或是譯碼,并將轉(zhuǎn)換好的字符或編碼以文件的形式存到相應(yīng)的文件里面。</p><p><b> 測試數(shù)據(jù)如下表:</b></p><p> ?。╨)利用教材中的數(shù)據(jù)調(diào)試程序。</p><p> ?。?)用下表給出的字符集和頻
9、度的實際統(tǒng)計數(shù)據(jù)建立哈夫曼樹,并實現(xiàn)以下報文的編碼和譯碼:"THIS PROGRAM IS MY FAVORITE"。</p><p> 選擇E,輸入THIS PROGRAM IS MY FAVORITE,屏幕上顯示11010001011000111111000100010100110000100101010110010111011000111111100101000111111100111
10、01011000001001001001101101010</p><p> 同時文件codefile里面也出現(xiàn)相應(yīng)的代碼</p><p> 選擇D,從codefile中調(diào)入代碼,終端顯示THIS PROGRAM IS MY FAVORITE,并且文件textfile中也相應(yīng)的存入了這段話。</p><p> 選擇P,文件CodeFile以緊湊格式顯示在終端上
11、。</p><p> 選擇T,將已在內(nèi)存中的哈夫曼樹以直觀的方式(樹或凹入表形式)顯示在終端上,同時將此字符形式的哈夫曼樹寫入文件TreePrint中。</p><p> 選擇其他的字母,將出現(xiàn)出錯提示,并重新回到選擇菜單。</p><p><b> 概要設(shè)計</b></p><p> ADT BinaryTre
12、e{</p><p> 數(shù)據(jù)對象D:D是具有相同特性的數(shù)據(jù)元素集合。</p><p><b> 數(shù)據(jù)關(guān)系R:</b></p><p> 若D為空,則R為空,稱Huffmantree為空霍夫曼樹;</p><p> 若D不為空,則R={H},H是如下的二元關(guān)系:</p><p> 1、 H
13、滿足二叉樹的所有要求;</p><p> 2、 H中所有數(shù)乘以該數(shù)所在節(jié)點的深度值之后和最小。</p><p><b> 基本操作P:</b></p><p> InputHuffman(Huffman Hfm) </p><p> 操作結(jié)果:輸入并存儲字符和相應(yīng)權(quán)值。</p><p>
14、 Select(HuffmanTree HT,int end,int *s1,int *s2)</p><p> 初始條件:頻率數(shù)組已經(jīng)建立。</p><p> 操作結(jié)果:選擇HT[1....i-1]中無雙親且權(quán)值最小的兩個節(jié)點,其序號為s1,s2。</p><p> HuffmanCoding(Huffman Hfm)</p><p>
15、; 初始條件:頻率數(shù)組已經(jīng)建立。</p><p> 操作結(jié)果:w存放n個字符的權(quán)值(均>0),構(gòu)造赫夫曼樹HT,并求出n個字符的構(gòu)造赫夫曼編碼HC。</p><p> InitHuffman(Huffman Hfm)</p><p> 初始條件:頻率數(shù)組已經(jīng)建立。</p><p> 操作結(jié)果:要求用戶輸入字符和相應(yīng)權(quán)值,初
16、始化赫夫曼數(shù)</p><p> Encoding(Huffman Hfm)</p><p> 初始條件:霍夫曼樹HuffmanTree已經(jīng)存在。</p><p> 操作結(jié)果:利用已建好的Huffman樹(如不在內(nèi)存,則從文件hfmTree中讀入),對文件ToBeTran中的正文進行編碼,然后將結(jié)果存入文件CodeFile中。</p><p&
17、gt; Decoding(Huffman Hfm)</p><p> 初始條件:霍夫曼樹HuffmanTree已經(jīng)存在。</p><p> 操作結(jié)果:利用已建好的Huffman樹將文件CodeFile中的代碼進行譯碼,結(jié)果存入文件TextFile中。</p><p> Print(Huffman Hfm)</p><p> 初始條件
18、:霍夫曼樹HoffmanTree已經(jīng)存在。</p><p> 操作結(jié)果:將文件CodeFile以緊湊格式顯示在終端上,每行50 個代碼。</p><p> Treeprint(Huffman Hfm)</p><p> 初始條件:霍夫曼樹HuffmanTree已經(jīng)存在。</p><p> 操作結(jié)果:將已在內(nèi)存中的哈夫曼樹以凹入表的形式
19、顯示在終端上,同時將此字符形式的哈夫曼樹寫入文件TreePrint中。</p><p> }ADT HuffmanTree</p><p><b> 2 主程序流程</b></p><p> Void main()</p><p><b> {</b></p><p&g
20、t;<b> 顯示菜單;</b></p><p><b> Switch(k)</b></p><p><b> { </b></p><p><b> I:初始化</b></p><p><b> E:編碼</b><
21、/p><p><b> D:譯碼</b></p><p><b> P:印代碼文件</b></p><p><b> T:印哈夫曼樹</b></p><p><b> Q:退出運行</b></p><p><b>
22、} </b></p><p><b> }</b></p><p><b> 程序調(diào)用模塊</b></p><p><b> 詳細(xì)設(shè)計</b></p><p> 3.1數(shù)據(jù)類型: </p><p> typedef char
23、**HuffmanCode;//動態(tài)分配數(shù)組存儲霍夫曼表碼表</p><p> typedef struct{</p><p> unsigned int weight;</p><p> unsigned int parent,lchild,rchild;</p><p> }HTNode,*HuffmanTree;//動態(tài)
24、分配數(shù)組存儲霍夫曼樹</p><p> typedef struct{</p><p> HuffmanTree HT;</p><p> char *c;</p><p> int length;</p><p> HuffmanCode HC;</p><
25、p> }Huffman;//分配數(shù)組存儲字符串及其對應(yīng)的霍夫曼樹</p><p> Huffman Hfm;</p><p> char k; /*控制循環(huán)的標(biāo)志*/</p><p><b> 3.2 偽碼算法:</b></p><p><b> 主程序</b></p>
26、<p><b> main()</b></p><p><b> {</b></p><p> InitHuffman(Huffman Hfm);</p><p> Encoding(Huffman Hfm);</p><p> Decoding(Huffman Hfm);&l
27、t;/p><p> Print(Huffman Hfm);</p><p> Treeprint(Huffman Hfm);</p><p><b> }</b></p><p><b> 其他模塊:</b></p><p> void Select(HuffmanTr
28、ee HT,int end,int *s1,int *s2)//選擇HT[1....i-1]中無雙親且權(quán)值最小的兩個節(jié)點,其序號為s1,s2</p><p> FOR (i=1;i<=end;i++)</p><p><b> {</b></p><p> IF(HT[i].parent是最小的)</p><p&
29、gt; THEN HT[i].parent——>*s1</p><p> IF(HT[i].parent是次最小的)</p><p> THEN HT[i].parent——>*s2</p><p><b> }</b></p><p> Huffman HuffmanCoding(Huffma
30、n Hfm) //w存放n個字符的權(quán)值(均〉0),構(gòu)造赫夫曼樹HT,并求出n個字符的構(gòu)造赫夫曼編碼HC</p><p><b> {</b></p><p> FOR(i=n+1;i<=2*n-1;++i) //選擇HT[1....i-1]中無雙親且權(quán)值最小的兩個節(jié)點,其序號為s1,s2</p><p><b> {<
31、;/b></p><p> Select(Hfm.HT,i-1,&s1,&s2);</p><p> 修改父親位置; </p><p><b> 修改孩子位置;</b></p><p> 父親結(jié)點權(quán)值為左右孩子權(quán)值之和;</p><p><b> }&
32、lt;/b></p><p> //從葉子結(jié)點到根逆向求每個字符的赫夫曼編碼</p><p> FOR(i=1;i<=n;++i)</p><p> //逐個字符求赫夫曼編碼</p><p> { start=n-1;//編碼結(jié)束符位置</p><p> for(c=i,f=Hfm.HT[i].p
33、arent;f!=0;c=f,f=Hfm.HT[f].parent)</p><p> //從葉子到根逆向求編碼</p><p><b> {</b></p><p> IF(c==Hfm.HT[f].lchild) cd[--start]='0';</p><p> ELSE cd[--sta
34、rt]='1';</p><p><b> }</b></p><p> 再從cd復(fù)制編碼到Hfm.HC</p><p><b> }</b></p><p> RETURN Hfm;</p><p><b> }</b><
35、;/p><p> Huffman InitHuffman(Huffman Hfm)//初始化赫夫曼數(shù),要求用戶輸入字符和相應(yīng)權(quán)值</p><p><b> {</b></p><p> 對文件hfmTree以讀文本的形式打開</p><p> IF(fp==NULL)</p><p> 調(diào)用
36、InputHuffman函數(shù),用戶輸入字符和相應(yīng)權(quán)值存入赫夫曼數(shù)中</p><p><b> ELSE</b></p><p> 輸出"The Huffmantree has already existed!\nPlease choose again!\n\n");</p><p> 讀入hfmTree中文本 &l
37、t;/p><p> FOR(i=1;i<=n;i++)</p><p> 作為獨立結(jié)點對結(jié)點的parent,lchild,rchild分別賦值0</p><p> FOR(;i<=2*n-1;++i)</p><p> 作為獨立結(jié)點對結(jié)點的weight,parent,lchild,rchild分別賦值0 </p&g
38、t;<p> Hfm=HuffmanCoding(Hfm);</p><p> RETURN Hfm;</p><p><b> }</b></p><p> void Encoding(Huffman Hfm)//利用已建好的Huffman樹(如不在內(nèi)存,則從文件hfmTree中讀入),對文件ToBeTran中的正文進行
39、編碼,然后將結(jié)果存入文件CodeFile中。</p><p><b> {</b></p><p> 輸出"\n\n*******************Encoding**************************\n\n"</p><p> IF((ffp=fopen("ToBeTran"
40、,"rt"))==NULL)</p><p> 提示輸入"Please input the sentence: "</p><p> scanf("%s",ch);</p><p> printf("\n");</p><p> 以寫文本的形式打開Code
41、File</p><p><b> ELSE</b></p><p> 讀入ToBeTran文件中的字符;</p><p> WHILE(ch[j])</p><p> FOR(i=1;i<=n;i++)</p><p> IF(ch[j]==Hfm.c[i])</p>
42、<p> 分別在終端和文件CodeFile輸入Hfm.HC[i]</p><p> void Decoding(Huffman Hfm)//利用已建好的Huffman樹將文件CodeFile中的代碼進行譯碼,結(jié)果存入文件TextFile中。</p><p> { 定義char d[500]</p><p> 輸出"\n\n******
43、************Decoding************************\n\n"</p><p> IF((fp=fopen("CodeFile","rt"))==NULL)</p><p> 輸出Please input the code:;</p><p><b> ELSE
44、 </b></p><p> 將文件Codefile中的內(nèi)容讀到d數(shù)組中</p><p> 輸出The file is :</p><p> 以寫文本的方式打開TextFile</p><p> WHILE(d[j])</p><p> 根到葉子結(jié)點遍歷,并按照lchild——>0,rch
45、ild——>1來輸出</p><p> 入到文件TextFile中</p><p><b> 關(guān)閉文件</b></p><p><b> }</b></p><p> void Print(Huffman Hfm)//將文件CodeFile以緊湊格式,示在終端上,每行50 個代碼。&l
46、t;/p><p><b> {</b></p><p> FOR(i=1;i<=n;i++)</p><p> 輸出Hfm.c[i]</p><p> 輸出Hfm.HT[i].weight</p><p> 以只讀二進制的方式打開CodeFile文件</p><p&
47、gt; while ( feof(fprint)==0 )</p><p><b> 逐個輸出</b></p><p> IF (m%50==0)</p><p><b> 輸出"\n"</b></p><p><b> 關(guān)閉文件</b></
48、p><p><b> }</b></p><p> void Treeprint(Huffman Hfm)//將已在內(nèi)存中的哈夫曼樹以凹入表的形式顯示在終端上,同時將此字符形式的哈夫曼樹寫入文件TreePrint中。</p><p><b> {</b></p><p> 打開hfmTree文件
49、</p><p> 將字符及其對應(yīng)的代碼賦給變量Hfm.c[i]和Hfm.c[i][j]</p><p> 輸出Hfm.c[i],對Hfm.c[i][j]進行判斷,不是\n則輸出*,否則停止輸出</p><p><b> }</b></p><p> 3.3函數(shù)調(diào)用關(guān)系圖</p><p>
50、<b> 調(diào)試分析</b></p><p> 4.1 調(diào)試過程中遇到的問題:</p><p> 第一個問題是一直比較棘手的問題就是文件的調(diào)用與寫入,因為文件方面的知識一直就掌握的不是很好,在寫代碼時產(chǎn)生很大困難,所以在解決這個問題的時候我把文件部分系統(tǒng)的看了一下,這才從自身角度解決了這個問題。而實際中遇到的問題就是如何判斷已經(jīng)有了hfmtree這個文件,并且怎么
51、調(diào)用到內(nèi)存中來。</p><p> 解決方案:設(shè)置一個全局結(jié)構(gòu)體變量來存放已經(jīng)在文件中存放的霍夫曼樹。</p><p> 第二個問題是關(guān)于界面的美觀設(shè)計方面,因為很多代碼在文本中編輯時是比較整齊美觀的,但是在程序運行中卻出現(xiàn)很多問題,不對齊等等。還有就是換行符的使用,一不小心就會產(chǎn)生偏差。</p><p> 解決方案:進入程序進行調(diào)試,檢查每段輸出代碼的顯示。
52、</p><p> 第三個問題是Huffman樹的打印,方式為凹入式打印,由于在當(dāng)時學(xué)習(xí)的時候這部分內(nèi)容沒有留意,根本沒有概念,所以在編寫程序過程中出現(xiàn)了嚴(yán)重的問題。導(dǎo)致該項功能無法完成。</p><p> 解決方案:尚未完善解決,只是將內(nèi)存中的哈夫曼樹中各節(jié)點的值及其孩子輸出。</p><p> 4.2 算法的時空分析:</p><p&g
53、t;<b> 算法的時間復(fù)雜度:</b></p><p> Select(HuffmanTree HT,int end,int *s1,int *s2) O(n)</p><p> HuffmanCoding(Huffman Hfm) O(n2)</p><p> InputHuffman(Huffm
54、an Hfm) O(n)</p><p> InitHuffman(Huffman Hfm) O(n)</p><p> Encoding(Huffman Hfm) O(n)</p><p> Decoding(Huffman Hfm)
55、 O(n)</p><p> Print(Huffman Hfm) O(n)</p><p> 4.3 經(jīng)驗與體會:</p><p> 整個程序在編的時候思路是很明朗的,包括菜單的設(shè)置都是很清晰的,但是如何通過一個菜單將所有涉及到的文件與終端聯(lián)系起來還有打印哈夫曼樹都是比較困難的問題,由于
56、文件這一章節(jié)我們以前學(xué)習(xí)的時候并沒有很重視,所以在運用的時候遇到了很大的困難,同時通過這次的設(shè)計我也看到其實文件這一章是很重要的,我們做了一個程序,必須要把有些必要的數(shù)據(jù)進行保存,如果只是停留在內(nèi)存中那就很難在以后被重復(fù)利用,會很大程度上提高我們調(diào)試的效率;另外凹入式打印哈夫曼樹更是讓我頭疼了一整天的問題,由于根本不知道其概念是什么,更不用說去編寫代碼了。同時我也覺得有些細(xì)節(jié)問題是很重要的,不管是一個整型變量還是一個結(jié)構(gòu)體變量,有時候?qū)?/p>
57、整個程序起著至關(guān)重要的作用。</p><p><b> 用戶使用說明</b></p><p> 1.本程序的運行環(huán)境為DOS操作系統(tǒng),執(zhí)行文件為:hfmtree.exe。</p><p> 2. 運行程序后出現(xiàn)選擇菜單。</p><p> 3.根據(jù)提示選擇相應(yīng)的操作,初始化,編碼,譯碼,印代碼文件,印哈夫曼樹&l
58、t;/p><p> 退出,每次選擇完,都會再次彈出選擇菜單供用戶選擇。結(jié)束符為回車鍵。</p><p><b> 測試結(jié)果</b></p><p> 在進入系統(tǒng)以后,選擇第一個初始化,按要求鍵入要求的字符及其頻度</p><p><b> 截圖如下所示:</b></p><p
59、><b> 圖1</b></p><p> 進入程序,顯示的菜單界面</p><p><b> 圖2</b></p><p> 輸入I,選擇進行初始化</p><p><b> 圖3</b></p><p> 初始化時對字符的個數(shù)進行限
60、制,不得少于2個。</p><p><b> 圖4、5</b></p><p> 在字符個數(shù)處輸入“27”,之后依次輸入各字符及其權(quán)值。</p><p><b> 圖6</b></p><p> 在菜單界面選擇E,出現(xiàn)提示語句,要求輸入句子。</p><p><
61、b> 圖7</b></p><p> 輸入“THIS_PROGRAM_IS_MY_FAVORITE”,回車之后,顯示出該句的哈夫曼編碼。</p><p> ?。ù颂帪榍蠛喗?,將空格用下劃線“_”作為代替)</p><p><b> 圖8</b></p><p> 在菜單界面選擇D,則對文件中已有
62、的哈夫曼編碼進行反譯,將譯出的字符顯示出來。</p><p><b> 圖9</b></p><p> 在菜單界面選擇P,將文件中的哈夫曼編碼緊湊輸出,每行50個。結(jié)果如下圖:</p><p><b> 圖10、11</b></p><p> 該程序中,我加入了將初始化的各字符的編碼輸出的語
63、句,可以看到各個字符的哈弗曼編碼。</p><p><b> 圖12</b></p><p> 這3行數(shù)字便是緊湊輸出哈夫曼編碼的結(jié)果。</p><p><b> 圖13</b></p><p> 同時,不同的人使用本程序進行不同的哈夫曼編碼時,由于前一位使用者初始化的數(shù)據(jù)后一位不一定同樣適
64、用,為了避免這種情況,因此當(dāng)已經(jīng)初始化后再進行初始化時會出現(xiàn)提示是否重新初始化的信息提示,如上圖所示。</p><p><b> 圖14</b></p><p> 在菜單界面選擇T,打印處內(nèi)存中的哈夫曼樹各節(jié)點的值及其雙親節(jié)點和子節(jié)點。</p><p><b> 圖15</b></p><p>
65、; TEXTFILE.TXT文本文件,記錄用戶輸入的需要進行編碼的句子。</p><p><b> 圖16</b></p><p> CODEFILE.TXT文本文件,記錄TEXTFILE.TXT文本文件中字符的哈弗曼編碼。</p><p><b> 圖17</b></p><p> HF
66、MTREE.TXT文本文件,記錄輸入的各字符及其權(quán)值</p><p><b> 附錄</b></p><p><b> 源程序文件名清單:</b></p><p> TEXTFILE.TXT 記錄待編碼的句子</p><p> CODEFILE.TXT 記錄哈
67、夫曼編碼</p><p> HFMTREE.TXT 記錄字符個數(shù)、名稱及權(quán)值</p><p><b> 源代碼:</b></p><p> #include <stdio.h></p><p> #include <string.h></p><p&g
68、t; #include <malloc.h></p><p> #include<stdlib.h></p><p> #include<ctype.h></p><p> #define NULL 0</p><p> #define OK 1</p><p> #de
69、fine ERROR 0</p><p> #define OVERFLOW -2</p><p> #define MAX_NUM 32767</p><p> #define MAX 60</p><p> typedef char **HuffmanCode;//動態(tài)分配數(shù)組存儲哈夫曼表碼表</p><p&g
70、t; typedef struct{</p><p> unsigned int weight;</p><p> unsigned int parent,lchild,rchild;</p><p> }HTNode,*HuffmanTree;//動態(tài)分配數(shù)組存儲哈夫曼樹</p><p> typedef struct{&
71、lt;/p><p> HuffmanTree HT;</p><p> char *c;</p><p> int length;</p><p> HuffmanCode HC;</p><p> }Huffman;//全局結(jié)構(gòu)體變量,來存儲字符與代碼</p><
72、;p> void Select(HuffmanTree HT,int end,int *s1,int *s2)//選擇HT[1....i-1]中無雙親且權(quán)值最小的兩個節(jié)點,其序號為s1,s2</p><p><b> {</b></p><p><b> int i;</b></p><p> int min
73、1=MAX_NUM;</p><p><b> int min2;</b></p><p> for (i=1;i<=end;i++)//遍歷查找權(quán)值最小的結(jié)點S1</p><p><b> {</b></p><p> if (HT[i].parent==0&&HT[
74、i].weight<min1)</p><p><b> {</b></p><p><b> *s1=i;</b></p><p> min1=HT[i].weight;</p><p><b> }</b></p><p><b&
75、gt; }</b></p><p> min2=MAX_NUM;</p><p> for(i=1;i<=end;i++)//遍歷查找除S1外權(quán)值最小的結(jié)點S2</p><p><b> {</b></p><p> if(HT[i].parent==0&&(*s1!=i)&a
76、mp;&min2>HT[i].weight)</p><p><b> {</b></p><p><b> *s2=i;</b></p><p> min2=HT[i].weight;</p><p><b> }</b></p><
77、p><b> }</b></p><p><b> }</b></p><p> Huffman HuffmanCoding(Huffman Hfm) //存放n個字符的權(quán)值(均〉0),構(gòu)造哈夫曼樹HT,并求出n個字符的構(gòu)造哈夫曼編碼HC</p><p><b> {</b></p
78、><p> int i,n,m,s1,s2,start;</p><p><b> int c,f;</b></p><p><b> char *cd;</b></p><p> n=Hfm.length;</p><p> if(n<=1) return H
79、fm;</p><p><b> m=2*n-1;</b></p><p> for(i=n+1;i<=m;++i) //選擇HT[1....i-1]中無雙親且權(quán)值最小的兩個節(jié)點,其序號為s1,s2</p><p><b> {</b></p><p> Select(Hfm.HT,i
80、-1,&s1,&s2);</p><p> Hfm.HT[s1].parent=i;//修改父親位置</p><p> Hfm.HT[s2].parent=i;</p><p> Hfm.HT[i].lchild=s1;//修改孩子位置</p><p> Hfm.HT[i].rchild=s2;</p>
81、<p> Hfm.HT[i].weight=Hfm.HT[s1].weight+Hfm.HT[s2].weight;//父親結(jié)點權(quán)值為左右孩子權(quán)值之和</p><p><b> }</b></p><p> //從葉子結(jié)點到根逆向求每個字符的哈夫曼編碼</p><p> Hfm.HC=(HuffmanCode)malloc((
82、n+1)*sizeof(char *));//分配n個字符編碼的頭指針向量</p><p> cd=(char *)malloc(n*sizeof(char));//分配求編碼的工作空間</p><p> cd[n-1]='\0';//編碼結(jié)束符</p><p> for(i=1;i<=n;++i)//逐個字符求哈夫曼編碼</p&g
83、t;<p><b> {</b></p><p> start=n-1;//編碼結(jié)束符位置</p><p> for(c=i,f=Hfm.HT[i].parent;f!=0;c=f,f=Hfm.HT[f].parent)//從葉子到根逆向求編碼</p><p><b> {</b></p>
84、<p> if(c==Hfm.HT[f].lchild) cd[--start]='0';</p><p> else cd[--start]='1';</p><p><b> }</b></p><p> Hfm.HC[i]=(char *)malloc((n-start)*sizeo
85、f(char));</p><p> strcpy(Hfm.HC[i],&cd[start]);//從cd復(fù)制編碼到Hfm.HC</p><p><b> }</b></p><p> free(cd);//釋放工作空間</p><p> return Hfm;</p><p>&
86、lt;b> }</b></p><p> Huffman InputHuffman(Huffman Hfm)//輸入函數(shù),控制用戶輸入字符和相應(yīng)權(quán)值</p><p><b> {</b></p><p><b> int i,n;</b></p><p> printf(
87、"\n\n********************Initialization*********************\n");</p><p> printf("The chars and weights will be saved in the file :\hfmTree\ \n");</p><p> printf("Plea
88、se input the number of the chars: ");</p><p> scanf("%d",&n);</p><p> if(n<=1) </p><p> {printf("Only One Char!There Is No Need For Coding!");
89、//若只有一個數(shù)值則無需編碼</p><p> printf("\n");</p><p> printf("Please input the number of the chars: ");</p><p> scanf("%d",&n);}</p><p> Hf
90、m.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));</p><p> Hfm.c=(char *)malloc((n+1)*sizeof(char));</p><p> for(i=1;i<=n;i++)</p><p><b> {</b></p><p>
91、printf("Please input the char: ");</p><p> scanf("%s",&Hfm.c[i]);</p><p> printf("Please input the weight of the char: ");</p><p> scanf("%
92、d",&Hfm.HT[i].weight);</p><p> Hfm.HT[i].parent=0;</p><p> Hfm.HT[i].lchild=0;</p><p> Hfm.HT[i].rchild=0;</p><p><b> }</b></p><p>
93、; for(;i<=2*n-1;++i)</p><p><b> {</b></p><p> Hfm.HT[i].weight=0;</p><p> Hfm.HT[i].parent=0;</p><p> Hfm.HT[i].lchild=0;</p><p> Hfm.
94、HT[i].rchild=0;</p><p><b> }</b></p><p> Hfm.length=n;</p><p> return Hfm;</p><p><b> } </b></p><p> Huffman InitHuffman(Huffm
95、an Hfm)//初始化哈夫曼數(shù),要求用戶輸入字符和相應(yīng)權(quán)值</p><p><b> {</b></p><p> int n,i,x;</p><p><b> FILE *fp;</b></p><p> fp=fopen("hfmTree","rt&qu
96、ot;);//對文件hfmTree以讀文本的形式打開</p><p> if(fp==NULL)</p><p><b> {</b></p><p> Hfm=InputHuffman(Hfm);//調(diào)用InputHuffman函數(shù),用戶輸入字符和相應(yīng)權(quán)值存入哈夫曼數(shù)中</p><p> fp=fopen(&q
97、uot;hfmTree","wt");</p><p> fprintf(fp,"%d\n",Hfm.length);</p><p> for(i=1;i<=Hfm.length;i++)</p><p> fprintf(fp,"%c %d ",Hfm.c[i],Hfm.HT[i
98、].weight);</p><p> rewind(fp);</p><p><b> }</b></p><p><b> else</b></p><p> {printf("The Huffmantree has already existed!\nDo You Want
99、To Make A New One?('Y'or'N')\n\n");//詢問是否重新初始化</p><p> scanf("%s",&x);</p><p> if(x=='Y')</p><p> { Hfm=InputHuffman(Hfm);//調(diào)用InputHuff
100、man函數(shù),用戶輸入字符和相應(yīng)權(quán)值存入哈弗曼數(shù)中</p><p> fp=fopen("hfmTree","w+");</p><p> fprintf(fp,"%d\n",Hfm.length);</p><p> for(i=1;i<=Hfm.length;i++)</p>&
101、lt;p> fprintf(fp,"%c %d ",Hfm.c[i],Hfm.HT[i].weight);</p><p> rewind(fp);</p><p><b> }</b></p><p><b> else</b></p><p> {fscan
102、f(fp,"%d\n",&n);</p><p> Hfm.c=(char *)malloc((n+1)*sizeof(char));</p><p> Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));</p><p> for(i=1;i<=n;i++)</p>
103、<p> fscanf(fp,"%s %d ",&Hfm.c[i],&Hfm.HT[i].weight);//將已經(jīng)在文件中的字符和其對應(yīng)的權(quán)重輸入到Hfm.c[i]和&Hfm.HT[i].weight中</p><p> for(i=1;i<=n;i++)//對每個節(jié)點初始化</p><p><b> {
104、 </b></p><p> Hfm.HT[i].parent=0;</p><p> Hfm.HT[i].lchild=0;</p><p> Hfm.HT[i].rchild=0;</p><p><b> }</b></p><p> for(;i<=2*
105、n-1;++i)</p><p><b> {</b></p><p> Hfm.HT[i].weight=0;</p><p> Hfm.HT[i].parent=0;</p><p> Hfm.HT[i].lchild=0;</p><p> Hfm.HT[i].rchild=0;&
106、lt;/p><p><b> }</b></p><p> Hfm.length=n;</p><p><b> }</b></p><p><b> }</b></p><p> fclose(fp);</p><p>
107、 Hfm=HuffmanCoding(Hfm);</p><p> return Hfm;</p><p><b> }</b></p><p> void Encoding(Huffman Hfm)//利用已建好的Huffman樹(如不在內(nèi)存,則從文件hfmTree中讀入),對文件ToBeTran中的正文進行編碼,然后將結(jié)果存入文件Co
108、deFile中。</p><p><b> {</b></p><p> int i=0,j=0,n;</p><p> char ch[MAX];</p><p> FILE *fp,*fw;</p><p> n=Hfm.length;</p><p> p
109、rintf("\n\n*******************Encoding**************************\n\n");</p><p> if((fw=fopen("ToBeTran","r+"))==NULL)//嘗試打開ToBeTran</p><p><b> {</b>&l
110、t;/p><p> printf("\nPlease input the sentence: ");</p><p> scanf("%s",ch);</p><p> printf("\n");</p><p> fp=fopen("CodeFile",&q
111、uot;wt+");</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> fscanf(fw,"%s",ch);</p><p>
112、 fclose(fw);</p><p><b> }</b></p><p> while(ch[j])</p><p><b> {</b></p><p> for(i=1;i<=n;i++)</p><p> if(ch[j]==Hfm.c[i])&
113、lt;/p><p><b> {</b></p><p> printf("%s",Hfm.HC[i]);</p><p> fprintf(fp,"%s",Hfm.HC[i]);</p><p><b> break;</b></p>&l
114、t;p><b> }</b></p><p><b> j++;</b></p><p><b> }</b></p><p> printf("\n");</p><p> rewind(fp);</p><p>
115、 fclose(fp);</p><p><b> }</b></p><p> void Decoding(Huffman Hfm)//利用已建好的Huffman樹將文件CodeFile中的代碼進行譯碼,結(jié)果存入文件TextFile中。</p><p><b> {</b></p><p>
116、 HuffmanTree p;</p><p><b> int i,n;</b></p><p><b> int j=0;</b></p><p> char d[500];</p><p><b> FILE *fp;</b></p><p&
117、gt; n=Hfm.length;</p><p> printf("\n\n******************Decoding************************\n\n");</p><p> if((fp=fopen("CodeFile","r+"))==NULL)</p><p>
118、;<b> {</b></p><p> printf("Please input the code:");</p><p> scanf("%s",d);</p><p><b> }</b></p><p><b> else</
119、b></p><p><b> {</b></p><p> fscanf(fp,"%s",d);//將文件中的字符輸入到數(shù)組d中</p><p> fclose(fp);</p><p><b> }</b></p><p> print
120、f("\nThe file is : ");</p><p> fp=fopen("TextFile","wt+");//以寫入文件的形式打開TextFile</p><p> while(d[j])</p><p><b> {</b></p><p>
121、 p=&Hfm.HT[2*n-1];</p><p> while(p->lchild||p->rchild)</p><p><b> {</b></p><p> if(d[j]=='0')</p><p> { i=p->lchild; p=&Hfm.H
122、T[i]; }</p><p><b> else</b></p><p> { i=p->rchild; p=&Hfm.HT[i]; }</p><p><b> j++;</b></p><p><b> }</b></p><p
123、> printf("%c",Hfm.c[i]);</p><p> fprintf(fp,"%c",Hfm.c[i]);</p><p><b> }</b></p><p> printf("\n");</p><p> fclose(fp);
124、</p><p><b> }</b></p><p> void Print(Huffman Hfm)//將文件CodeFile以緊湊格式顯示在終端上,每行50 個代碼。</p><p><b> {</b></p><p><b> int i,n;</b><
125、/p><p> int m=1;//計數(shù)器</p><p><b> char ch;</b></p><p> FILE* fprint;</p><p> n=Hfm.length;</p><p> printf("\n\n******************Output t
126、he code of the chars****************\n\n");</p><p> for(i=1;i<=n;i++)//顯示每一個字符對應(yīng)的哈夫曼編碼</p><p><b> {</b></p><p> printf("\n");</p><p>
127、printf("Char: %c\t",Hfm.c[i]);</p><p> printf("Weight: %d\t",Hfm.HT[i].weight);</p><p> printf("Code: ");</p><p> puts(Hfm.HC[i]);</p><p&
128、gt;<b> }</b></p><p> fprint=fopen("CodeFile","rb");</p><p> while ( feof(fprint)==0 )</p><p><b> {</b></p><p> ch=fgetc
129、(fprint);</p><p> printf("%c",ch);</p><p><b> m++;</b></p><p> if (m%50==0)//保證每一行輸出50個字符</p><p> printf("\n");</p><p>
130、<b> }</b></p><p> printf("\n");</p><p> fclose(fprint);</p><p><b> }</b></p><p> void main()</p><p><b> { &l
131、t;/b></p><p> Huffman Hfm;</p><p> char k; /*控制循環(huán)的標(biāo)志*/</p><p><b> while(1)</b></p><p> { printf(" --------------------------------------\n"
132、;);</p><p> printf(" |Thank You To Use MY Huffman Program |\n");</p><p> printf(" | |\n");</p><p> printf(" |
133、 I.Initialization |\n");</p><p> printf(" | E.Encoding |\n");</p><p> printf(" | D.Decoding |\n");</p&
134、gt;<p> printf(" | P.Printing |\n");</p><p> printf(" | T.TreePrint |\n");</p><p> printf(" | Q.Ex
135、it |\n");</p><p> printf(" --------------------------------------\n");</p><p> printf(" Please Input Your Option\n");</p><p> scanf(&q
136、uot;%c",&k);</p><p> k=toupper(k);</p><p><b> switch(k)</b></p><p> { case 'I': Hfm=InitHuffman(Hfm); getchar();break;</p><p> case
137、9;E': Encoding(Hfm); getchar();break;</p><p> case 'D': Decoding(Hfm); getchar();break;</p><p> case 'P': Print(Hfm); getchar();break;</p>&l
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計赫夫曼編碼譯碼器
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告--赫夫曼編碼譯碼器
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計----huffman樹編碼和譯碼
- 赫夫曼編譯碼器數(shù)據(jù)結(jié)構(gòu)課程設(shè)計
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計-哈夫曼編碼譯碼器
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計--數(shù)據(jù)結(jié)構(gòu)課程設(shè)計----huffman編碼
- 哈夫曼(huffman)編譯碼器課程設(shè)計
- 哈夫曼(huffman)編譯碼器課程設(shè)計
- 課程設(shè)計-赫夫曼編譯碼器數(shù)據(jù)結(jié)構(gòu)設(shè)計
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告(huffman編碼器)
- 數(shù)據(jù)結(jié)構(gòu)--huffman編碼和譯碼
- 赫夫曼編譯碼器的實現(xiàn)數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告
- 數(shù)據(jù)結(jié)構(gòu)哈夫曼編碼譯碼器課程設(shè)計報告(有源程序)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告--huffman編碼與文件壓縮
- 課程設(shè)計---pcm編譯碼器設(shè)計
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計---哈弗曼編碼譯碼
- pcm_編譯碼器設(shè)計及應(yīng)用課程設(shè)計
- 通信原理課程設(shè)計-dpcm編譯碼器設(shè)計及應(yīng)用
- 哈夫曼編碼譯碼數(shù)據(jù)結(jié)構(gòu)課程設(shè)計
- 數(shù)據(jù)結(jié)構(gòu)及其應(yīng)用(算法與數(shù)據(jù)結(jié)構(gòu)課程設(shè)計)
評論
0/150
提交評論