生活随笔
收集整理的這篇文章主要介紹了
20172328--蓝墨云班课实验--哈夫曼树的编码
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
哈夫曼編碼測(cè)試 任務(wù)詳情 設(shè)有字符集:S={a,b,c,d,e,f,g,h,i,j,k,l,m,n.o.p.q,r,s,t,u,v,w,x,y,z}。 給定一個(gè)包含26個(gè)英文字母的文件,統(tǒng)計(jì)每個(gè)字符出現(xiàn)的概率,根據(jù)計(jì)算的概率構(gòu)造一顆哈夫曼樹。 并完成對(duì)英文文件的編碼和解碼。 要求: (1)準(zhǔn)備一個(gè)包含26個(gè)英文字母的英文文件(可以不包含標(biāo)點(diǎn)符號(hào)等),統(tǒng)計(jì)各個(gè)字符的概率 (2)構(gòu)造哈夫曼樹 (3)對(duì)英文文件進(jìn)行編碼,輸出一個(gè)編碼后的文件 (4)對(duì)編碼文件進(jìn)行解碼,輸出一個(gè)解碼后的文件 (5)撰寫博客記錄實(shí)驗(yàn)的設(shè)計(jì)和實(shí)現(xiàn)過(guò)程,并將源代碼傳到碼云 (6)把實(shí)驗(yàn)結(jié)果截圖上傳到云班課 任務(wù)分析與分析思路 首先要把字符集從文件中讀出來(lái),并保存在一個(gè)數(shù)組里面。這一步暫時(shí)想用IO流來(lái)實(shí)現(xiàn)。 緊接著是去計(jì)算每一個(gè)字符出現(xiàn)的頻率。初步想用嵌套循環(huán)來(lái)實(shí)現(xiàn),并把出現(xiàn)的概率存在另一個(gè)數(shù)組中。 然后通過(guò)這兩個(gè)步驟,構(gòu)建出一個(gè)二維數(shù)組,每一個(gè)字符對(duì)應(yīng)一個(gè)出現(xiàn)的頻率。 然后寫一個(gè)compareTo方法,對(duì)該二維數(shù)組的第二個(gè)元素進(jìn)行排序,得到從小到大的一個(gè)順序。 用構(gòu)造哈夫曼樹的方法,依次遞歸,找到最小的兩個(gè)元素然后相加構(gòu)成一個(gè)子樹,直到最終的和為1結(jié)束。 通過(guò)遍歷哈夫曼樹,得到每一個(gè)元素的編碼值,并存進(jìn)一個(gè)新的數(shù)組code[]中。 對(duì)從文件中讀出的數(shù)據(jù)進(jìn)行遍歷,并與code[]中的字符進(jìn)行比較,如若相等,則轉(zhuǎn)換為對(duì)應(yīng)的變碼。直至遍歷結(jié)束,哈夫曼編碼完成。 對(duì)于解碼,暫時(shí)不知道怎么完成。。。。 真正的解決過(guò)程 《FIRST》 :將文件讀出來(lái)就讓我卡殼了,萬(wàn)事真的開頭也難。。。我百度了一下如何讀寫文件:
通過(guò)學(xué)習(xí),我照著編寫的讀文件的代碼: File file = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\text.txt");Reader reader = new FileReader(file);BufferedReader bufferedReader = new BufferedReader(reader);String temp = bufferedReader.readLine();
File file2 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");Writer writer = new FileWriter(file2);writer.write(result1);writer.close();
這樣就實(shí)現(xiàn)了我預(yù)期中的第一步。從把字符集從文件中讀出來(lái),并保存在一個(gè)數(shù)組characters[]里面。
《SECOND》 :然后進(jìn)行計(jì)算每一個(gè)字符出現(xiàn)的頻率。首先用嵌套循環(huán)來(lái)實(shí)現(xiàn),并把出現(xiàn)的概率存在另一個(gè)數(shù)組中。真正地初次編完代碼,好的,全是0。我繼續(xù)改,知道在嵌套循環(huán)中邏輯沒(méi)有錯(cuò)誤,但是全是0.0。
這就讓我有點(diǎn)百思不得其解了,為什么邏輯沒(méi)有錯(cuò)誤,但概率不出現(xiàn),細(xì)細(xì)分析一遍,其實(shí)是我的除法有問(wèn)題,在"/"運(yùn)算中,計(jì)算機(jī)會(huì)自動(dòng)忽略后面的小數(shù)位,所以需要加(float)的操作才化腐朽為神奇。。。(如下圖所示)
算頻率的時(shí)候我用了ASCII表的位置來(lái)比對(duì),我覺(jué)得自己的這個(gè)方法很巧妙。(可能只是我覺(jué)得) 還有多種方法可以實(shí)現(xiàn)頻率的計(jì)算~~ double frequency[] = new double[27];int numbers = 0;//空格的個(gè)數(shù)for (int i = 0; i < characters.length; i++) {if (characters[i] == ' ') {numbers++;}frequency[26] = (float) numbers / characters.length;}System.out.println("字符集為");for (int j = 97; j <= 122; j++) {int number = 0;//給字母計(jì)數(shù)for (int m = 0; m < characters.length; m++) {if (characters[m] == (char) j) {number++;}frequency[j - 97] = (float) number / characters.length;}System.out.print((char) j + ",");}
public class Node implements Comparable<Node> {private char data;private double weight;private Node left;private Node right;String codenumber;//這個(gè)就是保存0&1的變量public Node(char data, double weight){this.data = data;this.weight = weight;this.codenumber ="";}
《Fourth》 :得到每個(gè)字符對(duì)應(yīng)的編碼后,就可以對(duì)文件進(jìn)行編碼了。//對(duì)英文文件進(jìn)行編碼,輸出一個(gè)編碼后的文件String result1 = "";List<Node> temp1 = breadthFirstTraversal(root);for (int i = 0; i < characters.length; i++) {for (int j = 0; j < temp1.size(); j++) {if (characters[i] == temp1.get(j).getData()) {result1 += temp1.get(j).getCodenumber();}}}
File file2 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");Writer writer = new FileWriter(file2);writer.write(result1);writer.close();
《Fifth》 :對(duì)英文文件進(jìn)行解碼,輸出一個(gè)解碼后的文件。在這一部分我沒(méi)有思路,想了很久還是沒(méi)什么結(jié)果。在這一部分參考了我們班同學(xué)20172313余坤澎同學(xué)的博客,他的思路很好而且很容易讓人理解!根據(jù)他的思路,我把遍歷出的樹保存在一個(gè)Node型的列表temp1中,再?gòu)膖emp1中挑出字符和編碼分別存放在String型的列表newlist和String型的列表newlist1中,在使用他巧妙的暫時(shí)記錄點(diǎn)的方法,最后實(shí)現(xiàn)了解碼。//對(duì)英文文件進(jìn)行解碼,輸出一個(gè)解碼后的文件//將所有具有字符的葉子節(jié)點(diǎn)重新保存在一個(gè)newlist里面List<String> newlist = new ArrayList<>();for(int m=0;m < temp1.size();m++){if(temp1.get(m).getData()!='無(wú)')newlist.add(String.valueOf(temp1.get(m).getData()));}System.out.println("字符:"+newlist);List<String> newlist1 = new ArrayList<>();for(int m=0;m < temp1.size();m++){if(temp1.get(m).getData()!='無(wú)')newlist1.add(String.valueOf(temp1.get(m).getCodenumber()));}System.out.println("對(duì)應(yīng)編碼:"+newlist1);//先從編完碼的文件中讀出密文FileReader fileReader = new FileReader("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");BufferedReader bufferedReader1 = new BufferedReader(fileReader);String secretline = bufferedReader1.readLine();//將讀出的密文存在secretText列表中List<String> secretText = new ArrayList<String>();for (int i = 0; i < secretline.length(); i++) {secretText.add(secretline.charAt(i) + "");}//解密String result2 = "";//最后的解碼結(jié)果String current="";// 臨時(shí)的保存值while(secretText.size()>0) {current = current + "" + secretText.get(0);secretText.remove(0);for (int p = 0; p < newlist1.size(); p++) {if (current.equals(newlist1.get(p))) {result2 = result2 + "" + newlist.get(p);current="";}}}System.out.println("解碼后的結(jié)果:"+result2);File file3 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\text1.txt");Writer writer1 = new FileWriter(file3);writer1.write(result2);writer.close();}
最后的結(jié)果圖
點(diǎn)擊找到完整代碼
轉(zhuǎn)載于:https://www.cnblogs.com/LXY462283007/p/10100337.html
總結(jié)
以上是生活随笔 為你收集整理的20172328--蓝墨云班课实验--哈夫曼树的编码 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。