Huffman有好几种叫法
- 霍夫曼
- 哈夫曼
- 赫夫曼
- 难道还有别的吗…
不过我比较喜欢“哈”开头,因为笔画比较少……不过还是原汁原味的‘Huffman’更有感觉。
HuffmanTree
- Huffman树是“带权路径长度最短的树”,说白了就是权值越大的越靠近根节点越容易被取出来,权值越小的越深入地下越费力才能取出来。
- 所谓权值,我所知道的应用场所就是频率,越有可能被使用到的数据(频率越大)对应的权值也就越大,也就越靠近根节点(所在的层数越小)使得越容易被取出。如此排列使得获取数据所需要花费的力气的数学期望可以达到一个最小的值。
- 应用之一是哈夫曼编码
Huffman Code 哈夫曼编码
- 非等长编码,即出现频率越大的内容给予的编码长度越短(对应HuffmanTree中的实现就是其所在的层数越小),使得平均编码长度(数学期望)达到最小,减小对内容编码所占的空间
- HuffmanCode使用的编码方式是“前缀编码”,即每一个编码都不是另一个编码的前缀,使得译码的时候一个一个读取可以一一对应到相应的内容,例如下面
内容 | 编码 |
---|---|
a | 0 |
b | 10 |
c | 110 |
d | 111 |
- 对于一串编码”010110111”顺序读取下来就可以译码成”abcd”而没有二义性
- 这里就要用到HuffmanTree来进行编码表的创建,以26个小写字母为例,每个字母对应一串只有’0’和’1’的编码
1、统计字母的频率
- 实际只需统计频数即可,因为需要的是小写字母出现频率(权重)之间的大小关系,在这一点上频率和频数的作用一样
- 读取文件source.txt(#define SOURCEFILE source.txt),内容是一串小写字母
int Weight[267]={0};//[1]到[26]分别对应'a'到'z',[0]未使用
ifstream input;
input.open(SOURCEFILE);
char inChar;
while(!input.eof())
{
input>>inChar;/*默认输入的是小写字母,实际应当检查一下输入是否正确*/
Weighr[inChar - 'a' + 1] += 1;
}
input.close();
- 可能会有的小写字母未出现,那权值也就是0