利用huffman编码的思想对文件进行压缩,主要原理是通过huffman编码来重新表示字符,使得出现频率高的字符编码短,出现少的字符编码长。整体下来的话,所需的总的bit位是减少的。但是要注意当大部分字符出现的频率都差不多时,huffman压缩的压缩效率会很低。
一、利用huffman树对文件进行压缩主要分为以下两部分:
压缩:
1、统计字符出现的次数
因为文件的底层都是有256个字符存储的,所以我们使用一个256的数组来统计字符出现的次数。可以使用结构体,将次数,字符,huffman编码对应起来。要注意,不管是文件、图片、音频、视频他们的底层都是以字符形式存储的。我们读的时候不管是以文本形式还是以二进制形式都是按字符读取的。
2、构建huffman树
采用huffman算法,将一组集合中权值最小的两个树拿出来构建成一棵树,将他们的权值之和作为父节点插入到这个集合中,不断重复这个过程,直到集合中只有一颗树,这棵树就是huffman树,由于每次都要寻找最小的两个数,我们可以使用最小堆来寻找最小的两个数。在这里,我们可以用字符出现的次数作为权值。
3、得到huffman编码
从根节点出发,向左走位0,向右走为1,找到一个叶子结点,就将他对应字符的huffman编码存到数组里面。
4、将huffman编码写入文件
使用哈希表,可以在O(1)时间内找到字符所对应的编码,将每8位编码构成一个字符写入文件中。如果最后的几位编码不够8位,那么我们就要在后面几位中补0.
5、编写配置文件
由于在解压时往往是没有源文件的,而我们要解压的话必须要知道这棵huffman树,所以在我们压缩的时候编写一个配置文件来存储huffman树的信息。在配置文件里面将:字符+出现的次数存在一行。在这里要使用itoa这个函数将次数转换成一个字符串存储。
解压缩:
1、读取配置文件
由于解压和压缩往往不是一起的,所以在解压之前我们要先还原huffman这棵树,读取配置文件时我们是一行一行进行存储的,所以读的时候我么最好一行一行的读。但是这里要注意两个问题。第一:因为string底层是char*,而每一行的第一个字符是0—255,所以这一块我们要进行处理,可以单独读取。第二:将字符串转换为数字,使用atoi函数。
2、构建huffman树
构建huffman树和压缩时是一样的。
3、解压缩
首先在压缩文件里面读取一个字符,然后解析这个字符的每一位,采用贪心法,只要遇到一个叶子结点,就代表我们还原了一个字符,这时候我们就要将这个字符写到解压缩文件里面。但是在这里要注意,有可能最后的几位编码是我们补上去的,所以在这里我们要以源文件中字符出现的次数来控制解压缩,根据huffman的性质可知,根节点的权重就是字符出现的次数。