home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / sys / amiga / programmer / 4179 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  3.8 KB

  1. Path: comma.rhein.de!yaps!arno
  2. From: arno@yaps.rhein.de (Arno Eigenwillig)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: Re: realloc() bizzare behaviour...
  5. Message-ID: <MRm6y*XVf@yaps.rhein.de>
  6. Date: Sat, 17 Feb 1996 10:22:40 +0100
  7. References: <4fstmd$jco@bs33n.staffs.ac.uk>
  8. Organization: Yet Another Private Site in Meckenheim, Germany
  9. X-Copyright: This article may not be distributed on a CD-ROM
  10.  or in printed form without prior written consent of the author.
  11. X-Newsreader: Arn V 1.04
  12.  
  13. In article <4fstmd$jco@bs33n.staffs.ac.uk>, Wildfire writes:
  14.  
  15. > I've done an LZW compressor.
  16.  
  17. > struct string
  18. > {
  19. >     unsigned int
  20. >         length,
  21. >     char
  22. >         *string_body;
  23. > };
  24.  
  25. > Got that?  So first time I realloc(), I'm realloc()ing 257 of these 
  26. > structures.  Next time, 258, then 259, etc, etc.
  27.  
  28. I recently wrote an LZW compressor as CS homework, too. I've investi-
  29. gated the possibilities to manage the LZW code table in an efficient
  30. way and completely abandoned the idea of one big array. I believe my
  31. method to be more efficient and therefore allow myself to be so harsh
  32. and describe it instead of hacking around with yours.
  33.  
  34. First thing is, for compression you never need an LZW code's string in
  35. toto. If you investigate the compression's main loop, you will find
  36. out that it does not actually operate on a string S with a length of
  37. N, but it operates on a substring B (the first N-1 characters of S)
  38. and the trailing character C. Because B already has been assigned an
  39. LZW code, there is an entry in the code table for it, and you can
  40. take a pointer to it; or if B is only one character long, you can
  41. describe it by that character. Let us call the union which represents
  42. B either as pointer or as character by the name U.
  43.  
  44. Now you no longer need to manage actual strings (which is unfriendly
  45. to do because of variable length and all) but only pairs (B/C).
  46.  
  47. Second thing is, you need to manage the code table in a way that
  48. allows fast access. An array with the LZW code as index is just about
  49. the worst method imaginable, because you need to search linearily
  50. through it to find the LZW code for a given string. This will make
  51. your program O(N*N) or even slower.
  52.  
  53. My method was to use an array of hash chains (just like the Amiga file
  54. system does, BTW). That is, you create an array of M list headers
  55. (singly linked lists suffice, so a "list header" actually is a pointer
  56. to the first element) and define a hash function returning values
  57. between 0 and (M-1).
  58.  
  59. To put a string into the table, you compute its hash H, then put it
  60. into the H-th linked list. To search a string, you compute its hash H
  61. and linearily search through the H-th list. Technically speaking, this
  62. still gives you O(N*N) efficiency, but the Big-Oh-Notation kills
  63. benign coefficients: For 12 bit LZW compression, you cannot define
  64. more than 2^12 - 256 = 3840 LZW codes, so a few thousand hash chains
  65. result in nice short lists.
  66.  
  67. Obviously, to combine both ideas in an efficient way, you need a hash
  68. function that can compute a string's hash by knowing the hash of its
  69. first N-1 characters and the last character. The usual
  70.  
  71.     hash = 0;
  72.     for (i = 0; i < length; i++) {
  73.         hash = (hash*C + s[i]) % M;
  74.     }
  75.  
  76. is apt for this. Note that M should be prime and C should be large
  77. enough to allow for even distribution of the hash values of two-
  78. character-strings.
  79.  
  80. Alternatives to the hash chain array are binary search trees, flat
  81. arrays with rehashing, etc.
  82.  
  83. Disclaimer: The above is the result of a one-day homework project.
  84. Mileage for real-world tours may vary.
  85.  
  86. If you are willing to read TurboPascal *ugh* source code with German
  87. identifiers, I can provide an example implementation.
  88.  
  89. -- __
  90. __/// Arno Eigenwillig /\ <arno@yaps.rhein.de> \/ PGP key available.
  91. \XX/   V+49-2225-5870  /\ <Arnooo @ #amigager> \/ MIME 8bit welcome.
  92.               :-( Reduced net.presence until June 1996. )-:
  93.