home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / GCC / GERLIB_DEV08B.LHA / gerlib / libg++ / etc / ADT-examples / search.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  6.0 KB  |  224 lines

  1. // From: "Douglas C. Schmidt" <schmidt@blanche.ics.uci.edu>
  2. // Date: Sat, 29 Oct 88 14:11:51 -0700
  3.  
  4. #ifdef amiga
  5. #include <use_standard_argc_argv.h>
  6. #endif
  7.  
  8. #include <stream.h>
  9. #include <std.h>
  10. #include <builtin.h>
  11.  
  12. /**********************************************************************/
  13. /**********************************************************************/
  14.  
  15. typedef int ITEM_TYPE;
  16.  
  17. class Additive_Search
  18. {
  19.   
  20.   // Implements the binary search variation described on pages 138 and 139
  21.   // of Tim Standish's ``Data Structure Techniques'' textbook.  The big
  22.   // win here is that this version uses no division (or right shift),
  23.   // only addition, so it runs faster on most computers.
  24.   
  25. private:
  26.   
  27.   ITEM_TYPE        *Vector_Buffer; // Hold's copy of the initialized search structure
  28.   int               Vector_Length; // Length of the user's input
  29.   static int        Tree_Height;   // Height of the implicit binary search tree
  30.   static ITEM_TYPE *Temp;          // Temporary storage during initialization
  31.   
  32.   void Fill_Buffer (int h, int i); // Transforms sorted array into special
  33.   // representation that supports the
  34.   // additive binary search technique
  35. public:
  36.   
  37.   Additive_Search  (ITEM_TYPE *Array, int Len);
  38.   int  Is_Member   (ITEM_TYPE K);
  39.   ~Additive_Search (void);
  40.   
  41. };
  42.  
  43. int        Additive_Search::Tree_Height = 0;
  44. ITEM_TYPE* Additive_Search::Temp = 0; 
  45.  
  46. /**********************************************************************/
  47.  
  48. void Additive_Search::Fill_Buffer (int Hgt, int Index) 
  49. {
  50.   // Uses a very concise recursive routine to initialize the Vector_Buffer from
  51.   // the original sorted array (which must have been sorted, or else this
  52.   // *won't* work)!  This magic sequence of statements transforms the original sorted
  53.   // array into an new array representing the level order traversal of a complete
  54.   // binary search tree.  See Standish, page 138 for details...
  55.   
  56.   if ((Hgt <= Tree_Height) && (Index < Vector_Length))
  57.     {
  58.       Fill_Buffer (Hgt + 1, (Index + Index) + 1);
  59.       Vector_Buffer [Index] = *Temp++;
  60.       Fill_Buffer (Hgt + 1, (Index + Index) + 2);
  61.     }
  62.  
  63. }
  64.  
  65. /**********************************************************************/
  66.  
  67. Additive_Search::Additive_Search (ITEM_TYPE *Array, int Len)
  68. {
  69.   Tree_Height = lg (Len);
  70.   Vector_Length = Len;
  71.   Temp = Array;
  72.   Vector_Buffer = new ITEM_TYPE [Len];
  73.   Fill_Buffer (0, 0);             // Tree_Height and Index both start off at 0
  74. }
  75.  
  76. /**********************************************************************/
  77.  
  78. int  
  79. Additive_Search::Is_Member (ITEM_TYPE K) 
  80. {
  81.   // Performs the additive binary search upon the initialized Vector_Buffer.
  82.   // Note that we perform no division or multiplication in this search.
  83.   // Such omissions generally yield faster running times on most machines.
  84.   
  85.   register int i = 0;
  86.   
  87.   while (i < Vector_Length)
  88.     {
  89.       register int Cmp = (Vector_Buffer [i] - K);
  90.     
  91.       if (Cmp == 0) 
  92.         return 1;
  93.       else
  94.         {
  95.           i += i + 1;
  96.           if (Cmp < 0) 
  97.             i++;
  98.         }
  99.     }
  100.   
  101.   return 0;
  102. }
  103.  
  104. /**********************************************************************/
  105.  
  106. Additive_Search::~Additive_Search (void) 
  107. {
  108.   delete Vector_Buffer;
  109. }
  110.  
  111. /**********************************************************************/
  112. /**********************************************************************/
  113.  
  114. class Binary_Search 
  115. {
  116.   // Performs the typical binary search algorithm.  For comparison purposes only.
  117. #define COPY(DESTTYPE,DEST,SRC,NB) {\
  118.   register DESTTYPE a = (DEST); \
  119.   register DESTTYPE b = (SRC);\
  120.   register int i, j = (NB);\
  121.   for (i = (j & 07)+1; --i;) *a++ = *b++;\
  122.     for (i = (j>>3)+1; --i>0;) {\
  123.       *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++;\
  124.       *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++;\
  125. }}
  126.  
  127. private:
  128.   ITEM_TYPE *Vector_Buffer;
  129.   int        Vector_Length;
  130.   
  131. public:
  132.   
  133.   Binary_Search (ITEM_TYPE *Array, int Len): Vector_Length (Len)
  134.     {
  135.       Vector_Buffer = new ITEM_TYPE [Len];
  136.       
  137.       COPY (ITEM_TYPE*, Vector_Buffer, Array, Len); // The infamous Duff's Device!
  138.     }
  139.   
  140.   int  Is_Member (ITEM_TYPE K) 
  141.     {                           // Yawn, this looks familiar
  142.       register int hi;
  143.       register int lo;
  144.       
  145.       for (lo = 0, hi = Vector_Length - 1; lo <= hi ;) 
  146.         {
  147.           register int mid = (lo + hi) >> 1;
  148.           
  149.           if (Vector_Buffer [mid] == K) 
  150.             return 1;
  151.           else if (Vector_Buffer [mid] < K) 
  152.             lo = mid + 1;
  153.           else 
  154.             hi = mid - 1;
  155.         }
  156.       
  157.       return 0;
  158.     }
  159.   
  160.   ~Binary_Search (void) 
  161.     {
  162.       delete Vector_Buffer;
  163.     }   
  164. };
  165.  
  166. /**********************************************************************/
  167.  
  168. static int  Cmp (void *A, void *B) 
  169. { // Too bad we lack lambdas!
  170.   return (*(ITEM_TYPE*)A < *(ITEM_TYPE*)B)? 
  171.           -1 : 
  172.          ((*(ITEM_TYPE*)A == *(ITEM_TYPE*)B) ? 0 : 1);
  173. }
  174.  
  175. /**********************************************************************/
  176.  
  177. double return_elapsed_time (double);
  178. double start_timer (void);
  179. void   Gen_Rand (ITEM_TYPE Buf[], int Size);
  180.  
  181. int main (int, char *argv[]) 
  182. {
  183.   int        Size = atoi (argv [1]);
  184. #ifdef __GNUC__
  185.   ITEM_TYPE  Buf [Size];
  186. #else
  187.   ITEM_TYPE  *Buf = new ITEM_TYPE[Size];
  188. #endif
  189.   
  190.   Gen_Rand (Buf, Size);
  191.   qsort ((void *) Buf, Size, sizeof (ITEM_TYPE), Cmp);
  192.   
  193.   Additive_Search Foo (Buf, Size); 
  194.   Binary_Search   Bar (Buf, Size);
  195.   
  196.   start_timer ();
  197.   for (int i = 0; i < Size ; i++) 
  198.     if (! Bar.Is_Member (Buf [i]))
  199.       cout << "bad news, buf [" << i << "] = " << Buf [i] << "!\n";
  200.  
  201.   double Elapsed_Time = return_elapsed_time (0.0);
  202.   cout << "Binary Time = " << Elapsed_Time << "\n";
  203.   
  204.   start_timer ();
  205.   for (i = 0; i < Size ; i++) 
  206.     if (! Foo.Is_Member (Buf [i])) 
  207.       cout << "bad news, buf [" << i << "] = " << Buf [i] << "!\n";
  208.  
  209.   Elapsed_Time = return_elapsed_time (0.0);
  210.   cout << "Additive Time = " << Elapsed_Time << "\n";
  211.   
  212.   return 0;
  213. }
  214.  
  215. void Gen_Rand (ITEM_TYPE Buf[], int Size) 
  216. { // Generates some random numbers
  217.   srand (getpid ());
  218.   
  219.   for (int i = 0; i < Size; i++) 
  220.     Buf [i] = ITEM_TYPE (rand ());
  221.   
  222. }
  223.  
  224.