动态二分搜索器

来源:互联网 发布:深圳软件行业协会电话 编辑:程序博客网 时间:2024/06/07 10:10

算法导论的摊还分析章中的一道思考题,挺有意思的,2天以来用空闲时间写了下,debug亲测可运行。

//DynBinSearcher.h#ifndef DYNBINSEARCHER_#define DYNBINSEARCHER_template <class T>int binary_search(T key, T *arr, const int size){   int i = 0, j = size;   int mid = 0;   while (i < j){      mid = (i + j) / 2;      if (key < arr[mid]){         j = mid;      }      else{         if (key > arr[mid]){            i = mid + 1;         }         else{            return mid;         }      }   }   return -1;}struct Pair{   Pair(int n_1, int n_2){      i = n_1;      j = n_2;   }   int i;   int j;};template <class T>/* Dynamic binary seacher* Brief: an improved version of binary search,* elements are partitioned into ⌈lg(n+1)⌉* sorted subarrays with size of 1, 2, 4, ..., 2^⌈lg(n+1)⌉,* Although each individual array is sorted, elements in* different arrays bear no particular relationship to each* other.* search:   scan every subarrays from left to right, if* element is possibly in this subarray, then search it.* deletion: search the position of element, then take one* element from another subarray to replace it.* efficiency:* search: (worst case)lg(n)*lg(n)* insert: (worst case)O(n) (armotized cost)O(lg(n))* erase: (worst case)O(n) (armotized cost)O(lg(n))*/class DynBinSearcher{   template <class T>   friend int binary_search(T, T *, const int);public:   //IN ASSERTION: size != 0   DynBinSearcher(unsigned int size){      begin = 0;      //calculation of total bits needed      int i = 0;      while ((size >>= 1) | 0){         i++;      }      num = i + 1;      arrays = new T*[num];      //subarrays' space allocation      for (; i >= 0; i--){         arrays[i] = new int[1 << i];      }      //allocation for count      begin = 0;      full_bit = -1;      extra_bit = -1;   }   ~DynBinSearcher(){      destroyArrays();   }   Pair search(const T &);   //bool search(const T &)const;   void insert(const T &);   bool erase(const T &);#ifdef TEST   void output();#endifprivate:   //helper function to destroy current arrays   void destroyArrays(){      for (int i = 0; i < num; i++){         delete[]arrays[i];      }      delete[]arrays;   }   //for code simplicity, return 0 when full_bit == -1,   //2^full_bit otherwise.   inline int full()   {      return (full_bit == -1) ? 0 : 1 << full_bit;   }   //return the size of a subarray.   inline int size(int index)   {      if (index <= full_bit){         return 1 << index;      }      if (index < begin){         return full() + extra_bit + 1;      }      return full() + extra_bit;   }   //span space as twice bigger   void grow();   T **arrays;   int num;   //begin: current subarray to insert   int begin;   //extra_bit: extra bits in subarray ayyays[begin].   int extra_bit;   //full_bit: the rightest full subarray.   int full_bit;};template <class T>Pair DynBinSearcher<T>::search(const T &x){   int i = 0, j = 0;   while (i < num){      if (arrays[i][0] < x &&          x < arrays[i][size(i) - 1] &&          -1 != (j = binary_search(x, arrays[i], size(i)))          ){         return Pair(i, j);      }      if (arrays[i][0] == x){         return Pair(i, 0);      }      if (arrays[i][size(i) - 1] == x){         return Pair(i, size(i) - 1);      }      i++;   }   //not found, set i = j = -1   return Pair(-1, -1);}template <class T>void DynBinSearcher<T>::insert(const T &x){   int i = 0;   int size = full() + extra_bit;   for (; i < size; i++){      if (arrays[begin][i] > x){         break;      }   }   for (int j = size; j > i; j--){      arrays[begin][j] = arrays[begin][j - 1];   }   arrays[begin][i] = x;   //update parameters   if (++begin == num){      if (++extra_bit == full()){         extra_bit = 0;         if (++full_bit == num - 1){            //no free space now...            //allocate twice memory             grow();         }      }      begin = full_bit + 1;   }}template <class T>bool DynBinSearcher<T>::erase(const T &x){   Pair pos(0, 0);   pos = search(x);   int i = pos.i, j = pos.j;   if (i == -1){      //x not found      return false;   }   if (--begin == full_bit){      if (extra_bit == 0){         full_bit--;         extra_bit = full() - 1;      }      else{         extra_bit--;      }      begin = num - 1;   }   int filler = arrays[begin][size(begin)];   while (0 < j && filler <= arrays[i][j - 1]){      arrays[i][j] = arrays[i][j - 1];      --j;   }   while (j < size(i) - 1 && filler > arrays[i][j + 1]){      arrays[i][j] = arrays[i][j + 1];      ++j;   }   arrays[i][j] = filler;   return true;}template <class T>void DynBinSearcher<T>::grow(){   //calculate new size   int ol_size = num;   int k = 1;   while ((ol_size >>= 1) || 0) ++k;   int more = (1 << k) - k - 1;   k = num - k;   //allocation   T **new_array = new T *[num + more];   for (int s = 0; s < num + more; s++){      new_array[s] = new T[1 << s];   }   //initialization   int j = 0;   for (; j <= k; j++){      for (int p = 0; p < size(j); p++){         new_array[j][p] = arrays[j][p];      }   }   for (; j < num; j++){      for (int p = 0; p < (1 << k); p++){         new_array[j][p] = arrays[j][p];      }   }   int i = k + 1;   for (; i < num; i++){      int r = 1 << k;      for (int n = 0; n < (1 << (i - k)) - 1; n++, j++){         for (int m = 0; m < (1 << k); m++, r++){            new_array[j][m] = arrays[i][r];         }      }   }   //reset arrays   destroyArrays();   arrays = new_array;   //update parameters   num += more;   begin = k + 1;   extra_bit = 0;   full_bit = k;}#ifdef TESTtemplate <class T>void DynBinSearcher<T>::output(){   for (int i = 0; i < num; i++){      for (int j = 0; j < size(i); j++){         cout << setw(4) << arrays[i][j];         if ((1 + j) % 16 == 0){            cout << endl;         }      }      cout << "\n--------------------------------" << i          << "--------------------------------\n";   }   cout << endl;}#endif#endif
//DynBinSearcher_test.cpp#include <iostream>#include <iomanip>#include <ctime>using namespace std;#define TEST 1#define DATA_SIZE 400#include "DynBinSearcher.h"#include "ArrayQueue.h"int main(){   srand(time(0));   DynBinSearcher<int> dbs(10);   ArrayQueue<int> recorder(DATA_SIZE);   //insertion test   for (int i = 0; i < DATA_SIZE; i++){      if (i == 50){         dbs.insert(19);         recorder.enqueue(19);         continue;      }      int x = rand() % 100 + 1;      recorder.enqueue(x);      dbs.insert(x);     /* cout << "insert(" << x << ")" << endl;      dbs.output();*/   }   dbs.output();   //search test   Pair p_19 = dbs.search(19);   cout << "search 19: "       << "(" << p_19.i << "," << p_19.j << ")" << endl;   //deletion test   for (int i = 0; i < DATA_SIZE; i++){      int x = recorder.front();      if (!dbs.erase(x))          cout << "ERROR: " << x << "NOT FOUND\n";      recorder.dequeue();   }   cout << "clear." << endl;   dbs.output();   return 0;}
0 0
原创粉丝点击