00001 #ifndef __HASHTABLE_H
00002 #define __HASHTABLE_H
00003
00004 #include <vector>
00005 #include <iostream>
00006
00007 const size_t primes[30] = {2,5,11,23,47,97,197,397,797,1597,3203,6421,12853,25717,51437,102877,205759,411527,823117,1646237,3292489,6584983,13169977,26339969,52679969,105359939,210719881,421439783,842879579,1685759167};
00008 const int numPrimes = 30;
00009
00010 template <class data, class key, size_t (*hashFunc)(key* K), bool (*equals)(key* k1, key* k2)>
00011 class Hashtable{
00012 private:
00013 int primeIndex;
00014 size_t sizeOfTable;
00015 std::vector<bool>* isUsed;
00016 std::vector<key*>* keys;
00017 std::vector<data*>* datas;
00018 size_t numElems;
00019 size_t numUsedBins;
00020
00021 size_t find(key* k){
00022 size_t hashVal = (hashFunc(k) % sizeOfTable);
00023
00024 size_t pos = hashVal;
00025 int i = 1;
00026 while (1){
00027
00028
00029
00030
00031
00032
00033
00034
00035 if (!((*isUsed)[pos])){
00036 return pos;
00037 }else if ((*keys)[pos] != NULL && equals((*keys)[pos], k)){
00038 return pos;
00039 }
00040 pos = (hashVal + (i*i)) % sizeOfTable;
00041
00042 i++;
00043 }
00044
00045 return pos;
00046 }
00047
00048 void resizeTable(){
00049 using namespace std;
00050
00051 cout << "RESIZING!\n";
00052
00053 vector<bool>* oldIsUsed = isUsed;
00054 vector<key*>* oldKeys = keys;
00055 vector<data*>* oldDatas = datas;
00056 size_t oldSizeOfTable = sizeOfTable;
00057
00058 numElems = 0;
00059 numUsedBins = 0;
00060
00061
00062
00063 primeIndex++;
00064 sizeOfTable = primes[primeIndex];
00065
00066 isUsed = new vector<bool>(sizeOfTable, false);
00067 keys = new vector<key*>(sizeOfTable, NULL);
00068 datas = new vector<data*>(sizeOfTable, NULL);
00069
00070 for (size_t i = 0; i < oldSizeOfTable; i++){
00071 if ((*oldIsUsed)[i] && ((*oldKeys)[i] != NULL)){
00072 size_t index = find((*oldKeys)[i]);
00073 (*isUsed)[index] = true;
00074 numElems++;
00075 numUsedBins++;
00076 (*keys)[index] = (*oldKeys)[i];
00077 (*datas)[index] = (*oldDatas)[i];
00078 }
00079 }
00080
00081 delete oldKeys;
00082 delete oldIsUsed;
00083 delete oldDatas;
00084 }
00085
00086 public:
00087 Hashtable() :
00088 primeIndex(10), sizeOfTable(primes[primeIndex]),
00089 isUsed(new std::vector<bool>(sizeOfTable, false)),
00090 keys(new std::vector<key*>(sizeOfTable, NULL)),
00091 datas(new std::vector<data*>(sizeOfTable, NULL)),
00092 numElems(0), numUsedBins(0) {}
00093
00094 ~Hashtable(){
00095 delete keys;
00096 delete isUsed;
00097 delete datas;
00098 }
00099
00100 data* retrieve(key* k){
00101 size_t index = find(k);
00102 if (!(*isUsed)[index])
00103 return NULL;
00104 return (*datas)[index];
00105 }
00106
00107 void retrieveAllData(std::vector<data*>* returnVec){
00108 returnVec->clear();
00109
00110 for (size_t i = 0; i < sizeOfTable; i++){
00111 if ((*isUsed)[i] && (*keys)[i] != NULL){
00112 returnVec->push_back((*datas)[i]);
00113 }
00114 }
00115 }
00116
00117 void retrieveAllKeys(std::vector<key*>* returnVec){
00118 returnVec->clear();
00119
00120 for (size_t i = 0; i < sizeOfTable; i++){
00121 if ((*isUsed)[i] && (*keys)[i] != NULL){
00122 returnVec->push_back((*keys)[i]);
00123 }
00124 }
00125 }
00126
00127 bool insert(data* d, key* k){
00128 size_t index = find(k);
00129
00130 if ((*isUsed)[index]) return false;
00131
00132
00133 if (numUsedBins+1 >= sizeOfTable / 2){
00134 resizeTable();
00135 index = find(k);
00136 }
00137
00138 numElems++;
00139 numUsedBins++;
00140 (*isUsed)[index] = true;
00141 (*keys)[index] = k;
00142 (*datas)[index] = d;
00143
00144 return true;
00145 }
00146
00147 data* deleteData(key* k, key** retrievedKey){
00148 size_t index = find(k);
00149
00150 if (!(*isUsed)[index]) return NULL;
00151
00152 *retrievedKey = (*keys)[index];
00153 data* returnVal = (*datas)[index];
00154
00155 (*keys)[index] = NULL;
00156 (*datas)[index] = NULL;
00157
00158 numElems--;
00159
00160 return returnVal;
00161 }
00162
00163 size_t numElements(){
00164 return numElems;
00165 }
00166
00167 size_t usedCapacity(){
00168 return numUsedBins;
00169 }
00170
00171 size_t capacity(){
00172 return sizeOfTable;
00173 }
00174
00175 private:
00176 Hashtable(const Hashtable&);
00177 Hashtable& operator=(const Hashtable&);
00178
00179 };
00180
00181 #endif