用哈希表优化的lz77压缩算法的实现

最近终于有空研究研究E*F的K*KYU2。
和预料到的一样仍然是广泛使用LZ77,而且是毫不改变地使用LZ77……但是,时代进步了, 图片文件都是真彩色的了,大小变大了3倍,仍然使用LZ77的代价就是速度……大家都知道LZ77的特点就是解压超快,压缩巨慢(不然就不会有LZW这种 不伦不类的算法出来了……)
在png的相关网站上查找了一下优化方案,自己写了一下优化代码,虽然目前速度仍然不能很让人满意(在双核的机器上压 缩一个160多兆的文件用了60多秒),但是勉强可以用于实际应用了。贴出来和大家分享。如果要进一步优化,估计要玩一些trick,或是借助于指令级别 的。
以下讨论是基于4096字节定长窗口的字典的LZ77,字节组织是每bit表示查表或是原数据;查表是2字节,前16位表示索引,后16位表示长度,因此最长的序列只能有15字节。优化的思路是哈希表。
由 环境可以看出,低于3个字节的码序列是不需要查表保存的,因此码的最短长度是3个字节。使用一个哈希算法将之转化成1个字节的哈希码。这种哈希码共有 256个。当在查表前,首先要计算出当前字节及后面两个字节组成的序列的哈希码,然后在哈希码表中查得第一条匹配记录。当然,即使哈希码匹配,3字节并不 一定完全一样,这之后还是需要按字节比较。但这可以提前淘汰大部分的数据。匹配后,再查下一条记录。
优化的负担是额外增加了一个哈希码头指针表和 一个链表。每一个字节在字典中的更新都会造成它本身及前面两个字节处共3个字节的哈希码变化,即表项删除和增加。为了使这种删除和增加更有效率,做成了双 向链表的形式(实际测试下来比单向节省约一半时间)。当然这里的链表是以数组形式实现的,不需要动态分配空间,否则所带来的负担将是不可承受的。字典定义 如下:

《用哈希表优化的lz77压缩算法的实现》
《用哈希表优化的lz77压缩算法的实现》
typedef 
struct
 _tagLz77Dict 

{
《用哈希表优化的lz77压缩算法的实现》    
int     hash_start[256];
《用哈希表优化的lz77压缩算法的实现》    
int     hash_next[4096];
《用哈希表优化的lz77压缩算法的实现》    
int     hash_prev[4096];
《用哈希表优化的lz77压缩算法的实现》    
char    dict[4096];
《用哈希表优化的lz77压缩算法的实现》}

 lz77_dict, 
*
p_lz77_dict;
《用哈希表优化的lz77压缩算法的实现》

其中,hash_start是256个哈希码的首码索引。hash_next是每个哈希码的下一个编码,hash_prev是每个哈希码的前一个编码。均以-1表示无效。
字典初始化函数如下:

《用哈希表优化的lz77压缩算法的实现》
void
 init_dict(p_lz77_dict pdic)
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》


