261 lines
12 KiB
C
261 lines
12 KiB
C
/*
|
|
This File is copied from
|
|
|
|
http://www.oreilly.com/catalog/masteralgoc/index.html
|
|
Mastering Algorithms with C
|
|
By Kyle Loudon
|
|
ISBN: 1-56592-453-3
|
|
Publishd by O'Reilly
|
|
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ------------------------------- chtbl.c -------------------------------- *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <include/list.h>
|
|
#include <include/chtbl.h>
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ------------------------------ chtbl_init ------------------------------ *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int
|
|
(*match)(const void *key1, const void *key2), void (*destroy)(void*data)) {
|
|
|
|
int i;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Allocate space for the hash table. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL)
|
|
return -1;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Initialize the buckets. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
htbl->buckets = buckets;
|
|
|
|
for (i = 0; i < htbl->buckets; i++)
|
|
list_init(&htbl->table[i], destroy);
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Encapsulate the functions. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
htbl->h = h;
|
|
htbl->match = match;
|
|
htbl->destroy = destroy;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Initialize the number of elements in the table. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
htbl->size = 0;
|
|
|
|
return 0;
|
|
} /* end chtbl_init () */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ---------------------------- chtbl_destroy ----------------------------- *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
void chtbl_destroy(CHTbl *htbl) {
|
|
|
|
int i;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Destroy each bucket. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
for (i = 0; i < htbl->buckets; i++) {
|
|
list_destroy(&htbl->table[i]);
|
|
} /* end for () */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Free the storage allocated for the hash table. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
free(htbl->table);
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* No operations are allowed now, but clear the structure as a precaution. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
memset(htbl, 0, sizeof(CHTbl));
|
|
|
|
return;
|
|
} /* end chtbl_destroy() */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ----------------------------- chtbl_insert ----------------------------- *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
int chtbl_insert(CHTbl *htbl, const void *data) {
|
|
|
|
void *temp;
|
|
int bucket,retval;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Do nothing if the data is already in the table. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
temp = (void *)data;
|
|
|
|
if (chtbl_lookup(htbl, &temp) == 0)
|
|
return 1;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Hash the key. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
bucket = htbl->h(data) % htbl->buckets;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Insert the data into the bucket. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0)
|
|
htbl->size++;
|
|
|
|
return retval;
|
|
} /* end chtbl_insert() */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ----------------------------- chtbl_remove ----------------------------- *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
int chtbl_remove(CHTbl *htbl, void **data) {
|
|
|
|
ListElmt *element, *prev;
|
|
int bucket;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Hash the key. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
bucket = htbl->h(*data) % htbl->buckets;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Search for the data in the bucket. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
prev = NULL;
|
|
|
|
for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) {
|
|
if (htbl->match(*data, list_data(element))) {
|
|
|
|
/***********************************************************************
|
|
* *
|
|
* Remove the data from the bucket. *
|
|
* *
|
|
***********************************************************************/
|
|
|
|
if (list_rem_next(&htbl->table[bucket], prev, data) == 0) {
|
|
htbl->size--;
|
|
return 0;
|
|
} /* end if() */
|
|
else {
|
|
return -1;
|
|
}/* end else */
|
|
}/* end if (htbl->match(*data, list_data(element))) */
|
|
|
|
prev = element;
|
|
}/* end for() */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Return that the data was not found. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
return -1;
|
|
} /* end int chtbl_remove(CHTbl *htbl, void **data) */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ----------------------------- chtbl_lookup ----------------------------- *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
int chtbl_lookup(const CHTbl *htbl, void **data) {
|
|
|
|
ListElmt *element;
|
|
int bucket;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Hash the key. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
bucket = htbl->h(*data) % htbl->buckets;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Search for the data in the bucket. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) {
|
|
if (htbl->match(*data, list_data(element))) {
|
|
|
|
/***********************************************************************
|
|
* *
|
|
* Pass back the data from the table. *
|
|
* *
|
|
***********************************************************************/
|
|
|
|
*data = list_data(element);
|
|
return 0;
|
|
}/* end if() */
|
|
}/* end for() */
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Return that the data was not found. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
return -1;
|
|
} /* end chtbl_lookup() */
|