《数据结构与算法》课程设计报告——赫夫曼编码/译码器
-
題目
赫夫曼編碼/譯碼器
-
實驗目的
本課程設計是為了讓同學們了解學習數據結構的作用和意義。數據結構是計算機科學與技術專業的專業基礎課,是十分重要的課程。所有的計算機系統軟件和應用軟件都要用到各種類型的數據結構。因此,想要更好地運用計算機來解決實際問題,僅僅掌握幾門計算機程序設計語言是遠遠難以應付當前眾多復雜的課題,想要有效地使用計算機,充分發揮它的性能,還必須學習和掌握好數據結構的有關知識,打好數據結構這門課的扎實基礎,對于學習計算機專業其它的課程,如操作系統、軟件工程、編譯原理、數據庫、人工智能等十分有益。
?
-
需求分析
(1)初始化(Initialization)。從終端讀入字符集大小n,以及n個字符和n個權值,建立赫夫曼樹,并將它存于文件hfmTree中。
(2)編碼(Encoding)。利用已建好的赫夫曼樹(如不在內存,則從文件hfmTree中讀入),對文件ToBeTran中的正文進行編碼,然后將結果存入文件CodeFile中。
(3)譯碼(Decoding)。利用已建好的赫夫曼樹將文件CodeFile中的代碼進行譯碼,結果存入文件Textfile中。
(4)打印代碼文件(Print)。將文件CodeFile以緊湊格式顯示在終端上,每行50個代碼。同時將此字符形式的編碼文件寫入文件CodePrin中。
(5)打印赫夫曼樹(Tree printing)。將已在內存中的赫夫曼樹以直觀的方式(比如樹)顯示在終端上,同時將此字符形式的赫夫曼樹寫入文件TreePrint 中。
(6)網絡通信(Network)。通過赫夫曼編碼的形式作為加密方式,進行網絡通信。
?
-
概要設計
?
?
建立赫夫曼樹
?
編碼
?
?
譯碼
?
-
詳細設計
?
?
建立赫夫曼樹
/*** @param code - 字符集* @param weight - 頻數*/public void create(char[] code,double[] weight) {num=code.length;?? //獲取字符集字符總數node_tot=2*num-1;? //總共需要2num-1個節點PriorityQueue<HTNode> Q = new PriorityQueue<HTNode>();?? //優先隊列排序HT=new HTNode[node_tot+1];HT[0]=new HTNode(0);//給葉子結點賦值for(int i=1;i<=num;i++) {HT[i]=new HTNode(i,code[i-1],weight[i-1]);Q.add(HT[i]);}int id=num;//Huffman編碼while(Q.size()>=2) {//找到兩個權值最小的結點作為左右子樹的根節點構造新的二叉樹。HTNode s1=Q.remove();HTNode s2=Q.remove();id++;//創建新的節點//新節點的權值是兩個子節點之和HT[id]=new HTNode(id,s1,s2);?????s1.parent=s2.parent=id;??????? //將兩個子節點的父節點設置為 id;//新節點重新放入隊列Q.add(HT[id]);}}?
建立編碼表
/*** 從葉子到根逆向求每個字符的Huffman編碼*/public void createHuffmanCode() {int start,c,f;char[] cd=new char[num];HuffmanCodeList=new String[num+1]; //分配內存空間//依次對所有字符編碼for(int i=1; i<=num; i++){start=num;//從葉子到根逆向求編碼for(c=i,f=HT[i].parent;f!=-1;c=f,f=HT[f].parent) {if(HT[f].lchild==c) {cd[--start]='0';}else{cd[--start]='1';}}//復制編碼到Huffman編碼表HuffmanCodeList[i]=new String(cd,start,num-start);}}?
編碼
/*** 從葉子到根逆向求每個字符的Huffman編碼*/public void createHuffmanCode() {int start,c,f;char[] cd=new char[num];HuffmanCodeList=new String[num+1]; //分配內存空間//依次對所有字符編碼for(int i=1; i<=num; i++){start=num;//從葉子到根逆向求編碼for(c=i,f=HT[i].parent;f!=-1;c=f,f=HT[f].parent) {if(HT[f].lchild==c) {cd[--start]='0';}else{cd[--start]='1';}}//復制編碼到Huffman編碼表HuffmanCodeList[i]=new String(cd,start,num-start);}}?
譯碼
/*** @param code_str - 需要譯碼的字符串* @return encode - 完成Huffman譯碼的字符串*/public String deCode(String code_str) {int len=code_str.length();String decode=new String();String temp=new String();//依次與所有字符編碼開始匹配for(int i=0;i<len;i++) {temp=temp+code_str.charAt(i);for(int j=1;j<=num;j++) {//匹配成功if(HuffmanCodeList[j].equals(temp)) {decode=decode+HT[j].code;temp="";break;}}if(temp.length()>128)return null;}if(!temp.equals(""))return null;return decode;}?
文件分析
FileDialog jf=new FileDialog(this,"選擇文本文件",FileDialog.LOAD);jf.setVisible(true);String path=getAllPath(jf);if(path==null) {return;}String str=readFileToString(path);int len=str.length();char[] code = new char[128];double[] weight =new double[128];for(int i=0;i<128;i++) {code[i]=(char)i;}int num=0;for(int i=0;i<len;i++) {char ch=str.charAt(i);if(ch<0||ch>128) {JOptionPane.showMessageDialog(null, "文件讀取錯誤", "錯誤提示",JOptionPane.ERROR_MESSAGE);return;}if(weight[ch]==0)num++;weight[ch]+=1;}char[] new_code = new char[num];double[] new_weight =new double[num];for(int i=0,j=0;i<128;i++) {if(weight[i]!=0.0) {new_code[j]=code[i];new_weight[j++]=weight[i];}}initHuffmanTree(new_code,new_weight,textArea,textArea_3);?
樹圖繪制
/*** @param root HuffmanTree ROOT* @param g Graphics**/public void paintTree(int root,Graphics g,int x,int y){if(root!=-1){if(HT[root].code=='\0')g.drawString(new Double(HT[root].weight).toString(),x-10,y+10);elseg.drawString(chartoString(HT[root].code)+(new Double(HT[root].weight).toString()),x-10,y+10);if(HT[root].lchild!=-1||HT[root].rchild!=-1){int width=7*HT[root].leaf;g.drawLine(x, y+10, x-width, y+30);paintTree(HT[root].lchild, g,x-width,y+30);g.drawLine(x, y+10, x+width, y+30);paintTree(HT[root].rchild, g,x+width,y+30);}}}??網絡通信 /*** @param port 監聽端口* @param ta JTextArea對象* @throws IOException 如果發生I / O錯誤*/public void startReceive(int port,JTextArea ta) throws IOException{// TODO 自動生成的方法存根ssk = new ServerSocket(port);isStop=false;ssk.setSoTimeout(5*1000);new Thread(()-> {while(!isStop) {Socket sk=null;try {sk = ssk.accept();} catch (IOException e) {// TODO 自動生成的 catch 塊e.printStackTrace();}new Thread(new ReceiveThread(sk,ta)).start();}try {ssk.close();} catch (IOException e) {// TODO 自動生成的 catch 塊e.printStackTrace();}}).start();}?
-
調試分析
GUI布局
使用Windows Builder插件和代碼調整的方式進行GUI布局,以達到快速建立GUI和精確布局的目的。
初始化
初始化過程中,會以默認編碼形式生成哈夫曼樹并生成編碼表。
編碼控制
采用三種編碼產生方式以達到多樣性的需求。
?
樹圖繪制
遞推法實行的樹圖繪制。
?
文本編碼
?
即時編碼
錯誤提醒:
網絡通信
多線程同步問題
synchronized(ta) {if(destr==null)ta.append("Oh,My God! "+ip+" send a message but it isn\'t Huffman Code!"+"\r\n");elseta.append("Remote Host["+ip+"]:"+destr+"\r\n");}Synchronized同步以解決多線程問題。
-
總結
我認為,在這學期的實驗中,在收獲知識的同時,還收獲了閱歷,收獲了成熟,在此過程中,我們通過查找大量資料,請教老師,以及不懈的努力,不僅培養了獨立思考、動手操作的能力,在各種其它能力上也都有了提高。更重要的是,在實驗課上,我們學會了很多學習的方法。而這是日后最實用的,真的是受益匪淺。要面對社會的挑戰,只有不斷的學習、實踐,再學習、再實踐。
通過設計并編寫有關赫夫曼編碼與解碼,鍛煉自己的編程能力,養成良好的編程風格。不管怎樣,這些都是一種鍛煉,一種知識的積累,能力的提高。完全可以把這個當作基礎東西,只有掌握了這些最基礎的,才可以更進一步,取得更好的成績。很少有人會一步登天吧。永不言棄才是最重要的。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的《数据结构与算法》课程设计报告——赫夫曼编码/译码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Eclipse——UML类图插件
- 下一篇: 《数据结构与算法》实验报告——快速排序