版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、<p> 《數(shù)據(jù)結(jié)構(gòu)與算法設(shè)計(jì)》</p><p><b> 課程設(shè)計(jì)任務(wù)書</b></p><p> 以Java編程語言,要求軟件帶有簡單的GUI(利用AWT或者Swing實(shí)現(xiàn));</p><p><b> 附:報(bào)告格式</b></p><p> 數(shù)據(jù)結(jié)構(gòu)與算法設(shè)計(jì)課程設(shè)計(jì)<
2、;/p><p> 【設(shè)計(jì)題目】 哈弗曼編碼</p><p><b> 【問題描述】 </b></p><p> 哈弗曼編碼在數(shù)據(jù)壓縮方面應(yīng)用十分廣泛.本課程設(shè)計(jì)主要是用哈弗曼樹(最優(yōu)二叉樹)實(shí)現(xiàn)字符串編碼及哈弗曼樹的GUI輸出,并驗(yàn)證哈弗曼編碼能否與實(shí)際應(yīng)用相吻合,進(jìn)而總結(jié)哈弗曼樹的實(shí)際應(yīng)用價值.</p><p&
3、gt;<b> 【軟件功能】</b></p><p> 1) 實(shí)現(xiàn)哈弗曼樹的構(gòu)建;</p><p> 2)利用哈弗曼樹生成葉結(jié)點(diǎn)字符的哈弗曼編碼;</p><p> 3) 實(shí)現(xiàn)各字符哈弗曼編碼及哈弗曼樹的GUI界面輸出.</p><p><b> 【算法思想】</b></p>
4、<p> ?。ㄒ唬┕ヂ幋a利用的抽象數(shù)據(jù)存儲結(jié)構(gòu)是鏈表、數(shù)組和基于鏈表的二叉樹。在實(shí)現(xiàn)過程中先將各字符根據(jù)權(quán)值從小到大存儲于在邏輯上連續(xù)葉節(jié)點(diǎn)的鏈表中,然后根據(jù)鏈表比較選取最小和次小兩權(quán)值建立子二叉樹,且子二叉樹根節(jié)點(diǎn)保存其子節(jié)點(diǎn)權(quán)值之和,通過子二叉樹根節(jié)點(diǎn)權(quán)值與鏈表上其他節(jié)點(diǎn)權(quán)值再比較,進(jìn)而合并,重組,循環(huán)最終構(gòu)建成基于鏈表的最優(yōu)二叉樹即哈弗曼樹。最后,使左分支為0,右分支為1,從葉節(jié)點(diǎn)向上直到根節(jié)點(diǎn)循環(huán)遍歷哈弗曼樹,獲
5、得各字符哈弗曼編碼,并保存于相應(yīng)字符的哈弗曼樹葉節(jié)點(diǎn)的順序存儲結(jié)構(gòu)數(shù)組中。 </p><p> ?。ǘ┕δ軐?shí)現(xiàn)模塊: </p><p> 1) 調(diào)用統(tǒng)計(jì)頻數(shù)函數(shù)和排序函數(shù),根據(jù)權(quán)值從小到大生成List<TreeNode>類型的鏈表;</p><p> 2) 調(diào)用建樹函數(shù),根據(jù)鏈表比較選取最小和次小兩權(quán)值建立二叉樹,記錄節(jié)點(diǎn)的左右孩子及雙親的位置
6、關(guān)系,最終構(gòu)建成哈弗曼樹,且記錄的左孩子權(quán)值小于右孩子;</p><p> 3) 調(diào)用編碼函數(shù),根據(jù)已建立的哈夫曼樹,從葉結(jié)點(diǎn)向上直到根結(jié)點(diǎn)建立哈夫曼編碼,并保存于相應(yīng)字符的哈弗曼樹葉結(jié)點(diǎn)的順序存儲結(jié)構(gòu)中。</p><p> 4) 調(diào)用遍歷函數(shù)和打印函數(shù),遍歷各字符的哈弗曼編碼并打印在GUI界面上;</p><p><b> 【邏輯結(jié)構(gòu)設(shè)計(jì)】<
7、/b></p><p> 本課程設(shè)計(jì)應(yīng)用的邏輯結(jié)構(gòu)設(shè)計(jì)包括:線性非連續(xù)的的鏈?zhǔn)酱鎯Y(jié)構(gòu)、線性連續(xù)的數(shù)組存儲結(jié)構(gòu)和基于鏈表的二叉樹。 </p><p><b> 【存儲結(jié)構(gòu)設(shè)計(jì)】</b></p><p> ?。?)哈弗曼樹結(jié)點(diǎn)存儲結(jié)構(gòu)設(shè)計(jì)類: </p><p> class TreeNode{</p&
8、gt;<p> private int weight; //統(tǒng)計(jì)該節(jié)點(diǎn)的字符屬性在文件中出現(xiàn)得頻率</p><p> private char ch; //節(jié)點(diǎn)的字符屬性</p><p> private TreeNode right;//右節(jié)點(diǎn)</p><p> private TreeNode left; //左節(jié)點(diǎn)</p&
9、gt;<p> private TreeNode parent; //父節(jié)點(diǎn)</p><p> private String hfmcode=""; //保存編碼的屬性</p><p> private static final int width=60; //JButton的寬度</p><p> private
10、static final int height=20; //JButton的高度</p><p> private int x,y; //節(jié)點(diǎn)的定位坐標(biāo)</p><p> private int depth=1; //默認(rèn)節(jié)點(diǎn)處位置的深度</p><p> .....及其屬性設(shè)置</p><p><b> }</b
11、></p><p> 利用ArrayList<TreeNode>順序鏈?zhǔn)酱鎯Y(jié)構(gòu)先存儲各字符及其權(quán)重,再根據(jù)權(quán)重構(gòu)建哈弗曼樹(最優(yōu)二叉樹)</p><p><b> 二叉樹如下:</b></p><p><b> 【基本操作設(shè)計(jì)】</b></p><p> 構(gòu)造哈夫曼樹的主
12、要實(shí)現(xiàn)方法:</p><p> public List<TreeNode> creatNodeList(String str)</p><p> //傳入字符串,生成一個結(jié)點(diǎn)鏈表;</p><p> public List<TreeNode> sortListW(List<TreeNode> list)</p>
13、<p> //按權(quán)重給結(jié)點(diǎn)從小到大排序;</p><p> public void sortListWofF(List<TreeNode> list)</p><p> //按父結(jié)點(diǎn)權(quán)重從小到大排序;</p><p> public void toList(TreeNode root, List<TreeNode> lis
14、t)</p><p> // 遍歷樹,生成存儲樹各結(jié)點(diǎn)的鏈表;</p><p> public TreeNode creatTree(List<TreeNode> nodeList, Graphics g,JFrame jf) </p><p> //根據(jù)權(quán)重創(chuàng)建哈弗曼樹;</p><p> 顯示哈弗曼樹主要方法:<
15、/p><p> public void creatUI() //創(chuàng)建操作界面界面及用于哈弗曼樹的顯示;</p><p> public void setNodeXYofRoot( TreeNode node,int a,int b)</p><p> //設(shè)置各結(jié)點(diǎn)位置;</p><p> public void drawNode(Lis
16、t<TreeNode> list, Graphics g)</p><p><b> //畫出各結(jié)點(diǎn);</b></p><p> public void drawLine(TreeNode root, Graphics g)</p><p> //畫出各結(jié)點(diǎn)之間的連線;</p><p> 哈弗曼編碼獲
17、取主要方法:</p><p> public void setHfmcode(TreeNode root)</p><p> //設(shè)置根結(jié)點(diǎn)哈弗曼編碼;</p><p> public String hfmcodeofSting(String s, TreeNode root)</p><p> //通過字符獲得哈弗曼編碼;</
18、p><p> public String Stingofhfmcode(String s, TreeNode root)</p><p> //通過哈弗曼編碼獲得字符。</p><p><b> 【模塊流程圖】</b></p><p><b> TreeNode類</b></p>
19、<p> Line類 </p><p> Shape類 </p><p><b> Shape類</b></p><p>
20、 ActionListener內(nèi)部類監(jiān)聽按鈕</p><p> 點(diǎn)擊 點(diǎn)擊 點(diǎn)擊 </p><p> creatTree() getText() getText()</p><p> 【生成樹圖】 hfmcodeofSting() St
21、ingofhfmcode()</p><p> setHfmcode() setText() setText()</p><p><b> 【界面設(shè)計(jì)】</b></p><p><b> 【用戶手冊】</b></p><p> 第一步:先將程序在eclipse運(yùn)行
22、,產(chǎn)生上述界面;</p><p> 第二步:在“請輸入要創(chuàng)建的樹碼”文本框輸入字符串,點(diǎn)擊“顯示哈弗曼樹”按鈕,在顯示區(qū)域?qū)@示樹圖;</p><p> 第三步:在“請輸入查詢字符”文本框輸入待查詢字符,點(diǎn)擊“查詢”按鈕,即可在查詢結(jié)果文本框輸出字符的哈弗曼編碼;</p><p> 第四步:在“請輸入哈弗編碼”文本框輸入哈弗曼編碼,點(diǎn)擊“檢驗(yàn)”按鈕,即可在“檢
23、驗(yàn)結(jié)果”中顯示對應(yīng)字符,即可驗(yàn)證哈弗曼編碼與字符是否對應(yīng)。</p><p><b> 程序上機(jī)調(diào)試報(bào)告</b></p><p> 【語法錯誤及其排除】</p><p> ?。?)終端輸出的漢字為亂碼。</p><p> 解決方法:重新設(shè)置工程和各類編碼格式均為GBK,使工程內(nèi)所有文件編碼格式保持一致;</p&
24、gt;<p> ?。?)圖形界面處理時,組建的層次繼承關(guān)系出現(xiàn)錯誤。</p><p> 解決方法:查找API和參考java圖形界面設(shè)計(jì)章節(jié)的例題。</p><p> ?。?)字符串的相關(guān)函數(shù)使用有誤,為真正明白相關(guān)函數(shù)的原理</p><p> 解決方法:利用編程測試字符串各函數(shù)的功能,找出穩(wěn)定可靠的函數(shù),用于自己的代碼中。</p>&
25、lt;p> 【算法錯誤及其排除】</p><p> ?。?)如在設(shè)置哈弗曼樹結(jié)點(diǎn)位置用setNodeXYofRoot(TreeNode node,int a,int b)函數(shù)時未考慮遞歸的算法思想,出現(xiàn)結(jié)點(diǎn)位置設(shè)置混亂和部分結(jié)點(diǎn)無法在界面顯示且不穩(wěn)定。</p><p> 解決方法:采用遞歸算法并與鏈表結(jié)點(diǎn)的字符的深度相結(jié)合設(shè)置節(jié)點(diǎn)的位置坐標(biāo)。</p><p&g
26、t; (2)根據(jù)哈弗曼編碼檢測對應(yīng)的字符時無法將鏈表list<TreeNode>每一個結(jié)點(diǎn)的哈弗曼編碼與輸入檢測的哈弗曼編碼相匹配,在監(jiān)聽類內(nèi)部未能實(shí)現(xiàn)。</p><p> 解決方法:不在監(jiān)聽類內(nèi)部實(shí)現(xiàn)匹配操作,而是在Demo類中定義Stingofhfmcode(String s, List<TreeNode> list)函數(shù)用于測試并獲得哈弗曼編碼對應(yīng)的字符。</p>
27、<p> 當(dāng)字符串較多時會出現(xiàn)畫出的哈弗曼樹過于密集而不夠清晰的現(xiàn)象,在原來的基礎(chǔ)上再次繪制會覆蓋原先的樹,出現(xiàn)混亂。</p><p> 解決方法:調(diào)整結(jié)點(diǎn)間距,使其結(jié)點(diǎn)距離適中。出現(xiàn)的覆蓋現(xiàn)象是因?yàn)槊看卫L制沒有刷新界面,通過繼承JFrame中的update()函數(shù)并調(diào)用。</p><p> 統(tǒng)計(jì)的字符時用連續(xù)數(shù)組存儲實(shí)現(xiàn)具有局限性,且不利于進(jìn)一步構(gòu)建哈弗曼樹。</p
28、><p> 解決方法:利用鏈?zhǔn)酱鎯Y(jié)構(gòu),調(diào)用庫類 ArrayList<TreeNode>實(shí)現(xiàn)。</p><p><b> 3、程序測試結(jié)果</b></p><p> 【測試數(shù)據(jù)】 任意輸入字符串例如: jghjfgjfghjfjhjh,jk.m.,hj,mnvnvvnvvnvn</p><p><b&
29、gt; 【輸出結(jié)果】</b></p><p><b> 1、顯示界面圖</b></p><p> 2、查j的編碼: 01</p><p> 3、實(shí)驗(yàn)匹配01 對應(yīng) j</p><p> 4、如果不存在實(shí)驗(yàn)的 如:11111110000 對應(yīng)路徑不存在,匹配不成功</p><
30、p><b> 【程序性能評價】</b></p><p> 由于哈弗曼編碼在數(shù)據(jù)壓縮方面應(yīng)用十分廣泛.本程序用哈弗曼樹(最優(yōu)二叉樹)實(shí)現(xiàn)字符串編碼及哈弗曼樹的GUI輸出,直觀,簡約,并成功驗(yàn)證了哈弗曼編碼能與實(shí)際編碼的構(gòu)想完全吻合,為哈弗曼編碼的推廣及應(yīng)用提供了一定的參考價值。在程序設(shè)計(jì)時,充分考慮到各項(xiàng)異常,遇到不符合的事項(xiàng),都會彈出對話框,給予提示,大大增強(qiáng)了人機(jī)交互的能力,更有
31、利于實(shí)驗(yàn)的檢測和驗(yàn)證。</p><p><b> 【性能改進(jìn)方向】</b></p><p> 本程序雖然能直觀的為驗(yàn)證哈弗曼編碼的實(shí)際應(yīng)用價值提供一定參考價值,但功能相對簡單。由于網(wǎng)絡(luò)安全及數(shù)據(jù)壓縮是現(xiàn)今社會談?wù)摰臒衢T話題,因此,在數(shù)據(jù)傳送時,對壓縮傳送數(shù)據(jù)及加密數(shù)據(jù),已成為哈弗曼編碼思想的重要應(yīng)用領(lǐng)域之一。此程序可向?qū)?shù)據(jù)加密及數(shù)據(jù)解壓的方向改進(jìn),以便于驗(yàn)證哈弗
32、曼編碼在數(shù)據(jù)壓縮及加密等領(lǐng)域的應(yīng)用,進(jìn)而推廣哈弗曼編碼的重要應(yīng)用價值。</p><p><b> 【收獲及體會】</b></p><p> 通過本次數(shù)據(jù)結(jié)構(gòu)的課程設(shè)計(jì),我學(xué)習(xí)了很多在上課沒懂的知識,并對求哈夫曼樹及哈夫曼編碼/譯碼的算法有了更加深刻的了解,更鞏固了課堂中學(xué)習(xí)有關(guān)于哈夫曼編碼的知識,真正學(xué)會一種算法了。當(dāng)求解一個算法時,不是拿到問題就不加思索地做,而
33、是首先要先對它有個大概的了解,接著再詳細(xì)地分析每一步怎么做,無論自己以前是否有處理過相似的問題,只要按照以上的步驟,必定會順利地做出來。</p><p> 這次課程設(shè)計(jì),我在編輯中犯了不應(yīng)有的錯誤,設(shè)計(jì)統(tǒng)計(jì)字符和合并時忘記應(yīng)該怎樣保存保存數(shù)據(jù),在不斷分析后明確并改正了錯誤和疏漏,使我的程序有了更高的質(zhì)量。這不僅是程序設(shè)計(jì),更是鍛煉我們處理問題的能力,同時也使我們了解到團(tuán)隊(duì)合作的可貴.編寫程序是件細(xì)心活,稍不留神
34、就會出錯,這就必須要求我們對待事情要認(rèn)真!在編寫程序的過程中,錯誤不斷出現(xiàn),不同的類型(如少寫了一個符號,寫錯了字母,用錯了函數(shù)等等)層出不窮,這考驗(yàn)我們待事細(xì)心,耐心,能不能堅(jiān)持到底,不能半途而廢。</p><p> 三人行必有我?guī)?遇到問題我們一起討論,研究,錯了再寫,寫了在改.經(jīng)過多次的修改,調(diào)試,運(yùn)行,添加,終于最后在大家的歡呼聲中,完成了我們的任務(wù).雖說是累了點(diǎn),但我們也從中找到了自己的快樂,每當(dāng)完成
35、一個新的函數(shù)時,那心情是激動啊,這畢竟是自己弄出來的,同時也使我感受到了學(xué)習(xí)的快樂!</p><p> 一個成功的項(xiàng)目必須在寫代碼前,先要對課題有充分的思考和規(guī)劃,否則即使完成了項(xiàng)目也會浪費(fèi)很多的時間和精力。所以,我覺,科學(xué)合理的編程方法是我這次課程設(shè)計(jì)的最大收獲。</p><p> 源程序代碼 (要求有盡可能多的注釋語句)</p><p><b>
36、 Haffman 類</b></p><p> package hTreeDemo;</p><p> import java.awt.Graphics;</p><p> import java.util.*;</p><p> import javax.swing.JFrame;</p><p&
37、gt; import javax.swing.JOptionPane;</p><p><b> /*</b></p><p> * 給出一個字符串,統(tǒng)計(jì)每個字符在字符串中出現(xiàn)的次數(shù),并返回一個TreeNode類型的數(shù)組</p><p> * 用TreeNode類型的數(shù)組創(chuàng)建一個霍夫曼樹,并制定每個葉節(jié)點(diǎn)的霍夫曼編碼</p>
38、<p> * 給出字符要求輸出該字符的霍夫曼編碼(或者給出字符串,給出該字符串的霍夫曼編碼)</p><p> * 畫出一個界面,輸入字符串,然后輸出這段字符串的哈弗曼碼以及畫出哈弗曼樹:</p><p> * 建一個界面類,在main方法里調(diào)用:實(shí)現(xiàn)字符串輸入和畫出哈樹及輸出哈弗曼碼的功能。</p><p><b> * </
39、b></p><p> * 最終是先從一個文件中傳入數(shù)據(jù)壓縮存儲到另一可選位置,并可以解壓縮的功能。</p><p> * @author Administrator</p><p><b> *</b></p><p><b> */</b></p><p>
40、 public class Huffman {</p><p><b> /**</b></p><p><b> * 程序入口</b></p><p><b> * </b></p><p> * @param args</p><p>
41、* //</p><p><b> */</b></p><p> public static void main(String[] args) {</p><p> Interface face = new Interface();</p><p> //Graphics g = nul
42、l;</p><p> //Huffman demo = new Huffman();</p><p> face.creatUI();</p><p> //List<TreeNode> list = demo.creatNodeList("asdsa");</p><p><b> //
43、</b></p><p> //for (int i = 0; i < list.size(); i++) {</p><p> //System.out.println(list.get(i).getCh() + " 次數(shù):"</p><p> //+ list.get(i).getWeight());<
44、/p><p><b> //}</b></p><p> //TreeNode root = demo.creatTree(list, g,face);</p><p> //System.out.println(root);</p><p> //demo.print(root);</p>&l
45、t;p> //demo.setHfmcode(root);</p><p> //System.out.println("已經(jīng)設(shè)置了哈夫曼碼");</p><p> //String hfmcode1 = demo.hfmcodeofSting("w", root);</p><p> //System.
46、out.println(hfmcode1);</p><p> //String s = "";</p><p> //demo.set(root, s);</p><p> //String hfmcode = demo.hfmcodeofSting("e", root);</p><p>
47、; ////System.out.println(hfmcode);</p><p><b> }</b></p><p><b> /*</b></p><p> * 傳入字符串,生成一個節(jié)點(diǎn)隊(duì)列。因?yàn)橐话阄淖侄际钦加袃蓚€字節(jié),所以輸入的字符串都能轉(zhuǎn)變?yōu)閱蝹€文字。</p><p><
48、;b> * </b></p><p> * @param str:字符串</p><p><b> * </b></p><p> * @return 樹節(jié)點(diǎn)類型的隊(duì)列</p><p><b> */</b></p><p> Set<St
49、ring> saveChar= new HashSet<String>();</p><p> public List<TreeNode> creatNodeList(String str) {</p><p> String[] sr=str.split("");</p><p> for (int i =
50、0; i < sr.length; i++) {</p><p> if(sr[i].equals("")){</p><p> continue; </p><p><b> }</b></p><p> saveChar.add(sr[i].toString());</p>
51、;<p><b> }</b></p><p> // System.out.println(saveChar.size());</p><p> /*for(String s:saveChar){</p><p> System.out.print(s+" ");</p><
52、;p><b> }*/</b></p><p> List<TreeNode> list = new ArrayList<TreeNode>(); // 自定義隊(duì)列,接受字符串中的字符</p><p> for (int h = 0; h < str.length(); h++) {</p><p>
53、 int count = 0; // 計(jì)算下面的這個循環(huán)循環(huán)次數(shù)</p><p> for (int i = 0; i < list.size(); i++) { // 遍歷chars隊(duì)列,看新的字符是不是在其中</p><p> if (str.charAt(h) == list.get(i).getCh()) {//ok</p><p> // 如果
54、str中去除的字符已經(jīng)在節(jié)點(diǎn)隊(duì)列中了</p><p> list.get(i).setWeight(list.get(i).getWeight() + 1); // 讓權(quán)重增加一</p><p><b> break;</b></p><p><b> }</b></p><p><b&
55、gt; count++;</b></p><p><b> }</b></p><p> if (count == list.size()) {</p><p> // 如果從str取出的新的char不在隊(duì)列中</p><p> //System.out.println("-------
56、---");</p><p> TreeNode newNode = new TreeNode(str.charAt(h));</p><p> newNode.setWeight(1);</p><p> list.add(newNode);</p><p><b> }</b></p>
57、<p><b> }</b></p><p> // System.out.println(count01);</p><p> return list;</p><p><b> }</b></p><p><b> /**</b></p>
58、<p> * 按權(quán)重給節(jié)點(diǎn)隊(duì)列排序</p><p><b> * </b></p><p> * @return weight屬性從小到大排序的節(jié)點(diǎn)隊(duì)列</p><p><b> */</b></p><p> public List<TreeNode> sortL
59、istW(List<TreeNode> list) {</p><p> for (int i = 0; i < list.size(); i++) {</p><p> for (int j = i + 1; j < list.size(); j++) {</p><p> if (list.get(j).getWeight() &l
60、t; list.get(i).getWeight()) {</p><p> // 如果第j個節(jié)點(diǎn)元素的權(quán)重屬性小于第i個元素的權(quán)重屬性</p><p> TreeNode newNode = list.set(i, list.get(j));// 用指定元素替換以前在該位置的元素</p><p> list.set(j, newNode);</p>
61、;<p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> return list;</p><p><b> }</b></p><p>&
62、lt;b> /**</b></p><p> * 按父節(jié)點(diǎn)權(quán)重給節(jié)點(diǎn)隊(duì)列排序</p><p><b> * </b></p><p> * @return weight:屬性從小到大排序的節(jié)點(diǎn)隊(duì)列</p><p><b> */</b></p><p&
63、gt; public void sortListWofF(List<TreeNode> list) {</p><p> for (int i = 0; i < list.size(); i++) {</p><p> for (int j = i + 1; j < list.size(); j++) {</p><p><b&g
64、t; // 排序</b></p><p> if (list.get(j).getParent().getWeight() < list.get(i)</p><p> .getParent().getWeight()) {</p><p> // 如果第j個節(jié)點(diǎn)元素的權(quán)重屬性小于第i個元素的權(quán)重屬性</p><p>
65、; TreeNode newNode = list.set(i, list.get(j));// 用指定元素替換以前在該位置的元素</p><p> list.set(j, newNode);</p><p><b> }</b></p><p><b> }</b></p><p><
66、;b> }</b></p><p><b> }</b></p><p><b> /**</b></p><p> * 生成一個霍夫曼樹,并給這個哈樹節(jié)點(diǎn)的depth屬性</p><p><b> * </b></p><p&g
67、t; * @param nodeList</p><p> * :按權(quán)重從小到大排好序的樹節(jié)點(diǎn)類型的隊(duì)列</p><p> * @param g</p><p> * :畫布對象</p><p> * @param jf</p><p> *
68、 :在這個界面上加組件</p><p> * @return 霍夫曼樹的根節(jié)點(diǎn)</p><p><b> */</b></p><p> public TreeNode creatTree(List<TreeNode> nodeList, Graphics g,JFrame jf) {</p><p>
69、 if(saveChar.size()==1){</p><p> JOptionPane.showMessageDialog(null,"一個字符創(chuàng)建不了哈弗曼樹,請輸入多個不同的字符!");</p><p> return null;</p><p><b> }</b></p><p>
70、 while (true)</p><p><b> {</b></p><p> nodeList = sortListW(nodeList);</p><p> TreeNode left = nodeList.remove(0);</p><p> TreeNode right = nodeList.re
71、move(0);</p><p> TreeNode root = new TreeNode('F');</p><p> root.setWeight(right.getWeight() + left.getWeight());</p><p> // 手動確定三者之間的關(guān)系</p><p> left.setPar
72、ent(root);</p><p> right.setParent(root);</p><p> root.setLeft(left);</p><p> root.setRight(right);</p><p> //System.out.println("組合了"+(++j));</p>
73、<p> nodeList.add(0, root); // 將根節(jié)點(diǎn)加到隊(duì)列中</p><p> if (nodeList.size() == 1) </p><p><b> {</b></p><p> List<TreeNode> newList = new ArrayList<TreeNode&g
74、t;();</p><p> toList(root, newList); // 把樹轉(zhuǎn)變?yōu)殛?duì)列</p><p> //給每個節(jié)點(diǎn)加深度</p><p> for (int i = 0; i < newList.size(); i++)</p><p><b> {</b></p><p
75、> TreeNode ran = newList.get(i);</p><p> TreeNode newNode = ran;</p><p> while (ran.getParent() != null) </p><p><b> {</b></p><p> newNode.setDepth(
76、newNode.getDepth() + 1);</p><p> ran = ran.getParent();</p><p><b> }</b></p><p><b> }</b></p><p> sortListD(newList); // 按depth排序</p>
77、<p> drawNode(newList, g);</p><p> drawLine(root, g);</p><p> return root;</p><p><b> }</b></p><p><b> }</b></p><p><
78、b> }</b></p><p><b> /**</b></p><p> * 遍歷樹,生成樹節(jié)點(diǎn)的隊(duì)列</p><p><b> * </b></p><p> * @param root</p><p><b> * @retur
79、n</b></p><p><b> */</b></p><p> public void toList(TreeNode root, List<TreeNode> list) {</p><p> if (root != null) {</p><p> toList(root.get
80、Left(), list);</p><p> toList(root.getRight(), list);</p><p> list.add(root);</p><p> //System.out.println("加了一次");</p><p><b> }</b></p>
81、;<p><b> }</b></p><p><b> /**</b></p><p> * 按節(jié)點(diǎn)擁有的子樹的最大深度depth來排序(用插入排序),引用傳遞,是否返回都無所謂</p><p><b> * </b></p><p> * @para
82、m list</p><p> * :要排序的樹節(jié)點(diǎn)隊(duì)列</p><p><b> */</b></p><p> public void sortListD(List<TreeNode> list) {</p><p> for (int i = 1; i < list.
83、size(); i++) {</p><p> for (int j = i; j > 0; j--) {</p><p> if (list.get(j).getDepth() > list.get(j - 1).getDepth()) { // 互換</p><p> TreeNode tem = list.set(j, list.get(j
84、- 1));</p><p> list.set(j - 1, tem);</p><p><b> }</b></p><p> // System.out.println(list.get(j).getCh()+" 深度 "+list.get(j).getDepth());</p><p>
85、;<b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> /**</b></p><p><b> * 設(shè)置各節(jié)點(diǎn)位置</b></p><
86、;p><b> * </b></p><p> * @param node :要設(shè)置位置的結(jié)點(diǎn)</p><p> * @param a: x位置</p><p> * @param b: y位置 </p><p><b> */</b><
87、;/p><p> public void setNodeXYofRoot( TreeNode node,int a,int b) { </p><p> if((node!=null)&&node.getDepth()==0)</p><p><b> {</b></p><p> node.
88、setX(a);</p><p> node.setY(b);</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> if(node.getLeft()!=nu
89、ll)</p><p><b> {</b></p><p> setNodeXYofRoot(node.getLeft(),node.getX()-10,node.getY()+60); </p><p><b> }</b></p><p> if(node.getRight()!=nu
90、ll)</p><p><b> {</b></p><p> setNodeXYofRoot(node.getRight(),node.getX()+10,node.getY()+60); </p><p><b> } </b></p><p><b> }</b&g
91、t;</p><p><b> }</b></p><p><b> /*</b></p><p> *畫出一個哈樹的節(jié)點(diǎn),并設(shè)置每個節(jié)點(diǎn)的x,y屬性</p><p><b> * </b></p><p> * @param list<
92、/p><p> * :排好序的,設(shè)置了depth的節(jié)點(diǎn)隊(duì)列</p><p> * @param jf</p><p> * :把組件加到這個界面上</p><p><b> */</b></p><p> public void drawNode(
93、List<TreeNode> list, Graphics g) {</p><p> while (true) </p><p><b> {</b></p><p> int depth = 0;</p><p> int newDepth = 0;</p><p> L
94、ist<TreeNode> newList = new ArrayList<TreeNode>();// 創(chuàng)建一個隊(duì)列用來接收同層次的節(jié)點(diǎn);</p><p> depth = list.get(0).getDepth(); // 取出第一個節(jié)點(diǎn)的depth,就是說一層一層的畫</p><p> newDepth = depth;</p><p
95、> while (newDepth == depth)</p><p><b> {</b></p><p> if (list.size() != 0) </p><p><b> {</b></p><p> // System.out.println(list.get(0).g
96、etCh()+"深度:————————————————"+list.get(0).getDepth());</p><p> newList.add(list.remove(0)); // 移到新的隊(duì)列里</p><p> if (list.size() != 0)</p><p><b> {</b></p&g
97、t;<p> newDepth = list.get(0).getDepth();// list中下一個元素的depth</p><p> // System.out.println("移除了一個");</p><p><b> } </b></p><p><b> else </b&
98、gt;</p><p><b> {</b></p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b&
99、gt;</p><p> sortListWofF(newList); // 給一層的節(jié)點(diǎn)按父節(jié)點(diǎn)的權(quán)重排序</p><p> int x=210+newList.get(0).getX()+5*getDepthofLeft(newList.get(0));</p><p> int y=60*depth+60;//</p><p>
100、 // 遍歷newList畫出一個深度的所有節(jié)點(diǎn)</p><p> for (int j = 0; j < newList.size(); j++)</p><p><b> {</b></p><p> if((newList.get(j).getDepth()==0))</p><p><b>
101、 {</b></p><p> setNodeXYofRoot(newList.get(j),x,y );</p><p> } </p><p><b> else</b></p><p><b> {</b></p><
102、;p> newList.get(j).setX(x);</p><p> newList.get(j).setY(y);</p><p><b> }</b></p><p> // 畫出節(jié)點(diǎn),即在桌面上加上JButton</p><p> if (newList.get(j).getLeft() !=
103、null)</p><p><b> {</b></p><p> newList.get(j).draw(g, "父", newList.get(j).getX()+3,</p><p> newList.get(j).getY()+5);</p><p><b> }</b
104、></p><p><b> else </b></p><p><b> {</b></p><p> newList.get(j).draw(g, "" + newList.get(j).getCh(),</p><p> newList.get(j).getX
105、()+3, newList.get(j).getY()+5);</p><p><b> }</b></p><p> // System.out.println("畫出了一個節(jié)點(diǎn) "+x+" "+y);</p><p><b> x+=20;</b></
106、p><p><b> }</b></p><p> // System.out.println("畫出了一組");</p><p><b> // 死循環(huán)的出口</b></p><p> if (list.size() == 0) {</p><p>
107、<b> return;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> /**</b></p><p&
108、gt; * 取得一個子樹的最左的葉節(jié)點(diǎn)的x值(僅適用于哈弗曼樹)</p><p><b> * </b></p><p> * @param root</p><p> * :子樹根節(jié)點(diǎn)</p><p> * @return 最左的葉節(jié)點(diǎn)的x值</p><p>&l
109、t;b> */</b></p><p> public int getDepthofLeft(TreeNode root) {</p><p> if (root.getLeft() == null) {</p><p> return root.getX();</p><p><b> }</b&
110、gt;</p><p> if (root != null) {</p><p> getDepthofLeft(root.getLeft());</p><p><b> }</b></p><p> return 0; // 不會執(zhí)行這一步</p><p><b> }&l
111、t;/b></p><p><b> /**</b></p><p> * 畫出每個節(jié)點(diǎn)間的連線</p><p><b> * </b></p><p> * @param root</p><p> * :樹的根節(jié)點(diǎn)</p>
112、<p> * @param g</p><p> * :在這個布上畫</p><p><b> */</b></p><p> public void drawLine(TreeNode root, Graphics g) {</p><p> if (root != nul
113、l) {</p><p> drawLine(root.getLeft(), g);</p><p> drawLine(root.getRight(), g);</p><p> if (root.getLeft() != null) {</p><p> Line line = new Line( root.getX() ,<
114、;/p><p> root.getY(), </p><p> root.getLeft().getX(),</p><p> root.getLeft().getY());</p><p> // root.getY()+40);root.getX()-5,</p><p> //
115、 root.getLeft().setX(root.getX()-5);</p><p> // root.getLeft().setY(root.getY()+40);</p><p><b> //</b></p><p> line.draw(g);</p><p> //System.out.pr
116、intln(root.getCh()+"畫出了一條線"+root.getLeft().getCh());</p><p><b> }</b></p><p> if (root.getRight() != null) {</p><p> Line line = new Line(root.getX(),</p
117、><p> root.getY(),</p><p> root.getRight().getX(),</p><p> root.getRight().getY());</p><p> line.draw(g);</p><p> //System.out.println(root.getCh()+&q
118、uot;畫出了一條線"+root.getRight().getCh());</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> /**</b><
119、/p><p> * 設(shè)置一個哈夫曼樹的哈夫曼編碼</p><p><b> * </b></p><p> * @param root</p><p><b> */</b></p><p> public void setHfmcode(TreeNode root)
120、{</p><p> //System.out.println("開始設(shè)置葉節(jié)點(diǎn)的哈弗曼編碼");</p><p> if (root != null)</p><p><b> {</b></p><p> setHfmcode(root.getLeft());</p>&l
121、t;p> setHfmcode(root.getRight());</p><p> if (root.getLeft() == null && root.getRight() == null)</p><p><b> { // 是葉節(jié)點(diǎn)</b></p><p> TreeNode newRoot = root;
122、</p><p> while (root.getParent() != null) </p><p><b> {</b></p><p> TreeNode newNode = root;</p><p> root = root.getParent();</p><p> if (
123、root.getLeft().equals(newNode))</p><p><b> {// 左節(jié)點(diǎn)</b></p><p> newRoot.setHfmcode(0 + newRoot.getHfmcode());</p><p><b> } </b></p><p><b&g
124、t; else </b></p><p><b> {</b></p><p> newRoot.setHfmcode(1 + newRoot.getHfmcode());</p><p><b> }</b></p><p><b> }</b><
125、/p><p> // System.out.println("設(shè)置了一個葉節(jié)點(diǎn)的哈弗曼編碼");</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p>
126、 //public void set(TreeNode root, String code) { //設(shè)置各節(jié)點(diǎn)的哈弗曼編碼</p><p> //if (root.getLeft() != null) {</p><p> //set(root.getLeft(), code + 0);</p><p><b> //}</
127、b></p><p> //if (root.getRight() != null) {</p><p> //set(root.getRight(), code + 1);</p><p><b> //}</b></p><p> //if (root.getLeft() == nul
128、l && root.getRight() == null) {</p><p><b> // 葉節(jié)點(diǎn)</b></p><p> //root.setHfmcode(code);</p><p><b> //}</b></p><p><b> //
129、}</b></p><p><b> /*</b></p><p> * 獲取字符串的哈弗曼編碼</p><p><b> * </b></p><p> * @param s:傳入的字符串</p><p><b> * </b>
130、</p><p> * @param root:傳入哈夫曼樹的根節(jié)點(diǎn)</p><p><b> * </b></p><p> * @return 字符串的哈弗曼編碼</p><p><b> */</b></p><p> public String hfmcod
131、eofSting(String s, TreeNode root) {</p><p> // System.out.println("調(diào)用toString ");</p><p> String code = "";</p><p><b> int j=0;</b></p><
132、;p> for (String charstr:saveChar) </p><p> if(charstr.equals(s))</p><p><b> {</b></p><p><b> j++;</b></p><p><b> }</b></
133、p><p> if(j==0) //字符不在樹形圖內(nèi)</p><p><b> {</b></p><p> JOptionPane.showMessageDialog(null,"字符不在查找范圍內(nèi),請重新輸入有效字符!");</p><p> return null;</p>
134、<p><b> }</b></p><p> for (int i = 0; i < s.length(); i++) {</p><p> char c = s.charAt(i);</p><p> StringBuffer sc = new StringBuffer();</p><p>
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(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è)計(jì)--數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)----huffman編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)----huffman樹編碼和譯碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告(huffman編碼器)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告--huffman編碼與文件壓縮
- 數(shù)字圖像處理課程設(shè)計(jì)-- huffman編碼理論及算法實(shí)現(xiàn)
- 哈夫曼(huffman)編譯碼器課程設(shè)計(jì)
- 編碼解碼 課程設(shè)計(jì)
- 哈夫曼(huffman)編譯碼器課程設(shè)計(jì)
- 應(yīng)用數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--huffman編/譯碼器
- Huffman編碼和LZW編碼的改進(jìn).pdf
- 數(shù)據(jù)結(jié)構(gòu)--huffman編碼和譯碼
- 課程設(shè)計(jì)-哈夫曼編碼
- 差分曼徹斯特編碼課程設(shè)計(jì)
- 《哈夫曼編碼》課程設(shè)計(jì)
- 課程設(shè)計(jì)哈夫曼編碼
- 哈夫曼編碼課程設(shè)計(jì)
- 課程設(shè)計(jì)哈夫曼編碼
- 基帶編碼軟件課程設(shè)計(jì)設(shè)計(jì)報(bào)告
- 3)哈夫曼編碼方法(huffman)
- 信息論與編碼課程設(shè)計(jì)
評論
0/150
提交評論