Systemnahe Programmierung in C: Hashtabellen |
|
1#ifndef ELEMENT_H__
2#define ELEMENT_H__ 1
3
4typedef char *Element;
5
6extern int compare(Element e1,
7 Element e2);
8
9extern unsigned int hash(Element e);
10
11#endif
|
1#include "Element.h"
2
3#include <string.h>
4
5int
6compare(Element e1, Element e2)
7{
8 int cmp = strcmp(e1, e2);
9
10 return (cmp >= 0) - (0 >= cmp);
11}
12
13/* hash function as used in Java for Strings */
14
15unsigned int
16hash(Element e)
17{
18 unsigned int res = 0;
19
20 while (*e != 0)
21 {
22 res = 31 * res + *e;
23 ++e;
24 }
25 return res;
26}
|
1#ifndef HASHTABLE0_H__
2#define HASHTABLE0_H__
3
4/*--------------------*/
5
6#include "Element.h"
7
8typedef struct Entry *Set;
9
10struct Entry
11{
12 int used;
13 Element info;
14};
15
16/*--------------------*/
17
18extern Set mkEmptySet(void);
19
20extern int isInSet(Element e, Set s);
21
22extern Set insertElem(Element e, Set s);
23
24/* not implemented:
25 extern Set removeElem(Element e, Set s);
26*/
27
28extern int invSetAsHashtable(Set s);
29
30/*--------------------*/
31
32#endif
|
1#include "Hashtable0.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5
6#define eqElement(e1,e2) (compare((e1),(e2)) == 0)
7
8/* constant hashtable size */
9/* not very flexible */
10
11#define size 1024
12
13/* counting modulo size */
14/* call these macros only with simple variables */
15
16#define incr(i) i = (i == size - 1) ? 0 : i + 1
17#define decr(i) i = ((i == 0) ? size : i) - 1
18
19/*--------------------*/
20
21
22Set
23mkEmpty(void)
24{
25 Set res = malloc(size * sizeof(*res));
26
27 if (!res)
28 {
29 perror
30 ("mkEmptySet: malloc failed");
31 exit(1);
32 }
33 {
34 unsigned int i;
35
36 for (i = 0; i < size; ++i)
37 res[i].used = 0;
38 }
39 return res;
40}
41
42/*--------------------*/
43
44int
45isInSet(Element e, Set s)
46{
47 unsigned int i = hash(e) % size;
48
49 while (s[i].used
50 && !eqElement(s[i].info, e))
51 {
52 incr(i);
53 }
54
55 return s[i].used;
56}
57
58/*--------------------*/
59
60Set
61insertElem(Element e, Set s)
62{
63 unsigned int i = hash(e) % size;
64
65 while (s[i].used
66 && !eqElement(s[i].info, e))
67 {
68 incr(i);
69 }
70
71 if (!s[i].used)
72 {
73 s[i].used = 1;
74 s[i].info = e;
75 }
76
77 return s;
78}
79
80/*--------------------*/
81
82int
83invSetAsHashtable(Set s)
84{
85 unsigned int i;
86
87 for (i = 0; i < size; ++i)
88 {
89 if (s[i].used)
90 {
91 unsigned int ix =
92 hash(s[i].info) % size;
93
94 /* all entries in hashtable
95 in the intervall [ix..i]
96 must be filled, otherwise the hash does not
97 fit to the position
98 */
99
100 unsigned int j = i;
101
102 while (j != ix)
103 {
104 decr(j);
105
106 if (!s[j].used)
107 return 0;
108 }
109 }
110 }
111
112 return 1;
113}
|
1#ifndef HASHTABLE_H__
2#define HASHTABLE_H__
3
4/*--------------------*/
5
6#include "Element.h"
7
8typedef struct Node *List;
9
10struct Node
11{
12 Element info;
13 List next;
14};
15
16
17typedef struct hashtable *Set;
18
19struct hashtable
20{
21 unsigned int size;
22 unsigned int card;
23 List *table;
24};
25
26/*--------------------*/
27
28extern Set mkEmptySet(void);
29extern int isEmptySet(Set s);
30
31extern int isInSet(Element e, Set s);
32
33extern Set insertElem(Element e, Set s);
34extern Set removeElem(Element e, Set s);
35
36extern unsigned int card(Set s);
37
38extern int invSetAsHashtable(Set s);
39
40/*--------------------*/
41
42#endif
|
1#include "Hashtable.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5
6/*--------------------*/
7
8/* auxiliary list functions */
9
10#define eqElement(e1,e2) (compare((e1),(e2)) == 0)
11
12#define mkEmptyList() ((List)0)
13#define isEmptyList(l) ((l) == (List)0)
14
15static int
16isInList(Element e, List l)
17{
18 while (!isEmptyList(l))
19 {
20 if (eqElement(e, l->info))
21 return 1;
22 l = l->next;
23 }
24 return 0;
25}
26
27/*--------------------*/
28
29static List
30cons(Element e, List l)
31{
32 /* the only call of malloc for List values */
33 List res = malloc(sizeof(*l));
34
35 if (!res)
36 {
37 perror("cons: malloc failed");
38 exit(1);
39 }
40 res->info = e;
41 res->next = l;
42
43 return res;
44}
45
46/*--------------------*/
47
48static List
49removeElem1(Element e, List l)
50{
51 if (isEmptyList(l))
52 return l;
53
54 if (eqElement(e, l->info))
55 {
56 List l1 = l->next;
57
58 free(l);
59 return l1;
60 }
61
62 l->next = removeElem1(e, l->next);
63 return l;
64}
65
66
67/*--------------------*/
68
69/* hash table creation */
70
71/* size for new empty hashtable */
72#define initialSize 16
73
74Set
75mkEmpty(void)
76{
77 Set res = malloc(sizeof(*res));
78 List *table =
79 malloc(initialSize *
80 sizeof(*table));
81
82 if (!res || !table)
83 {
84 perror
85 ("mkEmptySet: malloc failed");
86 exit(1);
87 }
88
89 res->size = initialSize;
90 res->card = 0;
91 res->table = table;
92
93 {
94 unsigned int i;
95
96 for (i = 0; i < res->size; ++i)
97 table[i] = mkEmptyList();
98 }
99
100 return res;
101}
102
103/*--------------------*/
104
105Set
106resizeHashtable(Set s,
107 unsigned int newsize)
108{
109 unsigned int size = s->size;
110
111 List *newtable =
112 malloc(newsize * sizeof(*newtable));
113
114 List *oldtable = s->table;
115
116 unsigned int i;
117
118 /* initialize new table */
119 for (i = 0; i < newsize; ++i)
120 newtable[i] = mkEmptyList();
121
122 /* move entries from old table into new table */
123 for (i = 0; i < size; ++i)
124 {
125 List l = oldtable[i];
126
127 while (!isEmptyList(l))
128 {
129 List l1 = l;
130 unsigned int i2 =
131 hash(l->info) % newsize;
132
133 l = l->next;
134 l1->next = newtable[i2];
135 newtable[i2] = l1;
136 }
137 }
138
139 free(oldtable);
140
141 s->size = newsize;
142 s->table = newtable;
143
144 return s;
145}
146
147/*--------------------*/
148
149/* if card > 1.0 * size, the table size is doubled */
150/* this factor and the expansion factor can be tuned */
151
152Set
153checkTableOverflow(Set s)
154{
155 /* don't use floating point arithmetic for this check */
156 if (s->card > s->size)
157 return resizeHashtable(s,
158 2 * s->size);
159
160 return s;
161}
162
163/*--------------------*/
164
165/* if card < 0.25 * size, the table size is divided by 2 */
166/* this factor and the shrinking factor can be tuned */
167
168Set
169checkTableUnderflow(Set s)
170{
171 if (s->size > initialSize
172 && 4 * s->card < s->size)
173 return
174 resizeHashtable(s, s->size / 2);
175
176 return s;
177}
178
179/*--------------------*/
180
181int
182isInSet(Element e, Set s)
183{
184 unsigned int i = hash(e) % s->size;
185
186 return isInList(e, s->table[i]);
187}
188
189/*--------------------*/
190
191Set
192insertElem(Element e, Set s)
193{
194 unsigned int i = hash(e) % s->size;
195 List l = s->table[i];
196
197 if (!isInList(e, l))
198 {
199 s->table[i] = cons(e, l);
200 ++(s->card);
201 s = checkTableOverflow(s);
202 }
203
204 return s;
205}
206
207Set
208removeElem(Element e, Set s)
209{
210 unsigned int i = hash(e) % s->size;
211 List l = s->table[i];
212
213 if (isInList(e, l))
214 {
215 s->table[i] = removeElem1(e, l);
216 --(s->card);
217 s = checkTableUnderflow(s);
218 }
219
220 return s;
221}
222
223/*--------------------*/
224
225static int
226checkHashes(Set s)
227{
228 unsigned int i;
229
230 for (i = 0; i < s->size; ++i)
231 {
232 List l = s->table[i];
233
234 while (!isEmptyList(l))
235 {
236 if (hash(l->info) % s->size !=
237 i)
238 return 0;
239 l = l->next;
240 }
241 }
242 return 1;
243}
244
245static int
246checkCard(Set s)
247{
248 unsigned int i;
249 unsigned int res = 0;
250
251 for (i = 0; i < s->size; ++i)
252 {
253 List l = s->table[i];
254
255 while (!isEmptyList(l))
256 {
257 ++res;
258 l = l->next;
259 }
260 }
261 return res == s->card;
262}
263
264static int
265checkTableLevel(s)
266{
267 /* check whether size and
268 card fit the space constraints */
269 return 1;
270}
271
272int
273invSetAsHashtable(Set s)
274{
275 return
276 checkHashes(s)
277 &&
278 checkCard(s)
279 &&
280 checkTableLevel(s);
281}
|
Letzte Änderung: 11.01.2007 | © Prof. Dr. Uwe Schmidt |