Caveat: Your implementation needs almost a complete restructuring.
A few issues ...
- The hash table contains:
node_t *table;
OR node_t table[SIZE];
It should be: node_t *table[SIZE];
(or a malloc
variant below: node_t **table
).
- The print function stops if a hash table entry is
NULL
.
- The print function does not follow the linked list for a given hash entry.
- What you're calling
sentinel
is a pointer to the table entry/head, so not really a sentinel (special value) as generally used. In the code below, I've renamed this to head
.
- You're using an explicit integer value for the
key
. But, for hashes of strings, this is generally derived from the string itself.
SIZE
is so large that without a lot more test data, the hash table algorithm isn't fully tested. That is, you'll only have one element per hash bucket.
- In
insert
, the original element
pointer is stored in the node_t
struct. In the general case, we should use strdup
(e.g.) The string might be read from a file.
find
might be more useful if it returned node_t
instead of char *
(i.e. the element
value).
- The use of the double pointers in
delete
and find
can be simplified.
Here is the restructured code. It is annotated:
// HASHTABLE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#ifndef SIZE
#ifdef BIGSIZE
#define SIZE 512
#else
#define SIZE 8
#endif
#endif
typedef struct nodez {
struct nodez *next;
const char *element;
int key;
} node_t;
typedef struct hash_table {
#if DYNAMIC_TABLE
node_t **table; // dynamic table size
#else
node_t *table[SIZE]; // fixed table size
#endif
} hashtable;
#ifndef STRDUP
#define STRDUP 1 // use strdup when storing entry
#endif
#define ARRAY_COUNT(_arr) \
(sizeof(_arr) / sizeof(_arr[0]))
hashtable *
create_table(void)
{
hashtable *ht = calloc(1,sizeof(hashtable));
#if DYNAMIC_TABLE
ht->table = calloc(SIZE,sizeof(node_t *));
#endif
return ht;
}
// strhash -- get hash key from string
int
strhash(const char *str)
{
int hash = 0;
for (; *str != 0; ++str)
hash += (unsigned) *str;
return hash;
}
// hash -- get hash index from hash key
int
hash(int key)
{
// make the value acceptable
key %= SIZE;
return key;
}
node_t *
find(hashtable *ht,const char *element,int key)
{
assert(element != NULL);
if (key <= 0)
key = strhash(element);
int hidx = hash(key);
node_t **head = &ht->table[hidx];
node_t *cur = *head;
for (; cur != NULL; cur = cur->next) {
if (key == cur->key) {
if (strcmp(element,cur->element) == 0)
break;
}
}
return cur;
}
// insert -- head insertion
node_t *
insert(hashtable *ht, const char *element)
{
assert(element != NULL);
int key = strhash(element);
// point to table bucket
int hidx = hash(key);
node_t **head = &ht->table[hidx];
// look for existing/duplicate element
node_t *cur = *head;
for (; cur != NULL; cur = cur->next) {
if (key == cur->key) {
if (strcmp(element,cur->element) == 0)
break;
}
}
if (cur != NULL) {
printf("insert: duplicate node -- '%s'\n",element);
exit(1);
}
node_t *new_node = malloc(sizeof(node_t));
if (new_node == NULL) {
printf("Failed to allocate %s.\n", element);
exit(1);
}
new_node->key = key;
#if STRDUP
element = strdup(element);
#endif
new_node->element = element;
// add to head of linked list for this hash bucket
new_node->next = *head;
*head = new_node;
return new_node;
}
bool
delete(hashtable *ht, const char *element)
{
// compute hash value from string
int key = strhash(element);
int hidx = hash(key);
node_t **head = &ht->table[hidx];
// look for a match
node_t *prev = NULL;
node_t *cur = *head;
for (; cur != NULL; cur = cur->next) {
if (key == cur->key) {
if (strcmp(element,cur->element) == 0)
break;
}
prev = cur;
}
// node not found
if (cur == NULL) {
printf("delete: node not found -- '%s'\n",element);
return false;
}
// remove the node from the linked list
if (prev != NULL)
prev->next = cur->next;
else
*head = cur->next;
// release the string
#if STRDUP
free((void *) cur->element);
#endif
// release the node
free(cur);
return true;
}
// displays the hashtable
void
display_hashtable(hashtable *ht,const char *why)
{
printf("\n");
printf("TABLE: %s\n",why);
for (int i = 0; i < SIZE; i++) {
node_t *cur = ht->table[i];
for (; cur != NULL; cur = cur->next)
printf("Element: %s || Slot: %d || Key: %d.\n",
cur->element, i, cur->key);
}
}
int
main(void)
{
hashtable *ht = create_table();
const char *names[] = {
"Francesco",
"Daniela",
"Pietro",
"Priscilla",
"Amber",
"Roger",
"Nelly",
"Marco",
"Susan",
"Mary",
"Ellen",
"Fred",
"Frank",
"Dick",
"Jane",
"Nancy",
"Elvira",
"Dracula",
"Frankenstein",
"Pierre",
"Alberto"
};
// insert all test names into table
for (int nidx = 0; nidx < ARRAY_COUNT(names); ++nidx)
insert(ht,names[nidx]);
display_hashtable(ht,"All Names");
// ensure we can find all the names
printf("\n");
printf("Checking table ...\n");
int err = 0;
for (int nidx = 0; nidx < ARRAY_COUNT(names); ++nidx) {
const char *name = names[nidx];
if (find(ht,name,0) == NULL) {
printf("ERROR: name '%s' not found\n",name);
err = 1;
}
}
if (err)
exit(1);
printf("All names found\n");
// delete all nodes in a random order
int delcount = 0;
while (delcount < ARRAY_COUNT(names)) {
// get a random name to delete
int delidx = rand() % ARRAY_COUNT(names);
const char *name = names[delidx];
// see if we have already deleted it
if (name == NULL)
continue;
delete(ht,name);
char why[100];
sprintf(why,"After deleting %s",name);
display_hashtable(ht,why);
// mark it as deleted
names[delidx] = NULL;
++delcount;
}
return 0;
}
Here is the program output:
TABLE: All Names
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Mary || Slot: 1 || Key: 409.
Element: Frank || Slot: 2 || Key: 498.
Element: Susan || Slot: 2 || Key: 522.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Daniela || Slot: 6 || Key: 686.
Element: Pierre || Slot: 7 || Key: 615.
Element: Roger || Slot: 7 || Key: 511.
Element: Amber || Slot: 7 || Key: 487.
Checking table ...
All names found
TABLE: After deleting Daniela
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Mary || Slot: 1 || Key: 409.
Element: Frank || Slot: 2 || Key: 498.
Element: Susan || Slot: 2 || Key: 522.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Pierre || Slot: 7 || Key: 615.
Element: Roger || Slot: 7 || Key: 511.
Element: Amber || Slot: 7 || Key: 487.
TABLE: After deleting Amber
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Mary || Slot: 1 || Key: 409.
Element: Frank || Slot: 2 || Key: 498.
Element: Susan || Slot: 2 || Key: 522.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Pierre || Slot: 7 || Key: 615.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Mary
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Susan || Slot: 2 || Key: 522.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Pierre || Slot: 7 || Key: 615.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Pierre
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Susan || Slot: 2 || Key: 522.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Susan
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Ellen || Slot: 0 || Key: 496.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Ellen
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Alberto || Slot: 1 || Key: 713.
Element: Nancy || Slot: 1 || Key: 505.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Nancy
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Alberto || Slot: 1 || Key: 713.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Pietro || Slot: 3 || Key: 627.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Pietro
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Alberto || Slot: 1 || Key: 713.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Alberto
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Marco || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Marco
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Priscilla || Slot: 3 || Key: 931.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Priscilla
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Elvira || Slot: 3 || Key: 611.
Element: Dick || Slot: 3 || Key: 379.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Elvira
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Dick || Slot: 3 || Key: 379.
Element: Dracula || Slot: 4 || Key: 700.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Dracula
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Dick || Slot: 3 || Key: 379.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Jane || Slot: 6 || Key: 382.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Jane
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Frank || Slot: 2 || Key: 498.
Element: Dick || Slot: 3 || Key: 379.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Frank
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Dick || Slot: 3 || Key: 379.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
Element: Roger || Slot: 7 || Key: 511.
TABLE: After deleting Roger
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Dick || Slot: 3 || Key: 379.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
TABLE: After deleting Dick
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Nelly || Slot: 4 || Key: 516.
Element: Francesco || Slot: 4 || Key: 916.
TABLE: After deleting Francesco
Element: Frankenstein || Slot: 0 || Key: 1256.
Element: Fred || Slot: 1 || Key: 385.
Element: Nelly || Slot: 4 || Key: 516.
TABLE: After deleting Frankenstein
Element: Fred || Slot: 1 || Key: 385.
Element: Nelly || Slot: 4 || Key: 516.
TABLE: After deleting Fred
Element: Nelly || Slot: 4 || Key: 516.
TABLE: After deleting Nelly
UPDATE:
hash(key)
does not certainly return a non-negative number. insert(h, "\377");
can lead to a return value of -1. Better to use unsigned hash(unsigned key) { key %= SIZE; return key; }
and unsigned hidx = hash(key);
. –
chux - Reinstate Monica
I thought that this would guarantee non-negative:
hash += (unsigned) *str;
But, it should have been:
hash += (unsigned char) *str;
I kept the int
[vs. unsigned int
] because I was already changing a lot of code.
But, to be a bit clearer, I've added typedefs:
typedef unsigned int hash_t; // hash value
typedef unsigned int hidx_t; // hash index
Disagree with "find might be more useful if it returned node_t instead of char * (i.e. the element value)." as that obliges calling to know about the structure of the hash table. HT details best left out of the public eye. Overall, many good points about this answer. –
chux - Reinstate Monica
Originally, I was going to make find
be called by insert
and delete
to eliminate some replicated code. But, I didn't do that. Below is a refactored version that splits find
into findnode
[as I suggested] which can be called by findelement
[as you suggested].
And, thanks for the compliment ...
// HASHTABLE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#ifndef SIZE
#ifdef BIGSIZE
#define SIZE 512
#else
#define SIZE 8
#endif
#endif
typedef unsigned int hash_t; // hash value
typedef unsigned int hidx_t; // hash index
typedef struct nodez {
struct nodez *next;
const char *element;
hash_t key;
} node_t;
typedef struct hash_table {
#if DYNAMIC_TABLE
node_t **table; // dynamic table size
#else
node_t *table[SIZE]; // fixed table size
#endif
} hashtable;
#ifndef STRDUP
#define STRDUP 1 // use strdup when storing entry
#endif
#define ARRAY_COUNT(_arr) \
(sizeof(_arr) / sizeof(_arr[0]))
hashtable *
create_table(void)
{
hashtable *ht = calloc(1,sizeof(hashtable));
#if DYNAMIC_TABLE
ht->table = calloc(SIZE,sizeof(node_t *));
#endif
return ht;
}
// strhash -- get hash key from string
hash_t
strhash(const char *str)
{
hash_t hash = 0;
for (; *str != 0; ++str)
hash += (unsigned char) *str;
return hash;
}
// hash -- get hash index from hash key
hidx_t
hash(hash_t key)
{
// make the value acceptable
key %= SIZE;
return key;
}
node_t *
findnode(hashtable *ht,const char *element,hash_t key,node_t **aprev)
{
assert(element != NULL);
if (key == 0)
key = strhash(element);
hidx_t hidx = hash(key);
node_t *cur = ht->table[hidx];
node_t *prev = NULL;
for (; cur != NULL; cur = cur->next) {
if (key == cur->key) {
if (strcmp(element,cur->element) == 0)
break;
}
prev = cur;
}
if (aprev != NULL)
*aprev = prev;
return cur;
}
const char *
findelement(hashtable *ht,const char *element,hash_t key)
{
node_t *cur = findnode(ht,element,key,NULL);
if (cur != NULL)
element = cur->element;
else
element = NULL;
return element;
}
// insert -- head insertion
node_t *
insert(hashtable *ht,const char *element)
{
assert(element != NULL);
hash_t key = strhash(element);
// point to table bucket
hidx_t hidx = hash(key);
node_t **head = &ht->table[hidx];
// look for existing/duplicate element
node_t *cur = findnode(ht,element,key,NULL);
if (cur != NULL) {
printf("insert: duplicate node -- '%s'\n",element);
exit(1);
}
node_t *new_node = malloc(sizeof(node_t));
if (new_node == NULL) {
printf("Failed to allocate %s.\n", element);
exit(1);
}
new_node->key = key;
#if STRDUP
element = strdup(element);
#endif
new_node->element = element;
// add to head of linked list for this hash bucket
new_node->next = *head;
*head = new_node;
return new_node;
}
bool
delete(hashtable *ht, const char *element)
{
// compute hash value from string
hash_t key = strhash(element);
hidx_t hidx = hash(key);
node_t **head = &ht->table[hidx];
// look for a match
node_t *prev;
node_t *cur = findnode(ht,element,key,&prev);
// node not found
if (cur == NULL) {
printf("delete: node not found -- '%s'\n",element);
return false;
}
// remove the node from the linked list
if (prev != NULL)
prev->next = cur->next;
else
*head = cur->next;
// release the string
#if STRDUP
free((void *) cur->element);
#endif
// release the node
free(cur);
return true;
}
// displays the hashtable
void
display_hashtable(hashtable *ht,const char *why)
{
printf("\n");
printf("TABLE: %s\n",why);
for (hidx_t i = 0; i < SIZE; i++) {
node_t *cur = ht->table[i];
for (; cur != NULL; cur = cur->next)
printf("Element: %s || Slot: %d || Key: %d.\n",
cur->element, i, cur->key);
}
}
int
main(void)
{
hashtable *ht = create_table();
const char *names[] = {
"Francesco",
"Daniela",
"Pietro",
"Priscilla",
"Amber",
"Roger",
"Nelly",
"Marco",
"Susan",
"Mary",
"Ellen",
"Fred",
"Frank",
"Dick",
"Jane",
"Nancy",
"Elvira",
"Dracula",
"Frankenstein",
"Pierre",
"Alberto"
};
// insert all test names into table
for (hidx_t nidx = 0; nidx < ARRAY_COUNT(names); ++nidx)
insert(ht,names[nidx]);
display_hashtable(ht,"All Names");
// ensure we can find all the names
printf("\n");
printf("Checking table ...\n");
int err = 0;
for (hidx_t nidx = 0; nidx < ARRAY_COUNT(names); ++nidx) {
const char *name = names[nidx];
if (findnode(ht,name,0,NULL) == NULL) {
printf("ERROR: name '%s' not found\n",name);
err = 1;
}
}
if (err)
exit(1);
printf("All names found\n");
// delete all nodes in a random order
int delcount = 0;
while (delcount < ARRAY_COUNT(names)) {
// get a random name to delete
hidx_t delidx = rand() % ARRAY_COUNT(names);
const char *name = names[delidx];
// see if we have already deleted it
if (name == NULL)
continue;
delete(ht,name);
char why[100];
sprintf(why,"After deleting %s",name);
display_hashtable(ht,why);
// mark it as deleted
names[delidx] = NULL;
++delcount;
}
return 0;
}