一、实现功能
1.压缩文本文件 :xzip 源文件名字 压缩后文件名字
2.解压文本文件 :xuzip 压缩文件名字 解压后文件名字
3.压缩比大约18%左右(与文件内容有关系)
因为文件内容都是重复的所以这里压缩比比较高。
4.做成了类似Linux内置命令的样子放在了/bin目录下(这样可以自动补全路径)
最后cmp比对一下压缩前后的两个文件发现两个文件完全一样。
二、理论证明
压缩文本文档为什么可行?
1.一个char占8位,所以哈弗曼编码格式压缩之后,应该是少于8个字符(8层字符最多拥有2^8个叶子节点)。即使有些时候多于8个长度字符(树可能不是平衡的,大部分集中到了某一支)但是出现的频度不同,编码短的出现的频度高,所以还是可以达到压缩的效果。
2.ASCII码数量一共128个字符,从0~127编码,ASCII码中表示的字符首位都是0,所以建树一般应该会小于8层,所以利用哈弗曼编码形成新的编码方式的每个字符平均是小于八位的,从而实现压缩的功能。
压缩一般文件是否可行?
理论上是行不通的,不排除个别时候可以,但是绝大多数大文件应该是不可以只利用哈弗曼编码压缩的。因为对于一般文件来说,他并不是我们之前那种可以显示的字符,就是说我们如果按一个字节一个字节读出来的话就会有一些乱码,因为有首位是1的情况,那么8位就有2^8种编码方式,利用哈弗曼建树的话平均就是8层(2 ^8个叶子节点),达不到压缩的效果。比如我尝试压缩一个图片,图片反而变大了,虽然解码后还是图片本身,但是没有达到压缩的效果。
三、代码设计
1.数据结构
(1)哈弗曼树采用二叉链表存储,节点如下:
struct HuffmanNode{
HuffmanNode(char k,int w):key(k),weight(w),lchild(NULL),rchild(NULL){
}
HuffmanNode(){
}//提供三种构造方法
HuffmanNode(int w):weight(w),lchild(NULL),rchild(NULL){
}
char key;
int weight;
HuffmanNode *lchild;
HuffmanNode *rchild;
};
(2)设计了两个类
HuffmanTreel类:用来处理关于哈弗曼编码的问题
主要方法有:
void buildTree(const map<char,unsigned> &mp,int mode);//建树
void getStr(HuffmanNode *p,string &str);//h获得新字符的编码方式
File类:用来从文件中读取数据和写入数据、编码、译码等工作
主要方法有:
map<char,unsigned> getMa