哈希表(散列)的实现方法
哈希表(散列)具有一种高效随机存取数据的特点。哈希表的主要思想是通过一个哈希函数,在所有可能的健与槽位之间建立一张映射表。哈希函数每次接受一个健将返回与健相对应的哈希编码或哈希值。健的数据类型可能多种多样,但哈希值的类型只能是整形。
本文主要讨论链式哈希表:
内村中结构图如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TABLESIZE 100
# ifndef _HashSep_H
struct _ListNode;
typedef struct _ListNode ListNode;
struct _HashTable;
typedef struct _HashTable HashTable;
struct _ELE_t;
typedef struct _ELE_t ELE_t;
int NextPrime( int );
int Hash( const char *, int );
HashTable *InitTable( int );
ListNode *Search( char *, HashTable * );
void Insert( char *, char *, HashTable * );
void Delete( char *, HashTable * );
# endif
struct _ELE_t {
char words[32];
char desc[60];
};
struct _ListNode {
ELE_t ele;
ListNode *next;
};
struct _HashTable {
unsigned int TableSize;
ListNode *HashList;
};
int NextPrime( int TableSize )
{
unsigned int flag = 1, tril = TableSize;
while ( 1 ) {
++tril; flag = 1;
for ( int i=2; i < tril; ++i ) {
if ( tril % i == 0 ) {
flag = 0; break;
}
}
if ( flag ) return tril;
}
}
int Hash( const char *key, int TableSize )
{
unsigned int HashVal = 0;
while ( *key != '\0' )
HashVal = (HashVal << 5) + *key++;
return HashVal % TableSize;
}
HashTable *InitTable( int TableSize )
{
HashTable *H;
H = (HashTable *)malloc(sizeof(HashTable));
if ( !H )
fprintf(stderr, "[Err::%s] Failed to allocate memory\n", __func__);
H->TableSize = NextPrime(TableSize);
H->HashList = (ListNode *)calloc(H->TableSize, sizeof(ListNode));
if ( !H->HashList )
fprintf(stderr, "[Err::%s] Failed to allocate memory\n", __func__);
return H;
}
ListNode *Search( char *key, HashTable *H )
{
ListNode *p;
p = &H->HashList[Hash(key, H->TableSize)];
while ( p && strcmp(key, p->ele.words) )
p = p->next;
return p;
}
void Insert( char *key, char *desc, HashTable *H )
{
ListNode *node, *tmp, *new;
node = &H->HashList[Hash(key, H->TableSize)];
if ( !strlen(node->ele.words) ) { /* the first head node is empty */
strcpy(node->ele.words, key); strcpy(node->ele.desc, desc);
return ;
}
tmp = node->next;
while ( tmp && strcmp(key, tmp->ele.words) ) {
node = tmp; tmp = tmp->next;
}
if ( !tmp ) { /* the key is not found in the hashtable */
new = (ListNode *)calloc(1, sizeof(ListNode));
if ( !new ) {
fprintf(stderr, "[Err::%s] Failed to allocate memory\n", __func__);
exit(-1);
}
strcpy(new->ele.words, key); strcpy(new->ele.desc, desc);
node->next = new;
}
else /* update the value for the existed key */
strcpy(tmp->ele.desc, desc);
}
void Delete( char *key, HashTable *H )
{
ListNode *node, *tmp;
node = &H->HashList[Hash(key, H->TableSize)];
if ( !strcmp(key, node->ele.words) ) {
tmp = node->next; memset(node, 0, sizeof(ListNode));
node->next = tmp;
return ;
}
tmp = node->next;
while ( tmp && strcmp(key, tmp->ele.words) ) {
node = tmp; tmp = tmp->next;
}
if ( !tmp ) // Can't find the key
fprintf(stderr, "[Err::%s] The key doesn't existed!\n", __func__);
else if ( !tmp->next ) { // the node is the last one
node->next = NULL; free(tmp);
}
else { // the node is within the linklist
node->next = tmp->next; free(tmp);
}
}
int main( void )
{
ListNode *node;
HashTable *table;
char words[32], desc[60];
/* Initinal the hashtable */
table = InitTable(TABLESIZE);
/* Input the data form keyeboard */
for ( int i=0; i < 2; ++i ) {
printf("Input key: "); fgets(words, 32, stdin);
printf("Input descion: "); fgets(desc, 60, stdin);
Insert(words, desc, table);
}
/* Delete a node from the hashtable */
printf("Delete a node key: "); fgets(words, 32, stdin);
Delete(words, table);
/* Search the node from the hashtable */
for ( int i=0; i < 2; ++i ) {
printf("key: "); fgets(words, 32, stdin);
node = Search(words, table);
if ( !node )
printf("Can't find the key!\n");
else
printf("Result: %s", node->ele.desc);
}
}