The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
ohashtbl.c
Go to the documentation of this file.
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: ohashtbl.c
8  * Author : Kyle Loudon/Dan Levin
9  * Date : Mon Apr 08 12:15:39 2013
10  * Version : 0.51
11  * ---
12  * Description: An open-addressed hashtable implemented as a pure, generic ADT - written in ANSI C
13  *
14  * Date Revision message
15  * 150331 This code ready for version 0.51
16  *
17  */
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 #include "ohashtbl.h"
26 
27 struct OHtbl_
28 {
29  int positions;
30  void *vacated;
31 
32  int (*h1)(const void *key);
33  int (*h2)(const void *key);
34  int (*match)(const void *key1, const void *key2);
35  void (*destroy)(void *data);
36 
37  int size;
38  void **table;
39 };
40 
41 /* Reserve a sentinel memory address for vacated elements */
42 static char vacated;
43 
44 /* FUNCTION DEFINITIONS */
45 
46 OHtbl OHTBLinit(int positions, int (*h1)(const void *key), int (*h2)(const void *key),
47  int (*match)(const void *key1, const void *key2), void (*destroy)(void *data))
48 {
49  OHtbl htbl;
50  int i;
51 
52  /* Allocate space for the open-addressed hash table header */
53  if ((htbl = malloc(sizeof(struct OHtbl_))) == NULL)
54  return NULL;
55 
56  /* Allocate space for the hash table */
57  if ((htbl->table = (void **)malloc(positions * sizeof(void *))) == NULL)
58  return NULL;
59 
60  /* Initialize each position */
61  htbl->positions = positions;
62 
63  for (i = 0; i < htbl->positions; i++)
64  htbl->table[i] = NULL;
65 
66  /* Set the vacated member to the sentinel memory address reserved for this */
67  htbl->vacated = &vacated;
68 
69  /* Encapsulate the functions */
70  htbl->h1 = h1;
71  htbl->h2 = h2;
72  htbl->match = match;
73  htbl->destroy = destroy;
74 
75  /* Initialize the number of elements in the table */
76  htbl->size = 0;
77 
78  return htbl;
79 }
80 
81 void OHTBLdestroy(OHtbl htbl)
82 {
83  int i;
84 
85  if (htbl->destroy != NULL)
86  {
87  /* Call a user-defined function to free dynamically allocated data */
88  for (i = 0; i < htbl->positions; i++)
89  {
90  if (htbl->table[i] != NULL && htbl->table[i] != htbl->vacated)
91  htbl->destroy(htbl->table[i]);
92  }
93  }
94 
95  /* Free the storage allocated for the hash table */
96  free(htbl->table);
97 
98  /* Free the storage allocated for the table header */
99  free(htbl);
100 }
101 
102 int OHTBLinsert(OHtbl htbl, const void *data)
103 {
104  void *temp;
105  int position, i;
106 
107  /* Do not exceed the number of positions in the table */
108  if (htbl->size == htbl->positions)
109  return -1;
110 
111  /* Do nothing if the data is already in the table */
112  temp = (void *)data;
113 
114  if (OHTBLlookup(htbl, &temp) == 0) /* Duplicate found! */
115  return 1;
116 
117  /* Use double hashing to hash the key */
118  for (i = 0; i < htbl->positions; i++)
119  {
120  position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->positions;
121 
122  if (htbl->table[position] == NULL || htbl->table[position] == htbl->vacated)
123  {
124  /* Insert the data into the table */
125  htbl->table[position] = (void *)data;
126  htbl->size++;
127  return 0;
128  }
129  }
130 
131  /* Return that the hash functions were selected incorrectly */
132  return -1;
133 }
134 
135 int OHTBLremove(OHtbl htbl, void **data)
136 {
137  int position, i;
138 
139  /* Use double hashing to hash the key */
140  for (i = 0; i < htbl->positions; i++)
141  {
142  position = (htbl->h1(*data) + (i * htbl->h2(*data))) % htbl->positions;
143 
144  if (htbl->table[position] == NULL)
145  {
146  /* Return that the data was not found */
147  return -1;
148  }
149  else if (htbl->table[position] == htbl->vacated)
150  {
151  /* Search beyond vacated positions */
152  continue;
153  }
154  else if (htbl->match(htbl->table[position], *data))
155  {
156  /* Pass back the data from the table */
157  *data = htbl->table[position];
158  htbl->table[position] = htbl->vacated;
159  htbl->size--;
160  return 0;
161  }
162  }
163 
164  /* Return that the data was not found */
165  return -1;
166 }
167 
168 int OHTBLlookup(const OHtbl htbl, void **data)
169 {
170  int position, i;
171 
172  /* Use double hashing to hash the key */
173  for (i = 0; i < htbl->positions; i++)
174  {
175  position = (htbl->h1(*data) + (i * htbl->h2(*data))) % htbl->positions;
176 
177  if (htbl->table[position] == NULL)
178  {
179  /* Return that the data was not found */
180  return -1;
181  }
182  else if (htbl->match(htbl->table[position], *data))
183  {
184  /* Pass back the data from the table */
185  *data = htbl->table[position];
186  return 0;
187  }
188  }
189 
190  /* Return that the data was not found... */
191  return -1;
192 }
193 
194 int OHTBLsize(OHtbl htbl)
195 {
196  return htbl->size;
197 }
198 
199 void OHTBLprint(OHtbl htbl, void (*callback)(const void *data))
200 {
201  int i;
202 
203  for (i=0; i<htbl->positions; i++)
204  {
205  if (htbl->table[i] == NULL)
206  printf("\nNULL");
207  else if (htbl->table[i] == htbl->vacated)
208  printf("\nVACATED");
209  else
210  callback(htbl->table[i]);
211  }
212 }