免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: mhello
打印 上一主题 下一主题

请教:哪种字符串压缩算法有比较好的压缩率分布? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2010-02-09 16:53 |只看该作者
本帖最后由 llsshh 于 2010-02-09 16:56 编辑

Thanks Haruhiko Okumura.
  1. /**************************************************************
  2.     LZSS.C -- A Data Compression Program
  3.     (tab = 4 spaces)
  4. ***************************************************************
  5.     4/6/1989 Haruhiko Okumura
  6.     Use, distribute, and modify this program freely.
  7.     Please send me your improved versions.
  8.         PC-VAN        SCIENCE
  9.         NIFTY-Serve    PAF01022
  10.         CompuServe    74050,1022
  11. **************************************************************/

  12. #include "stdafx.h"
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>

  17. #define N         4096    /* size of ring buffer */
  18. #define F           18    /* upper limit for match_length */
  19. #define THRESHOLD    2  /* encode string into position and length
  20.                            if match_length is greater than this */
  21. #define NIL            N    /* index for root of binary search trees */

  22. static unsigned long int
  23.         textsize = 0,    /* text size counter */
  24.         codesize = 0,    /* code size counter */
  25.         printcount = 0;    /* counter for reporting progress every 1K bytes */
  26. static unsigned char
  27.         text_buf[N + F - 1];    /* ring buffer of size N,
  28.             with extra F-1 bytes to facilitate string comparison */
  29. static int        match_position, match_length,  /* of longest match.  These are
  30.             set by the InsertNode() procedure. */
  31.         lson[N + 1], rson[N + 257], dad[N + 1];  /* left & right children &
  32.             parents -- These constitute binary search trees. */
  33. //static FILE    *infile, *outfile;  /* input & output files */

  34. void InitTree(void)  /* initialize trees */
  35. {
  36.     int  i;

  37.     /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
  38.        left children of node i.  These nodes need not be initialized.
  39.        Also, dad[i] is the parent of node i.  These are initialized to
  40.        NIL (= N), which stands for 'not used.'
  41.        For i = 0 to 255, rson[N + i + 1] is the root of the tree
  42.        for strings that begin with character i.  These are initialized
  43.        to NIL.  Note there are 256 trees. */

  44.     for (i = N + 1; i <= N + 256; i++)
  45.     {
  46.                 rson[i] = NIL;
  47.     }       
  48.     for (i = 0; i < N; i++)
  49.     {
  50.                 dad[i] = NIL;
  51.     }       
  52.        
  53. }

  54. void InsertNode(int r)
  55. {
  56.         /* Inserts string of length F, text_buf[r..r+F-1], into one of the
  57.        trees (text_buf[r]'th tree) and returns the longest-match position
  58.        and length via the global variables match_position and match_length.
  59.        If match_length = F, then removes the old node in favor of the new
  60.        one, because the old one will be deleted sooner.
  61.        Note r plays double role, as tree node and position in buffer. */

  62.     int  i, p, cmp;
  63.     unsigned char  *key;

  64.     cmp = 1;  key = &text_buf[r];  p = N + 1 + key[0];
  65.     rson[r] = lson[r] = NIL;  match_length = 0;
  66.     for ( ; ; )
  67.         {
  68.         if (cmp >= 0)
  69.                 {
  70.             if (rson[p] != NIL)
  71.                                 p = rson[p];
  72.             else
  73.                         {  
  74.                                 rson[p] = r;  
  75.                                 dad[r] = p;  
  76.                                 return;  
  77.                         }
  78.         }
  79.                 else
  80.                 {
  81.             if (lson[p] != NIL)
  82.                                 p = lson[p];
  83.             else
  84.                         {  
  85.                                 lson[p] = r;  
  86.                                 dad[r] = p;
  87.                                 return;  
  88.                         }
  89.         }
  90.         for (i = 1; i < F; i++)
  91.         {
  92.             if ((cmp = key[i] - text_buf[p + i]) != 0)  
  93.                                 break;
  94.         }       
  95.         if (i > match_length) {
  96.             match_position = p;
  97.             if ((match_length = i) >= F)  break;
  98.         }
  99.     }
  100.     dad[r] = dad[p];  
  101.         lson[r] = lson[p];
  102.         rson[r] = rson[p];
  103.     dad[lson[p]] = r;
  104.         dad[rson[p]] = r;
  105.     if (rson[dad[p]] == p)
  106.                 rson[dad[p]] = r;
  107.     else                  
  108.                 lson[dad[p]] = r;
  109.     dad[p] = NIL;  /* remove p */
  110. }

  111. void DeleteNode(int p)  /* deletes node p from tree */
  112. {
  113.     int  q;
  114.    
  115.     if (dad[p] == NIL)
  116.                 return;  /* not in tree */
  117.     if (rson[p] == NIL)
  118.                 q = lson[p];
  119.     else if (lson[p] == NIL)
  120.                 q = rson[p];
  121.     else
  122.         {
  123.         q = lson[p];
  124.         if (rson[q] != NIL)
  125.                 {
  126.             do {
  127.                                 q = rson[q];  
  128.                         } while (rson[q] != NIL);
  129.             rson[dad[q]] = lson[q];  
  130.                         dad[lson[q]] = dad[q];
  131.             lson[q] = lson[p];  
  132.                         dad[lson[p]] = q;
  133.         }
  134.         rson[q] = rson[p];  
  135.                 dad[rson[p]] = q;
  136.     }
  137.     dad[q] = dad[p];
  138.     if (rson[dad[p]] == p)
  139.                 rson[dad[p]] = q;  
  140.         else
  141.                 lson[dad[p]] = q;
  142.     dad[p] = NIL;
  143. }

  144. void App_LZSS_Encode(unsigned char* in,unsigned char* out)
  145. {
  146.     int  i, c, len, r, s, last_match_length, code_buf_ptr,ii,jj;
  147.     unsigned char  code_buf[17], mask;
  148.    
  149.     InitTree();  /* initialize trees */
  150.     code_buf[0] = 0;  /* code_buf[1..16] saves eight units of code, and
  151.         code_buf[0] works as eight flags, "1" representing that the unit
  152.         is an unencoded letter (1 byte), "0" a position-and-length pair
  153.         (2 bytes).  Thus, eight units require at most 16 bytes of code. */
  154.     code_buf_ptr = mask = 1;
  155.     s = 0;  
  156.         r = N - F;
  157.        
  158.     for (i = s; i < r; i++)
  159.                 text_buf[i] = ' ';  
  160.                 /* Clear the buffer with
  161.         any character that will appear often. */
  162.     for (len = 0; len < F && (c = in[len]/*getc(infile)*/) != '\0'/*EOF*/; len++)
  163.         text_buf[r + len] = c;  /* Read F bytes into the last F bytes of
  164.             the buffer */
  165.     if ((textsize = len) == 0)
  166.                 return;  /* text of size zero */
  167.     for (i = 1; i <= F; i++)
  168.                 InsertNode(r - i);  
  169.                 /* Insert the F strings,
  170.         each of which begins with one or more 'space' characters.  Note
  171.         the order in which these strings are inserted.  This way,
  172.         degenerate trees will be less likely to occur. */
  173.     InsertNode(r);  /* Finally, insert the whole string just read.  The
  174.         global variables match_length and match_position are set. */
  175.         ii=jj=0;
  176.     do {
  177.         if (match_length > len)
  178.                         match_length = len;  /* match_length
  179.             may be spuriously long near the end of text. */
  180.         if (match_length <= THRESHOLD)
  181.                 {
  182.             match_length = 1;  /* Not long enough match.  Send one byte. */
  183.             code_buf[0] |= mask;  /* 'send one byte' flag */
  184.             code_buf[code_buf_ptr++] = text_buf[r];  /* Send uncoded. */
  185.         }
  186.                 else
  187.                 {
  188.             code_buf[code_buf_ptr++] = (unsigned char) match_position;
  189.             code_buf[code_buf_ptr++] = (unsigned char)
  190.                 (((match_position >> 4) & 0xf0)
  191.              | (match_length - (THRESHOLD + 1)));  /* Send position and
  192.                     length pair. Note match_length > THRESHOLD. */
  193.         }
  194.         if ((mask <<= 1) == 0)
  195.                 {  /* Shift mask left one bit. */
  196.             for (i = 0; i < code_buf_ptr; i++)  /* Send at most 8 units of */
  197.                                 out[jj++]=   code_buf[i] ;  /*putc(code_buf[i], outfile);  */  /* code together */
  198.             codesize += code_buf_ptr;
  199.             code_buf[0] = 0;
  200.                         code_buf_ptr = mask = 1;
  201.         }
  202.         last_match_length = match_length;
  203.         for (i = 0; i < last_match_length &&
  204.                 (c = in[F+ii]/*getc(infile)*/) != '\0'/*EOF*/; i++)
  205.         {
  206.                         ii++;
  207.             DeleteNode(s);        /* Delete old strings and */
  208.             text_buf[s] = c;    /* read new bytes */
  209.             if (s < F - 1)
  210.                                 text_buf[s + N] = c;  /* If the position is
  211.                 near the end of buffer, extend the buffer to make
  212.                 string comparison easier. */
  213.             s = (s + 1) & (N - 1);  
  214.                         r = (r + 1) & (N - 1);
  215.                 /* Since this is a ring buffer, increment the position
  216.                    modulo N. */
  217.             InsertNode(r);    /* Register the string in text_buf[r..r+F-1] */
  218.         }
  219.         if ((textsize += i) > printcount)
  220.                 {
  221.        //     printf("%12ld\r", textsize);  
  222.                         printcount += 1024;
  223.                 /* Reports progress each time the textsize exceeds
  224.                    multiples of 1024. */
  225.         }
  226.         while (i++ < last_match_length)
  227.                 {    /* After the end of text, */
  228.             DeleteNode(s);                    /* no need to read, but */
  229.             s = (s + 1) & (N - 1);  r = (r + 1) & (N - 1);
  230.             if (--len) InsertNode(r);        /* buffer may not be empty. */
  231.         }
  232.     } while (len > 0);    /* until length of string to be processed is zero */
  233.     if (code_buf_ptr > 1)
  234.         {        /* Send remaining code. */
  235.         for (i = 0; i < code_buf_ptr; i++)
  236.                 {
  237.                         out[jj++] = code_buf[i]; /*putc(code_buf[i], outfile);*/
  238.                
  239.                 }
  240.                 out[jj] = '\0';
  241.         codesize += code_buf_ptr;
  242.     }
  243.     printf("In : %ld bytes\n", textsize);    /* Encoding is done. */
  244.     printf("Out: %ld bytes\n", codesize);
  245.     printf("Out/In: %.3f\n", (double)codesize / textsize);
  246. }

  247. void App_LZSS_Decode(unsigned char* in,unsigned char* out )    /* Just the reverse of Encode(). */
  248. {
  249.     int  i, j, k, r, c, iii,jjj;
  250.     unsigned int  flags;
  251.    
  252.     for (i = 0; i < N - F; i++)
  253.                 text_buf[i] = ' ';
  254.     r = N - F;
  255.         flags = 0;
  256.     for ( iii=0,jjj=0; ; )
  257.         {
  258.         if (((flags >>= 1) & 256) == 0)
  259.                 {
  260.             if ((c = in[iii++]/*getc(infile)*/) == '\0' /*EOF*/)
  261.                                 break;
  262.             flags = c | 0xff00;        /* uses higher byte cleverly */
  263.         }                            /* to count eight */
  264.                
  265.         if (flags & 1)
  266.                 {
  267.             if ((c = in[iii++]/*getc(infile)*/) == '\0'/*EOF*/)
  268.                                 break;
  269.             out[jjj++] = c;  /*putc(c, outfile);  */
  270.                         text_buf[r++] = c;  
  271.                         r &= (N - 1);
  272.         }
  273.                 else
  274.                 {
  275.             if ((i = in[iii++]/*getc(infile)*/) == '\0'/*EOF*/)
  276.                                 break;
  277.             if ((j = in[iii++]/*getc(infile)*/) == '\0'/*EOF*/)
  278.                                 break;
  279.             i |= ((j & 0xf0) << 4);
  280.                         j = (j & 0x0f) + THRESHOLD;
  281.             for (k = 0; k <= j; k++)
  282.                         {
  283.                 c = text_buf[(i + k) & (N - 1)];
  284.                 out[jjj++] = c; /*putc(c, outfile);  */
  285.                                 text_buf[r++] = c;  
  286.                                 r &= (N - 1);
  287.             }
  288.         }
  289.     }
  290.        
  291. }

  292. int main(int argc, char *argv[])
  293. {
  294. #if 0
  295.     char  *s;
  296.    
  297.     if (argc != 4) {
  298.         printf("'lzss e file1 file2' encodes file1 into file2.\n"
  299.                "'lzss d file2 file1' decodes file2 into file1.\n");
  300.         return EXIT_FAILURE;
  301.     }
  302.        
  303.     if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
  304.      || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
  305.      || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
  306.         printf("??? %s\n", s);  return EXIT_FAILURE;
  307.     }
  308.          if (toupper(*argv[1]) == 'E') Encode();  else Decode();
  309.     fclose(infile);  fclose(outfile);
  310.     return EXIT_SUCCESS;
  311. #else

  312.         unsigned char in[] ="aabbccddeeffgghhiijjkkllmmnnaabbccddeeffgghhiijjkkllmmnn我爱你中国我爱你中国";
  313.         unsigned char out[1000];
  314.         printf("in = %s\n",in);
  315.         Encode(in,out);
  316.         printf("After encode **********\n");
  317.         printf("out = %s\n",out);
  318.         Decode(out,in);
  319.         printf("After decode **********\n");
  320.         printf("in = %s\n",in);
  321.        
  322.         return 0;
  323. #endif
  324.    
  325. }
复制代码

论坛徽章:
0
12 [报告]
发表于 2010-02-09 17:42 |只看该作者
本帖最后由 mhello 于 2010-02-09 17:44 编辑

回复 11# llsshh


  非常感谢!楼主好人,祝新春快乐!

论坛徽章:
0
13 [报告]
发表于 2010-02-09 18:05 |只看该作者
同时感谢 Haruhiko Okumura,祝他情人节快乐!

论坛徽章:
0
14 [报告]
发表于 2010-02-09 18:12 |只看该作者
回复 11# llsshh


    感谢提供的代码,, 研究研究`

论坛徽章:
0
15 [报告]
发表于 2010-02-09 18:26 |只看该作者
回复 11# llsshh


    冒昧的问一句

  1. #if 0
  2. .....
  3. #else
  4. .....
  5. #endif
复制代码
是什么意思?  有这个必要吗?
再问问... 这代码能在Linux 下编译吗?

论坛徽章:
0
16 [报告]
发表于 2010-02-10 09:57 |只看该作者
#if 0
.....
#else
.....
#endif
这个是我测试用的。
应该可以,我这里没有环境试验。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP