日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

20172328--蓝墨云班课实验--哈夫曼树的编码

發布時間:2023/12/8 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 20172328--蓝墨云班课实验--哈夫曼树的编码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

哈夫曼編碼測試

任務詳情

  • 設有字符集: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}。
  • 給定一個包含26個英文字母的文件,統計每個字符出現的概率,根據計算的概率構造一顆哈夫曼樹。
  • 并完成對英文文件的編碼和解碼。
    • 要求:
    • (1)準備一個包含26個英文字母的英文文件(可以不包含標點符號等),統計各個字符的概率
    • (2)構造哈夫曼樹
    • (3)對英文文件進行編碼,輸出一個編碼后的文件
    • (4)對編碼文件進行解碼,輸出一個解碼后的文件
    • (5)撰寫博客記錄實驗的設計和實現過程,并將源代碼傳到碼云
    • (6)把實驗結果截圖上傳到云班課

任務分析與分析思路

  • 首先要把字符集從文件中讀出來,并保存在一個數組里面。這一步暫時想用IO流來實現。
  • 緊接著是去計算每一個字符出現的頻率。初步想用嵌套循環來實現,并把出現的概率存在另一個數組中。
  • 然后通過這兩個步驟,構建出一個二維數組,每一個字符對應一個出現的頻率。
  • 然后寫一個compareTo方法,對該二維數組的第二個元素進行排序,得到從小到大的一個順序。
  • 用構造哈夫曼樹的方法,依次遞歸,找到最小的兩個元素然后相加構成一個子樹,直到最終的和為1結束。
  • 通過遍歷哈夫曼樹,得到每一個元素的編碼值,并存進一個新的數組code[]中。
  • 對從文件中讀出的數據進行遍歷,并與code[]中的字符進行比較,如若相等,則轉換為對應的變碼。直至遍歷結束,哈夫曼編碼完成。
  • 對于解碼,暫時不知道怎么完成。。。。
  • 真正的解決過程

    • 《FIRST》:將文件讀出來就讓我卡殼了,萬事真的開頭也難。。。
    • 我百度了一下如何讀寫文件:

    • 通過學習,我照著編寫的讀文件的代碼:
    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();

    這樣就實現了我預期中的第一步。從把字符集從文件中讀出來,并保存在一個數組characters[]里面。

    • 《SECOND》:然后進行計算每一個字符出現的頻率。首先用嵌套循環來實現,并把出現的概率存在另一個數組中。真正地初次編完代碼,好的,全是0。我繼續改,知道在嵌套循環中邏輯沒有錯誤,但是全是0.0。

    • 這就讓我有點百思不得其解了,為什么邏輯沒有錯誤,但概率不出現,細細分析一遍,其實是我的除法有問題,在"/"運算中,計算機會自動忽略后面的小數位,所以需要加(float)的操作才化腐朽為神奇。。。(如下圖所示)

    • 算頻率的時候我用了ASCII表的位置來比對,我覺得自己的這個方法很巧妙。(可能只是我覺得)
      還有多種方法可以實現頻率的計算~~
    double frequency[] = new double[27];int numbers = 0;//空格的個數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;//給字母計數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 + ",");}
    • 《THIRD》:第三部原本想通過這兩個步驟,構建出一個二維數組,每一個字符對應一個出現的頻率。但是細細想來,二維數組會浪費大量的空間,索性就回過頭去寫哈夫曼樹的構成,參考了一些博客,寫出了大體的代碼,在廣度優先遍歷解決完成后,需要找到所有的葉子節點,才能知道每一個字符對應的編碼,所以需要記錄一個值,再添加子樹的時候將“0”和“1”記錄下來,最后最好輸出在我的廣度優先遍歷結果中,添加在結點的屬性里。
    • 于是我先嘗試了一下,用了一個int型的變量加在了huffman樹的節點類的屬性中,但是出現的結果是:

    • 我找了找規律,最后發現只有0和1的話,加起來很容易就會出現這種情況,而不會反映我的編碼,于是我才明白只能用String型來保存這個變量,字符串的相加才能正常出現編碼,這樣一來就解決了我的問題。
    public class Node implements Comparable<Node> {private char data;private double weight;private Node left;private Node right;String codenumber;//這個就是保存0&1的變量public Node(char data, double weight){this.data = data;this.weight = weight;this.codenumber ="";}

    • 《Fourth》:得到每個字符對應的編碼后,就可以對文件進行編碼了。
    //對英文文件進行編碼,輸出一個編碼后的文件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》:對英文文件進行解碼,輸出一個解碼后的文件。在這一部分我沒有思路,想了很久還是沒什么結果。在這一部分參考了我們班同學20172313余坤澎同學的博客,他的思路很好而且很容易讓人理解!根據他的思路,我把遍歷出的樹保存在一個Node型的列表temp1中,再從temp1中挑出字符和編碼分別存放在String型的列表newlist和String型的列表newlist1中,在使用他巧妙的暫時記錄點的方法,最后實現了解碼。
    //對英文文件進行解碼,輸出一個解碼后的文件//將所有具有字符的葉子節點重新保存在一個newlist里面List<String> newlist = new ArrayList<>();for(int m=0;m < temp1.size();m++){if(temp1.get(m).getData()!='無')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()!='無')newlist1.add(String.valueOf(temp1.get(m).getCodenumber()));}System.out.println("對應編碼:"+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 = "";//最后的解碼結果String current="";// 臨時的保存值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("解碼后的結果:"+result2);File file3 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\text1.txt");Writer writer1 = new FileWriter(file3);writer1.write(result2);writer.close();}

    最后的結果圖


    點擊找到完整代碼

    轉載于:https://www.cnblogs.com/LXY462283007/p/10100337.html

    總結

    以上是生活随笔為你收集整理的20172328--蓝墨云班课实验--哈夫曼树的编码的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。