文件压缩——哈夫曼树编码
Posted shy0322
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件压缩——哈夫曼树编码相关的知识,希望对你有一定的参考价值。
何谓哈夫曼树?——
百度百科:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
哈夫曼树的应用?——
哈夫曼编码 与 哈夫曼译码。
哈夫曼树为基础的项目?——
文件压缩。
文件压缩分两种:1.有损压缩。2.无损压缩。
哈夫曼树为核心算法的压缩方式是无损压缩。
其实我们windows常用的zip类型的压缩包底层,哈夫曼树就是核心算法之一(当然不全是)。
生成一棵哈夫曼树并进行哈夫曼编码,再用哈弗曼编码和哈夫曼树还原——
比如看这条语句:aaaabbbccd
1.首先统计文件字符出现次数——
a 4
b 3
c 2
d 1
2.构建huffman树——见图
3.根据huffman树生成huffman编码(huffman code)
a --- 0 b --- 11 c --- 101 d --- 100
aaaabbbccd --- 0000111111101101100
4.压缩——
test.txt -----> test.huffman
每一个字符都有唯一的路劲,那么每一个字符都有唯一的编码,那么就可以替换完成无损压缩。
5.解压缩——
使用test.huffman------->test.txt
那么详细的让我们看代码——
.h文件——
该类模拟生成哈夫曼树。
1 #pragma once 2 3 #include<queue> 4 5 template<typename W> 6 struct HuffmanTreeNode 7 { 8 W val; 9 HuffmanTreeNode* right; 10 HuffmanTreeNode* left; 11 }; 12 13 //堆——优先级队列。priority_queue 14 15 template<typename W,typename T> 16 class HuffmanTree 17 { 18 //放在内部,方便且安全 19 typedef HuffmanTreeNode Node; 20 public: 21 //优先队列中放的是结点的指针。 22 //因为我放的是指针,但是比较的时候不能比较指针啊。 23 //所以在这里我需要写一个仿函数。 24 //让他用我的仿函数比较。但是要注意,仿函数是第三个模板参数,所以第二个模板参数还是要一样的。 25 26 //因为我们要杜绝出现出现次数为0的情况,这种情况不会被我们统计但是如果不管会占空间。 27 HuffmanTree(W* a,size_t n,const T& invalid); 28 29 //生成完哈夫曼树后那么接下来就是要生成哈夫曼编码了 30 //生成哈夫曼编码的方法 31 //1.三叉链法。添加一个parents指针在HuffmanNode结构体中,并且注意初始化。 32 //2.递归,左0右1。递归方法放在FileCompress类中。 33 34 //因为如果利用递归法,就很有可能需要在最后,将根的哈夫曼码变成当前结点结构体中的哈夫曼码。 35 //所以需要类提供一个接口 36 //返回root 37 Node* GetRoot(); 38 39 ~HuffmanTree(); 40 //因为涉及树,所以删除很有可能需要调用递归,要自觉习惯用一个函数来完成析构任务。 41 void destory(Node* root); 42 private: 43 //暂时用不到拷贝构造和=运算符重载 44 //所以直接用防拷贝的方法。 45 HuffmanTree(const HuffmanTree<W> &t); 46 HuffmanTree<W>& operator=(const HuffmanTree<T> &t); 47 protected: 48 Node* root; 49 };
接下来是用例案例——
模拟实现文件解析类。
1 #pragma once 2 3 #include<string> 4 #include"HuffmanTree.h" 5 using namespace std; 6 7 //一个字符的信息—— 8 //我们会将这个值统计好传过去来生成哈夫曼树。 9 //但同时我们也知道哈夫曼树中有W的加的操作,>的操作,!=的操作。 10 //所以我们还需要重载+运算符,>运算符,!=运算符。 11 struct CharInfo 12 { 13 char _ch; 14 long long _count; 15 string _code; 16 CharInfo operator+(const CharInfo& info); 17 bool operator>(const CharInfo& info); 18 bool operator!=(const CharInfo& info); 19 }; 20 21 class FileCompress 22 { 23 public: 24 //构造函数就是写死,初始化哈希表。 25 FileCompress(); 26 //压缩 27 //1.首先要统计文件中字符出现的次数。 28 //2.用IO流的方式读字符串---因为是读,所以是ifstream,因为要从文件里读。 29 //C++reference里有些,构造函数就直接讲字符串当做参数(字符串实际为一个文件),读字符就用get。 30 void Compress(const char *file); 31 //解压缩 32 void Uncompress(const char *file); 33 void GenerateHuffmanCode(HuffmanTreeNode<char> *node); 34 protected: 35 CharInfo _hashInfos[256];//用来存放各个字符。 36 };
持续更新...
以上是关于文件压缩——哈夫曼树编码的主要内容,如果未能解决你的问题,请参考以下文章