又如一个List
/**************************************************************
* 哈希表管理单元(cs_hash.h 定义)
*
*
*
* 作者:何清
* 日期:2003-06-09
*
*
* 更新历史:
*
* @2003-06-09
* 创建文档
**************************************************************/
#ifndef __CSCRIPTPROJECT_HASH_H__
#define __CSCRIPTPROJECT_HASH_H__
#include "cs_os.h"
/* 计算Hash值的函数,则用户提供 */
typedef unsigned int (*HashFunc) (LPVOID key);
typedef void (*UserFunc) (LPVOID value, LPVOID data);
typedef struct _HashNode
{
LPVOID key;
LPVOID value;
struct _HashNode *next;
}HashNode;
typedef struct _HashTable
{
DWORD size;
DWORD nnodes;
HashNode **nodes;
HashFunc hash_func;
EqualFunc key_equal_func;
}HASHTABLE, *LPHASHTABLE;
/*
*Hash tables
*/
LPHASHTABLE hash_table_new (HashFunc hash_func, EqualFunc key_equal_func);
void hash_table_destroy (LPHASHTABLE hash_table);
LPVOID hash_table_find (LPHASHTABLE hash_table, LPVOID key);
void hash_table_insert (LPHASHTABLE hash_table, LPVOID key, LPVOID value);
BOOL hash_table_remove (LPHASHTABLE hash_table, LPVOID key);
void hash_table_foreach(LPHASHTABLE hash_table, UserFunc user_func, LPVOID data);
unsigned int hash_table_get_size (LPHASHTABLE hash_table);
/* Hash Functions
*/
unsigned int direct_hash (LPVOID v);
#endif /* end of __CSCRIPTPROJECT_HASH_H__ */
/**************************************************************
* 哈希表管理单元(cs_hash.c 实现)
*
*
*
* 作者:何清
* 日期:2003-06-09
*
*
* 更新历史:
*
* @2003-06-09
* 创建文档
**************************************************************/
#include "../include/cs_hash.h"
#include "../include/cs_mem.h"
#include <stdio.h>
#include <stdlib.h>
#define HASH_TABLE_MIN_SIZE 11
#define HASH_TABLE_MAX_SIZE 13845163
static const unsigned int primes[] = {
11, 19, 37, 73, 109, 163, 251, 367, 557, 823,
1237, 1861, 2777, 4177, 6247, 9371, 14057,
21089, 31627, 47431, 71143, 106721, 160073, 240101,
360163, 540217, 810343, 1215497, 1823231, 2734867,
4102283, 6153409, 9230113, 13845163
};
static const unsigned int nprimes = sizeof (primes) / sizeof (primes[0]);
static void hash_table_resize(LPHASHTABLE hash_table);
static HashNode** hash_table_find_node(LPHASHTABLE hash_table, LPVOID key);
static HashNode* hash_node_new(LPVOID key, LPVOID value);
static void hash_node_destroy(HashNode *hash_node);
static void hash_nodes_destroy(HashNode *hash_node);
static unsigned int primes_closest(unsigned int num);
static void hash_table_needresize(LPHASHTABLE hash_table);
/* 创建一个hash表容器 */
LPHASHTABLE hash_table_new (HashFunc hash_func, EqualFunc key_equal_func)
{
LPHASHTABLE hash_table;
unsigned int i;
hash_table = (LPHASHTABLE)mem_new( sizeof(HASHTABLE) );
hash_table->size = HASH_TABLE_MIN_SIZE;
hash_table->nnodes = 0;
hash_table->hash_func = hash_func ? hash_func : direct_hash;
hash_table->key_equal_func = key_equal_func;
hash_table->nodes = mem_new ( sizeof(HashNode*)*hash_table->size);
for (i = 0;
i < hash_table->size;
i++)
hash_table->nodes = NULL;
return hash_table;
}
/* 删除一个Hash表容器 */
void hash_table_destroy(LPHASHTABLE hash_table)
{
unsigned int i;
if ( NULL == hash_table )
return;
for (i = 0;
i < hash_table->size;
i++)
hash_nodes_destroy(hash_table->nodes);
mem_destroy(hash_table->nodes);
mem_destroy(hash_table);
}
static HashNode** hash_table_find_node(LPHASHTABLE hash_table, LPVOID key)
{
HashNode **node;
node = &hash_table->nodes[(* hash_table->hash_func) (key) % hash_table->size];
if (hash_table->key_equal_func)
while (*node &&
!(*hash_table->key_equal_func) ((*node)->key, key))
node = &(*node)->next;
else
while (*node &&
(*node)->key != key)
node = &(*node)->next;
return node;
}
/* 从hash表中找一个元素 */
LPVOID hash_table_find(LPHASHTABLE hash_table, LPVOID key)
{
HashNode *node;
if ( hash_table == NULL || key == NULL) return NULL;
node = *hash_table_find_node(hash_table, key);
if ( node )
return node->value;
else
return NULL;
}
/* 将一个元素插入到Hash表容器中 */
void hash_table_insert(LPHASHTABLE hash_table, LPVOID key, LPVOID value)
{
HashNode **node;
if ( hash_table == NULL )
return;
node = hash_table_find_node(hash_table, key);
if (*node)
{
(*node)->value = value;
}
else
{
*node = hash_node_new(key, value);
hash_table->nnodes++;
hash_table_needresize(hash_table);
}
}
BOOL hash_table_remove(LPHASHTABLE hash_table, LPVOID key)
{
HashNode **node, *dest;
if ( hash_table ==NULL ) return FALSE;
node = hash_table_find_node (hash_table, key);
if (*node)
{
dest = *node;
(*node) = dest->next;
hash_node_destroy(dest);
hash_table->nnodes--;
hash_table_needresize(hash_table);
return TRUE;
}
return FALSE;
}
void hash_table_foreach(LPHASHTABLE hash_table, UserFunc user_func, LPVOID data)
{
HashNode *node;
unsigned int i;
if ( hash_table == NULL || user_func == NULL )return;
for (i = 0;
i < hash_table->size;
i++)
for (node = hash_table->nodes;
node;
node = node->next)
(* user_func) (node->value, data);
}
unsigned int hash_table_get_size(LPHASHTABLE hash_table)
{
if ( hash_table ==NULL ) return 0;
return hash_table->nnodes;
}
static void hash_table_needresize(LPHASHTABLE hash_table)
{
if ((hash_table->size >= 3 * hash_table->nnodes &&
hash_table->size > HASH_TABLE_MIN_SIZE) ||
(3 * hash_table->size <= hash_table->nnodes &&
hash_table->size < HASH_TABLE_MAX_SIZE))
hash_table_resize (hash_table);
}
static void hash_table_resize(LPHASHTABLE hash_table)
{
HashNode **new_nodes;
HashNode *node;
HashNode *next;
unsigned int hash_val;
int new_size;
unsigned int i;
i = primes_closest(hash_table->nnodes);
new_size = i > HASH_TABLE_MAX_SIZE ? HASH_TABLE_MAX_SIZE : i < HASH_TABLE_MIN_SIZE ? HASH_TABLE_MIN_SIZE : i
new_nodes = mem_new( sizeof(HashNode*)*new_size);
for (i = 0;
i < hash_table->size;
i++)
for (node = hash_table->nodes;
node;
node = next)
{
next = node->next;
hash_val = (* hash_table->hash_func) (node->key) % new_size;
node->next = new_nodes[hash_val];
new_nodes[hash_val] = node;
}
mem_destroy(hash_table->nodes);
hash_table->nodes = new_nodes;
hash_table->size = new_size;
}
static HashNode* hash_node_new(LPVOID key, LPVOID value)
{
HashNode *hash_node;
hash_node = mem_new( sizeof(HashNode) );
hash_node->key = key;
hash_node->value = value;;
hash_node->next = NULL;
return hash_node;
}
static void hash_node_destroy(HashNode *hash_node)
{
hash_node->key = NULL;
hash_node->value = NULL;
mem_destroy(hash_node);
}
static void hash_nodes_destroy(HashNode *hash_node)
{
if (hash_node)
{
HashNode *node = hash_node;
HashNode *temp;
while (node->next)
{
node->key = NULL;
node->value = NULL;
temp = node;
node = node->next;
mem_destroy(temp);
}
node->key = NULL;
node->value = NULL;
mem_destroy(node);
}
}
static unsigned int primes_closest(unsigned int num)
{
unsigned int i;
for (i = 0;
i < nprimes;
i++)
if (primes > num)
return primes;
return primes[nprimes - 1];
}
unsigned int direct_hash (LPVOID v)
{
return (unsigned int)v;
}