home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / programm / 3426 < prev    next >
Encoding:
Text File  |  1993-01-06  |  3.3 KB  |  67 lines

  1. Newsgroups: comp.programming
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!rpi!batcomputer!cornell!karr
  3. From: karr@cs.cornell.edu (David Karr)
  4. Subject: Re: Locating duplicates
  5. Message-ID: <1993Jan7.021146.2290@cs.cornell.edu>
  6. Organization: Cornell Univ. CS Dept, Ithaca NY 14853
  7. References: <C07z6L.1Aq@world.std.com> <1993Jan5.043456.29130@micor.ocunix.on.ca> <1993Jan5.224141.21639@organpipe.uug.arizona.edu>
  8. Date: Thu, 7 Jan 1993 02:11:46 GMT
  9. Lines: 56
  10.  
  11. In article <1993Jan5.224141.21639@organpipe.uug.arizona.edu> dave@cs.arizona.edu (Dave Schaumann) writes:
  12. >Hmmm.  An even more robust algorithm would scan through the array to find
  13. >the difference between the largest and smallest elements, and then malloc()
  14. >an appropriate sized array.  Of course, if malloc() returns NULL, you'll
  15. >have to fall back to some kind of in-place sorting scheme.
  16.  
  17. How about this:
  18.  
  19. Assume in the following that all integers are 32 bits.
  20. Given array v of integers in which we have to detect duplicates,
  21. say v contains n entries.
  22. Allocate an array p of n integers and an array h of 512 integers, both
  23. initialized to all zeros.
  24.  
  25. Consider the 32-bit integers to be partitioned into 512=2^9 "segments"
  26. of 2^23 contiguous numbers sharing the same leading 9 bits.  Each
  27. entry in h is the index of the head of a list of entries in v (offset
  28. by 1 if this is in C, so that index 0 can indicate the empty list).
  29. The array p gives the "next" index for each item in a list (again
  30. offset by 1 if necessary).
  31.  
  32. The first pass over the data will put all the values from v that belong
  33. to the i-th segment into the list h[i], for each i.  This is done by
  34. scanning linearly once through the array; for each entry in v, examine
  35. the upper 9 bits and insert that value at the head of the corresponding
  36. list in h.  This takes a small constant time for each of n entries.
  37.  
  38. Now run through the 512 entries of h.  For each entry h[i], allocate a
  39. one-megabyte bit vector f (2^20 bytes=2^23 bits) initialized to all
  40. zeros.  Then scan the list pointed to by h[i], reading the lower 23
  41. bits of each value and setting the corresponding bit in f, and marking
  42. this entry in v as a duplicate if the flag was already set (we can put
  43. a distinguished value in the corresponding entry of p, for example,
  44. because we won't need to scan the list again).  Deallocate f when the
  45. end of the list is reached.  This phase takes a constant time to
  46. process each of the n entries in v, plus the time required to
  47. examine the 512 pointers in h.
  48.  
  49. And that's the end of the algorithm.  It takes K*n + K' time, where K
  50. is the time to perform the small number of operations required for
  51. each entry of v in the two phases, and K' represents a small overhead
  52. for each of the 512 head pointers.  That is, the algorithm is O(n),
  53. with a constant that I think compares reasonably well with algorithms
  54. that pre-scan v for min and max only and assume you can allocate an
  55. array large enough to index the entire range.
  56.  
  57. A shortcoming of course is that the running-time analysis is valid
  58. only if you can repeatedly allocate large amounts of zeroed-out memory
  59. in a small (essentially constant) time.  But pessimistic assumptions
  60. about memory initialization are bad for other index-array algorithms
  61. as well.
  62.  
  63. Of course any of the constants I used (e.g. 2^20, 512) can be
  64. adjusted to suit practical considerations, perhaps even at runtime.
  65.  
  66. -- David Karr (karr@cs.cornell.edu)
  67.