实验原理
Huffman 编码
(1) Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman 编码是可变字长编码(VLC)的一种。
(2)Huffman 编码基于信源的概率统计模型,它的基本思路是,出现概率大的信源符号编长码,出现概率小的信源符号编短码,从而使平均码长最小。
(3)在程序实现中常使用一种叫做树的数据结构实现 Huffman 编码,由它编出的码是即时码。
Huffman编码的数据结构
typedef struct huffman_node_tag
{
unsigned char isLeaf;//是否为树叶
unsigned long count;//节点代表的符号加权和
struct huffman_node_tag *parent;//父节点指针
union//共同体:如果是叶节点,则只能有symbol,如果是非叶节点,只能有左右孩子指针
{
struct
{
struct huffman_node_tag *zero, *one;//左右孩子指针
};
unsigned char symbol;//符号,叶节点带有的字符
};
} huffman_node;
typedef struct huffman_code_tag
{
/*以比特为单位的代码的长度。 */
unsigned long numbits;
/* The bits that make up this code. The first
bit is at position 0 in bits[0]. The second
bit is at position 1 in bits[0]. The eighth
bit is at position 7 in bits[0]. The ninth
bit is at position 0 in bits[1]. */
unsigned char *bits;//指向该码比特串的指针
} huffman_code;
Huffman 编码的方法
(1)统计符号的发生概率
(2)把频率按从小到大的顺序排列
(3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点, 这两个叶子节点不再参与比较,新的根节点参与比较
(4) 重复 3,直到最后得到和为 1 的根节点
(5) 将形成的二叉树的左节点标 0,右节点标 1,把从最上面的根节点到最下面的叶 子节点途中遇到的 0,1 序列串起来,就得到了各个符号的编码。
实验流程
重要代码分析
读入待编码的源文件
int
main(int argc, char** argv)//argc命令行参数个数和argv命令行参数
{
char memory = 0;//memory为0时,为文件的编解码,memory为1时为内存的编解码
char compress = 1;//compress为1时为编码,为0时为解码
int opt;//getopt()的返回值
const char *file_in = NULL, *file_out = NULL;//输入输出文件名
//step1:add by yzhang for huffman statistics
const char *file_out_table = NULL;
//end by yzhang
FILE *in = stdin;
FILE *out = stdout;
//step1:add by yzhang for huffman statistics
FILE * outTable = NULL;//用于txt文件的输出
//end by yzhang
/* 获取命令行参数 */
while((opt = getopt(argc, argv, "i:o:cdhvm")) != -1)//opt的返回值为iocdhvm或-1,getopt处理以'-’开头的命令行参数
{
switch(opt)
{
case 'i'://输入文件
file_in = optarg;//optarg为选项参数缩写,该变量存放参数
break;
case 'o'://输出文件
file_out = optarg;
break;
case 'c'://压缩
compress = 1;
break;
case 'd'://解压缩
compress = 0;
break;
case 'h'://帮助显示使用方法
usage(stdout);
return 0;
case 'v'://输出版本版权信息
version(stdout);
return 0;
case 'm':
memory = 1; //memory为1时为内存的编解码
break;
// by yzhang for huffman statistics
case 't':
file_out_table = optarg;
break;
//end by yzhang
default:
usage(stderr); //如果是其他情况,则将使用方法信息送到标准错误文件
return 1;
}
}
getopt()函数是Linux和Unix系统环境下解析命令行的函数。在本次实验中,命令行可设置为“-i test1.doc -o test1.huff -c -t test1.txt”
Huffman文件编码时的总流程
#define MAX_SYMBOLS 256
typedef huffman_node* SymbolFrequencies[MAX_SYMBOLS];//表示信源符号的数组
typedef huffman_code* SymbolEncoder[MAX_SYMBOLS];//表示码字的数组,用于保存码表
Huffman文