source: Sophya/trunk/Poubelle/DPC:FitsIOServer/SysTools/hashtable.h

Last change on this file was 658, checked in by ansari, 26 years ago

no message

File size: 4.4 KB
Line 
1// This may look like C code, but it is really -*- C++ -*-
2
3// This is a hash table. Some implementations of the STL have one, like the
4// Modena Standard Library.
5
6#ifndef HASHTABLE_H_SEEN
7#define HASHTABLE_H_SEEN
8
9#include "machdefs.h"
10#include "pexceptions.h"
11
12namespace SOPHYA {
13
14template <class T, class K>
15struct HashtableEntry {
16 uint_4 hash;
17 K key;
18 T value;
19 HashtableEntry<T,K> *next;
20};
21
22
23template <class T, class K>
24class Hashtable {
25public:
26 typedef uint_4 (*HashFunction)(K const& key);
27
28 Hashtable(uint_4 initialCapacity, float loadFactor) {
29 Init(initialCapacity,loadFactor);
30 }
31
32 Hashtable(int initialCapacity) {
33 Init(initialCapacity, 0.75);
34 }
35
36 Hashtable() {
37 Init(101, 0.75);
38 }
39
40 ~Hashtable() {
41 for (int i = count ; i-- > 0 ;) {
42 for (HashtableEntry<T,K>* e = table[i] ; e != NULL ; ) {
43 HashtableEntry<T,K>* ee = e->next;
44 delete e;
45 e = ee;
46 }
47 }
48 delete[] table;
49 }
50
51 void setHash(HashFunction f) {
52 hf = f;
53 }
54
55 uint_4 size() {
56 return count;
57 }
58
59 bool contains(T const& value) {
60 for (int i = count ; i-- > 0 ;) {
61 for (HashtableEntry<T,K>* e = table[i] ; e != NULL ; e = e->next) {
62 if (e->value == value) {
63 return true;
64 }
65 }
66 }
67 return false;
68 }
69
70 bool containsKey(K const& key) {
71 uint_4 hash = hf(key);
72 uint_4 index = (hash & 0x7FFFFFFF) % length;
73 for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
74 if ((e->hash == hash) && e->key == key) {
75 return true;
76 }
77 }
78 return false;
79 }
80
81 T const& get(K const& key) {
82 uint_4 hash = hf(key);
83 uint_4 index = (hash & 0x7FFFFFFF) % length;
84 for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
85 if ((e->hash == hash) && e->key == key) {
86 return e->value;
87 }
88 }
89 throw(NotFoundExc("Hashtable::get"));
90 }
91
92
93 void put(K const& key, T const& value) {
94 // Makes sure the key is not already in the hashtable.
95 uint_4 hash = hf(key);
96 uint_4 index = (hash & 0x7FFFFFFF) % length;
97 for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
98 if ((e->hash == hash) && e-> key == key) {
99 //T const& old = e.value;
100 e->value = value;
101 //return old;
102 }
103 }
104
105 if (count >= threshold) {
106 // Rehash the table if the threshold is exceeded
107 rehash();
108 return;// put(key, value);
109 }
110
111 // Creates the new entry.
112 HashtableEntry<T,K>* e = new HashtableEntry<T,K>;
113 e->hash = hash;
114 e->key = key;
115 e->value = value;
116 e->next = table[index];
117 table[index] = e;
118 count++;
119 //return null;
120 }
121
122
123 void remove(K const& key) {
124 uint_4 hash = hf(key);
125 uint_4 index = (hash & 0x7FFFFFFF) % tab.length;
126 for (HashtableEntry<T,K>* e = table[index], prev = null ; e != null ; prev = e, e = e->next) {
127 if ((e>hash == hash) && e>key == key) {
128 if (prev != NULL) {
129 prev->next = e->next;
130 } else {
131 table[index] = e->next;
132 }
133 count--;
134 //return e.value;
135 }
136 }
137 //return null;
138 }
139
140private:
141
142 void Init(uint_4 initialCapacity, float loadFactor) {
143 if ((initialCapacity == 0) || (loadFactor <= 0.0)) {
144 throw ParmError("Hashtable::Hashtable");
145 }
146 this->loadFactor = loadFactor;
147 this->length = initialCapacity;
148 this->count = 0;
149 table = new (HashtableEntry<T,K>*[initialCapacity]);
150 for (int i=0; i<length; i++) table[i] = NULL;
151 threshold = (uint_4)(initialCapacity * loadFactor);
152 hf = defaultHash;
153 }
154
155 static uint_4 defaultHash(K const& key) {
156 if (sizeof(K) <= sizeof(void*))
157 return (uint_4)(uint_8)(key);
158 else
159 return (uint_4)(uint_8)(&key);
160 }
161
162 void rehash() {
163 uint_4 oldCapacity = length;
164 HashtableEntry<T,K>** oldTable = table;
165
166 uint_4 newCapacity = oldCapacity * 2 + 1;
167 HashtableEntry<T,K>** newTable = new (HashtableEntry<T,K>*[newCapacity]);
168
169 threshold = (int)(newCapacity * loadFactor);
170 table = newTable;
171 length = newCapacity;
172
173 for (int i = oldCapacity ; i-- > 0 ;) {
174 for (HashtableEntry<T,K>* old = oldTable[i] ; old != NULL ; ) {
175 HashtableEntry<T,K>* e = old;
176 old = old->next;
177
178 int index = (e->hash & 0x7FFFFFFF) % newCapacity;
179 e->next = newTable[index];
180 newTable[index] = e;
181 }
182 }
183 delete[] oldTable;
184 }
185
186 HashtableEntry<T,K> **table;
187 uint_4 length;
188 uint_4 count;
189 uint_4 threshold;
190 float loadFactor;
191 HashFunction hf;
192};
193}
194
195#endif
Note: See TracBrowser for help on using the repository browser.