{
《用哈希表优化的lz77压缩算法的实现》    
int i;
《用哈希表优化的lz77压缩算法的实现》    memset(pdic
->dict, 04096);
《用哈希表优化的lz77压缩算法的实现》    
for (i = 0; i < 256++i) pdic->hash_start[i] = 1;
《用哈希表优化的lz77压缩算法的实现》    pdic
->hash_start[HASH(000)] = 409616;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》    
for (i = 0; i < 4096++i) {
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (i < 409616{
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_next[i] = 1;
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_prev[i] = 1;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        }
 else {
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_next[i] = (i+1);
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_prev[i] = (i1);
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》    }

《用哈希表优化的lz77压缩算法的实现》    pdic
->hash_prev[0= 1;
《用哈希表优化的lz77压缩算法的实现》    pdic
->hash_next[4095= 1;
《用哈希表优化的lz77压缩算法的实现》}


《用哈希表优化的lz77压缩算法的实现》

初始值仅后面16个码可用。
删除和增加哈希码函数:

《用哈希表优化的lz77压缩算法的实现》
void
 remove_dict_pos(p_lz77_dict pdic, 
int
 pos)
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》


{
《用哈希表优化的lz77压缩算法的实现》    
char a, b, c;
《用哈希表优化的lz77压缩算法的实现》    unsigned 
char hash;
《用哈希表优化的lz77压缩算法的实现》    
int old_pos = pos;
《用哈希表优化的lz77压缩算法的实现》    
int s, last;
《用哈希表优化的lz77压缩算法的实现》    a 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    b 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    c 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    hash 
= HASH(a, b, c);
《用哈希表优化的lz77压缩算法的实现》    last 
= pdic->hash_start[hash];
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》    
if (last == old_pos) {
《用哈希表优化的lz77压缩算法的实现》        
// head?
《用哈希表优化的lz77压缩算法的实现》
        last = pdic->hash_next[old_pos];
《用哈希表优化的lz77压缩算法的实现》        pdic
->hash_start[hash] = last;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (last >= 0{
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_prev[last] = 1;
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》    }
 else {
《用哈希表优化的lz77压缩算法的实现》        last 
= pdic->hash_prev[old_pos];
《用哈希表优化的lz77压缩算法的实现》        s 
= pdic->hash_next[old_pos];
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (last >= 0{
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_next[last] = s;
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (s >= 0{
《用哈希表优化的lz77压缩算法的实现》            pdic
->hash_prev[s] = last;
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》        pdic
->hash_prev[old_pos] = 1;
《用哈希表优化的lz77压缩算法的实现》    }

《用哈希表优化的lz77压缩算法的实现》}


《用哈希表优化的lz77压缩算法的实现》

《用哈希表优化的lz77压缩算法的实现》
//
 add a position’s hash rec

《用哈希表优化的lz77压缩算法的实现》

void
 add_dict_pos(p_lz77_dict pdic, 
int
 pos)
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》


{
《用哈希表优化的lz77压缩算法的实现》    
char a, b, c;
《用哈希表优化的lz77压缩算法的实现》    unsigned 
char hash;
《用哈希表优化的lz77压缩算法的实现》    
int old_pos = pos;
《用哈希表优化的lz77压缩算法的实现》    
int last;
《用哈希表优化的lz77压缩算法的实现》    a 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    b 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    c 
= pdic->dict[pos++];
《用哈希表优化的lz77压缩算法的实现》    pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》    hash 
= HASH(a, b, c);
《用哈希表优化的lz77压缩算法的实现》    last 
= pdic->hash_start[hash];
《用哈希表优化的lz77压缩算法的实现》    pdic
->hash_start[hash] = old_pos;
《用哈希表优化的lz77压缩算法的实现》    
if (last >= 0) pdic->hash_prev[last] = old_pos;
《用哈希表优化的lz77压缩算法的实现》    pdic
->hash_next[old_pos] = last;
《用哈希表优化的lz77压缩算法的实现》}


《用哈希表优化的lz77压缩算法的实现》

哈希算法随便选了一个(注意尽量不要全是3个字节异或,这样会使效率受影响,因为在实际应用中3个字节中有两个以上相同的比较多)

#define HASH(a, b, c)  (((unsigned char)a) + ((unsigned char)b) ^ ((unsigned char)c))

最后是解码函数主体:

《用哈希表优化的lz77压缩算法的实现》
//
 dest_buf should allocate size+size/8 bytes at least
《用哈希表优化的lz77压缩算法的实现》

//
 optimized algorithm

《用哈希表优化的lz77压缩算法的实现》

char
*
 fast_lz77_encode(
const
 
char
*
 buf, 
int
 size, 
int
*
 dest_size)
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》


{
《用哈希表优化的lz77压缩算法的实现》    nsg_auto_detect(__FUNCTION__);
《用哈希表优化的lz77压缩算法的实现》    
char* dest = (char*)malloc(size + size/8 + 1);
《用哈希表优化的lz77压缩算法的实现》    
char* org_dest = dest;
《用哈希表优化的lz77压缩算法的实现》    lz77_dict dict;
《用哈希表优化的lz77压缩算法的实现》    
int dict_start = 4096  16;
《用哈希表优化的lz77压缩算法的实现》    
int left = size;
《用哈希表优化的lz77压缩算法的实现》    unsigned 
char bits = 0;
《用哈希表优化的lz77压缩算法的实现》    
int bitcount = 8;
《用哈希表优化的lz77压缩算法的实现》    
char* bits_pos = dest;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》    
if (size == 0{
《用哈希表优化的lz77压缩算法的实现》        free(dest);
《用哈希表优化的lz77压缩算法的实现》        
return NULL;
《用哈希表优化的lz77压缩算法的实现》    }

《用哈希表优化的lz77压缩算法的实现》    init_dict(
&dict);
《用哈希表优化的lz77压缩算法的实现》    dest
++;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》    
while(left > 0{
《用哈希表优化的lz77压缩算法的实现》        
int max_len = 0;
《用哈希表优化的lz77压缩算法的实现》        
int table_index = 0;
《用哈希表优化的lz77压缩算法的实现》        
int i;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (left >= 3{
《用哈希表优化的lz77压缩算法的实现》            unsigned 
char hash = HASH(buf[0], buf[1], buf[2]);
《用哈希表优化的lz77压缩算法的实现》            
int offset = dict.hash_start[hash];
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》            
if (offset >= 0{
《用哈希表优化的lz77压缩算法的实现》                
int len = 0;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》                
while (offset >= 0{
《用哈希表优化的lz77压缩算法的实现》                    
int pos = offset;
《用哈希表优化的lz77压缩算法的实现》                    len 
= 0;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》                    
while (len < 15{
《用哈希表优化的lz77压缩算法的实现》                        
if (dict.dict[pos++!= buf[len]) break;
《用哈希表优化的lz77压缩算法的实现》                        pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》                        
++len;
《用哈希表优化的lz77压缩算法的实现》                    }

《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》                    
if (len > max_len) {
《用哈希表优化的lz77压缩算法的实现》                        table_index 
= (offset  len) & 0xFFF;
《用哈希表优化的lz77压缩算法的实现》                        max_len 
= len;
《用哈希表优化的lz77压缩算法的实现》                    }

《用哈希表优化的lz77压缩算法的实现》                    offset 
= dict.hash_next[offset];
《用哈希表优化的lz77压缩算法的实现》                }

《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (max_len >= 3{
《用哈希表优化的lz77压缩算法的实现》            
int i;
《用哈希表优化的lz77压缩算法的实现》            
int pos = dict_start  2;
《用哈希表优化的lz77压缩算法的实现》            
int old_pos;
《用哈希表优化的lz77压缩算法的实现》            
*(unsigned short*)dest = (table_index << 4| max_len;
《用哈希表优化的lz77压缩算法的实现》            
if (pos < 0) pos += 4096;
《用哈希表优化的lz77压缩算法的实现》            old_pos 
= pos;
《用哈希表优化的lz77压缩算法的实现》            
// remove previous 2, next 2 dict
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》
            for (i = max_len + 2; i >= 0i) {
《用哈希表优化的lz77压缩算法的实现》                remove_dict_pos(
&dict, pos++);
《用哈希表优化的lz77压缩算法的实现》                pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》            
// update dict
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》
            for (i = 0; i < max_len; ++i ) {
《用哈希表优化的lz77压缩算法的实现》                dict.dict[dict_start
++= buf[i];
《用哈希表优化的lz77压缩算法的实现》                dict_start 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》            pos 
= old_pos;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》            
for (i = max_len + 2; i >= 0i) {
《用哈希表优化的lz77压缩算法的实现》                add_dict_pos(
&dict, pos++);
《用哈希表优化的lz77压缩算法的实现》                pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》            dest 
+= 2;
《用哈希表优化的lz77压缩算法的实现》            buf 
+= max_len;
《用哈希表优化的lz77压缩算法的实现》            left 
-= max_len;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        }
 else {
《用哈希表优化的lz77压缩算法的实现》            
int pos = dict_start  2;
《用哈希表优化的lz77压缩算法的实现》            
int i;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》            
/**//* bits |= 0; */  /**//* not necessary */
《用哈希表优化的lz77压缩算法的实现》            
if (pos < 0) pos += 4096;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》            
for (i = 0; i < 3++i ) {
《用哈希表优化的lz77压缩算法的实现》                remove_dict_pos(
&dict, pos++);
《用哈希表优化的lz77压缩算法的实现》                pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》            dict.dict[dict_start
++= *buf;
《用哈希表优化的lz77压缩算法的实现》            dict_start 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            pos 
-= 3;
《用哈希表优化的lz77压缩算法的实现》            
if (pos < 0) pos += 4096;
《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》            
for (i = 0; i < 3++i ) {
《用哈希表优化的lz77压缩算法的实现》                add_dict_pos(
&dict, pos++);
《用哈希表优化的lz77压缩算法的实现》                pos 
&= 0xFFF;
《用哈希表优化的lz77压缩算法的实现》            }

《用哈希表优化的lz77压缩算法的实现》            
*dest++ = *buf++;
《用哈希表优化的lz77压缩算法的实现》            
left;
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》《用哈希表优化的lz77压缩算法的实现》        
if (bitcount == 0{
《用哈希表优化的lz77压缩算法的实现》            
// full
《用哈希表优化的lz77压缩算法的实现》
            bitcount = 8;
《用哈希表优化的lz77压缩算法的实现》            
*bits_pos = bits;
《用哈希表优化的lz77压缩算法的实现》            bits_pos 
= dest++;
《用哈希表优化的lz77压缩算法的实现》            bits 
= 0;
《用哈希表优化的lz77压缩算法的实现》        }

《用哈希表优化的lz77压缩算法的实现》        bits 
>>= 1;
《用哈希表优化的lz77压缩算法的实现》    }

《用哈希表优化的lz77压缩算法的实现》    
*bits_pos = bits >> bitcount;
《用哈希表优化的lz77压缩算法的实现》    
*dest_size = dest  org_dest;
《用哈希表优化的lz77压缩算法的实现》    
return org_dest;
《用哈希表优化的lz77压缩算法的实现》}


《用哈希表优化的lz77压缩算法的实现》

 

    原文作者:哈希算法
    原文地址: https://blog.csdn.net/olncy/article/details/2462448
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