LZ77算法 的分析与实现(3)

解压缩过程在一个循环中执行,此循环会持续迭代执行直到所有的符号处理完。使用ipos来保存向压缩数据中写入的当前位,并用opos来保存写入恢复数据缓冲区中当前字节。在循环的每次迭代过程中,首先从压缩数据读取一位来确定要解码的标记类型。

在解析一个标记时,如果读取的首位是1,说明遇到了一个短语标记。此时读取它的每个成员,查找滑动窗口中的短语,然后将短语写入恢复数据缓冲区中。当查找每个短语时,调用网络函数ntohl来保证窗口中的偏移量和长度的字节顺序是与操作系统匹配的。这个转换过程是必要的,因为从压缩数据中读取出来的偏移量和长度是大端格式的。在数据被拷贝到滑动窗口之前,前向缓冲区被用做一个临时转换区来保存数据。最后,写入该标记编码的匹配的符号。如果读取的标记的首位是0,说明遇到了一个符号标记。在这种情况下,将该标记编码的匹配符号写入恢复数据缓冲区中。

一旦将解码的数据写入恢复数据的缓冲区中,就调整滑动窗口。要将数据通过滑动窗口,将数据从右边滑入窗口,从左边滑出窗口。移动的字节数与从标记中解码的字符数相等。

lz77_uncompress的时间复杂度为O(n),其中n是原始数据中符号的个数。

示例:LZ77的实现文件

(示例所需要的头文件信息请查阅这篇文章:数据压缩的重要组成部分--位操作)

/*lz77.c*/
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

#include "bit.h"
#include "compress.h"

/*compare_win 确定前向缓冲区中与滑动窗口中匹配的最长短语*/
static int compare_win(const unsigned char *window, const unsigned char *buffer,
                      int *offset, unsigned char *next)
{
    int match,longest,i,j,k;

/*初始化偏移量*/
    *offset = 0;

/*如果没有找到匹配,准备在前向缓冲区中返回0和下一个字符*/
    longest = 0;
    *next = buffer[0];

/*在前向缓冲区和滑动窗口中寻找最佳匹配*/
    for(k=0; k<LZ77_WINDOW_SIZE; k++)
    {
        i = k;
        j = 0;
        match = 0;

/*确定滑动窗口中k个偏移量匹配的符号数*/
        while(i<LZ77_WINDOW_SIZE && j<LZ77_BUFFER_SIZE - 1)
        {
            if(window[i] != buffer[j])
                break;

match++;
            i++;
            j++;
        }

/*跟踪最佳匹配的偏移、长度和下一个符号*/
        if(match > longest)
        {
            *offset = k;
            longest = match;
            *next = buffer[j];
        }
    }
    return longest;
}

/*lz77_compress  使用lz77算法压缩数据*/
int lz77_compress(const unsigned char *original,unsigned char **compressed,int size)
{
    unsigned char    window[LZ77_WINDOW_SIZE],
                      buffer[LZ77_BUFFER_SIZE],
                      *comp,
                      *temp,
                      next;
    int              offset,
                      length,
                      remaining,
                      hsize,
                      ipos,
                      opos,
                      tpos,
                      i;
    /*使指向压缩数据的指针暂时无效*/
    *compressed = NULL;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/63ea8e8e21f6166bd56ddba031d50800.html