该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
对hello_compress的改进:
在下一章中我们这会讲到,通过前文来预测后文的结构称为“预测模型(predictor/model)”,而使用预测模型处理数据来去除数据冗余的结构称为“编码器(coder)”,这是一个压缩算法最重要的两个部分,在hello_compress中,我们使用的是简单记录最近的三字符短语的模型,编码器则是简单用一bit位来表示预测结果,所以这个hello_compress是一个简单、低效的压缩器。这里我们简单列举一下高级的模型和编码器:
模型有PPM(Prediction by Partial Matching)、DMC(Dynamic Markov Compression)、CTW(Context Weighting Tree)、CM(Context Mixing)等。
编码器有Shanon-Fano编码、Huffman编码、数字编码、区间编码等。
在后几节我可能会用高效的模型和编码器在实现一个与WinRAR效果相近的压缩器,现在我们先来继续看我们的hello_compress。
在hello_compress中,我们只用了两个字符来存放最近的数据(这两个字符被称为上下文Context),我们可以增加到3个字符,但是predictor_map也要增加到3维,如果增加到4个字符的话,predictor_map就完全吃不消了,这里我们采用一个策略:减少每个字符的精确度,增加记录字符的个数。改进的程序如下:
// file: hello_compress_improved
#include
#include
int main(int argc, char** argv)
{
static char stdin_buffer[65536];
static char stdout_buffer[65536];
static unsigned char predict_map[65536];
unsigned short context = 0;
unsigned char block[8];
unsigned char flag_byte = 0;
int flag_pos = 0;
int block_pos = 0;
int i;
int next_char;
int out_char;
setbuffer(stdin, stdin_buffer, sizeof(stdin_buffer));
setbuffer(stdout, stdout_buffer, sizeof(stdout_buffer));
if(argc == 2 && strcmp(argv[1], "encode") == 0)
{
// compress
while((next_char = getchar()) != EOF)
{
// write to file if a flag_byte is full
if(flag_pos == 8)
{
putchar(flag_byte);
for(i = 0; i < block_pos; i++)
{
putchar(block[i]);
}
flag_byte = 0;
flag_pos = 0;
block_pos = 0;
}
// fill a flag byte
if(next_char == predict_map[context])
flag_byte |= (1 << flag_pos);
else
block[block_pos++] = next_char;
flag_pos += 1;
predict_map[context] = next_char;
context = (context << 4) ^ (next_char & 0xff);
}
// write last block
if(flag_pos > 0)