寫在開頭——這是乙個耗時兩周,幾度中斷,最終還是未完成的**。
事情的源頭是一次上機實驗,這是一道選做題:
設計乙個哈夫曼編碼、解碼系統。對乙個 ascii 編碼的文字檔案中的字元進行哈夫曼編碼,生成編碼 檔案; 反過來,可將編碼檔案解碼還原為乙個文字檔案。 (1) 從檔案中讀入任意一篇英文短文(檔案為 ascii 編碼擴充套件名為 txt) (2) 統計並輸出不同字元在文章中出現的頻率(空格、換行、標點等也按字元處理); (3) 根據字元頻率構造哈夫曼樹,並給出每個字元的哈夫曼編碼;
開始的時候我覺得這道題可以做啊,重點不就是哈夫曼樹的建立嗎,書上的**白紙黑字。於是我就入坑了。。
從**入手呢?嗯,先寫乙個讀寫檔案的函式吧! 突然我的腦子一片空白,對檔案是怎麼操作來著,我怎麼毫無印象,才反應過來c語言的檔案操作早已經忘得精光。
對檔案的讀取用的方法取自前一篇部落格。檔案操作是解決了,可新問題又來了,統計字元。開始我就用兩個陣列data[ ],weight[ ] ,乙個存字元,乙個計數,不用想 死路一條。
於是,又專門建立乙個類data 來初步儲存從檔案讀取的字元的種類以及權值。然後是把他們排個序,為下一步建立哈夫曼樹做準備。
好了,現在原材料有了,可以開始寫哈夫曼樹了。可後來我哭了,我才明白演算法思想了然於胸和用**實現是天壤之別。翻開書,恭恭敬敬地看了好幾遍**,又加上我自己
的改造,算是基本完成。樹已經建好了,接下來就是對各個字元編碼了,沒成想這一步是如此的艱難,再一次卡死。這是昨天下午的事了。
開始想用非遞迴實現加乙個輔助棧,因為我一碰見遞迴就犯迷糊,可是二叉樹就是為遞迴而生的,我只能老老實實的迷失在遞迴裡。還好今天上午把他給解決了。
還剩最後兩個問題沒解決,把txt檔案哈夫曼編碼,把編碼後的檔案按照哈夫曼解碼。寫到這對於學渣的我已經是不容易了,以後繼續努力吧。
也就是說我現在的**可以把乙個txt檔案裡的字元讀取,建成乙個哈夫曼樹,並且給出各個字元對應的哈夫曼編碼。
下面是長篇**,寫的比較簡陋,也沒能來得及優化。函式都寫到類裡面了。。。
#include
#include
#include
#define max 80
using
namespace
std;
class data
};/*----------------哈夫曼樹的節點類----------*/
class nodehuff
~nodehuff(){}
};/*-----------------哈夫曼樹類-----------------*/
class huffmantree
~huffmantree()
nodehuff* getroot()
void deletetree(nodehuff* p) //刪除以p為根的整棵樹
/*--------------建立哈夫曼樹---------------*/
void creathuffman()
int j=0;
nodehuff* p1,*p2,*p,*t;
for(int i=0;inew nodehuff;
p1=h[i];
p2=h[i+1];
t->left=p1;
t->right=p2;
t->weight=p1->weight+p2->weight;
p=t;
j=i+2;
while(jweight>h[j]->weight))
h[j-1]=p;
}root=h[number-1];
}/*-------------------對檔案中的字元計數並且按遞增排序-------------------*/
void countandsort()
char q;
while(infile.good()&&!infile.eof())
}if((o==max)&&(number!=max))}}
}for(int i=number;i<=max;i++)
infile.close();
/*---------------對cc排序,將排好序的資料傳給data,weight--------------------*/
int j=0;
for(int k=0;kfor(int i=0;iif(cc[j].weight>cc[i].weight)
j=i;
}data[k]=cc[j].data;weight[k]=cc[j].weight;
cc[j].weight=999;
}cout
<<"---------各字元出現次數----------"
<"\t"
<"\t";
}for(int i=number;i0;weight[i]=999;
}}/*---------按照哈夫曼樹對字元編碼------------*/
void encode(nodehuff* p,char *encode)
nodehuff*l,*r,*q;
char lcode[max];
char rcode[max];
l=p->left;int i=0;
while(encode[i]!='\0')
;lcode[i]='0';lcode[i+1]='\0';
r=p->right;i=0;
while(encode[i]!='\0')
;rcode[i]='1';rcode[i+1]='\0';
encode(l,lcode);
encode(r,rcode);
}};int main()
; cout
<<"--------------------"
0;}
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...
哈夫曼編碼 哈夫曼樹
哈夫曼樹是乙個利用權值進行優化編碼的乙個比較奇怪的樹,他的實現比較簡單,用途也比較單一。哈夫曼樹的實現,實現要求 通過哈夫曼樹可以保證在編碼過程中不會出現例如 1000和100這樣的編碼規則,否則就會編碼失敗,因為1000和100在某些情況下的編碼會一模一樣。通過哈夫曼樹可以保證權值大的值進行編碼時...