链式哈希表介绍
待补充
链式哈希表实现
// Chtbl.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
/*链表元素结构体定义*/
typedef struct ListElmt_
{
void *pdata;
struct ListElmt_ *pNext;
}ListElmt;
/*链表结构体定义*/
typedef struct List_
{
int iSize;
void (*destory)(void *data);
ListElmt *ListElmtHead;
ListElmt *ListElmtTail;
}List;
/*链表操作宏定义*/
#define LIST_SIZE(list) ((list)->iSize)
#define LIST_HEAD(list) ((list)->ListElmtHead)
#define LIST_TAIL(list) ((list)->ListElmtTail)
#define LIST_IS_HEAD(list, element) ((element == (list)->ListElmtHead) ? 1:0)
#define LIST_IS_TAIL(list, element) ((element == (list)->ListElmtTail) ? 1:0)
#define LIST_DATA(element) ((element)->pdata)
#define LIST_NEXT(element) ((element)->pNext)
/*
*函数名:List_Init
*参数:list 链表
* destory 释放链表节点内存的函数
*功能:单链表初始化
*返回值:无
*作者:AlbertoNo1
*日期:2016-04-14
*/
void List_Init(List *list, void (*destory)(void *data))
{
/*入参合法性由调用者保证*/
list->iSize = 0;
list->destory = destory;
list->ListElmtHead = NULL;
list->ListElmtTail = NULL;
return ;
}
/*
*函数名:List_Ins_Next
*参数:list 链表
* Element 待插入元素的前一个节点元素
* data 待插入元素数据
*功能:单链表添加节点函数
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-04-14
*/
int List_Ins_Next(List *list, ListElmt *Element, void *data)
{
ListElmt *Lelmt = NULL;
if ((NULL == list) || (NULL == data))
{
return -1;
}
/*申请链表节点内存*/
Lelmt = (ListElmt*)malloc(sizeof(ListElmt));
if (NULL == Lelmt)
{
return -1;
}
Lelmt->pdata = data;
if (NULL == Element)
{
/*在链表头插入元素*/
Lelmt->pNext = list->ListElmtHead;
list->ListElmtHead = Lelmt;
if (0 == LIST_SIZE(list))
{
list->ListElmtTail = Lelmt;
}
}
else
{
/*在非链表头插入元素*/
Lelmt->pNext = Element->pNext;
Element->pNext = Lelmt;
if (NULL == Lelmt->pNext)
{
list->ListElmtTail = Lelmt;
}
}
/*链表大小加1*/
list->iSize++;
return 0;
}
/*
*函数名:List_Rem_Next
*参数:list 链表
* Element 待删除元素的前一个节点元素
* data 返回删除元素的数据域
*功能:单链表删除节点函数
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-04-14
*/
int List_Rem_Next(List *list, ListElmt *Element, void **data)
{
ListElmt *Old_Lelmt = NULL;
if ((NULL == list) || (NULL == data))
{
return -1;
}
if (0 == LIST_SIZE(list))
{
return -1;
}
if (NULL == Element)
{
/*删除链表头元素*/
*data = list->ListElmtHead->pdata;
Old_Lelmt = list->ListElmtHead;
list->ListElmtHead = list->ListElmtHead->pNext;
if (1 == LIST_SIZE(list))
{
list->ListElmtTail = NULL;
}
}
else
{
/*删除非链表头元素*/
if (1 == LIST_SIZE(list))
{
return -1;
}
else
{
*data = Element->pNext->pdata;
Old_Lelmt = Element->pNext;
Element->pNext = Element->pNext->pNext;
if (NULL == Element->pNext)
{
list->ListElmtTail = Element;
}
}
}
/*释放删除节点的内存*/
free(Old_Lelmt);
/*链表大小减一*/
list->iSize--;
return 0;
}
/*
*函数名:List_Destory
*参数:list 链表
*功能:单链表销毁
*返回值:无
*作者:AlbertoNo1
*日期:2016-04-14
*/
void List_Destory(List *list)
{
void *data = NULL;
/*入参合法性由调用者保证*/
while (LIST_SIZE(list) > 0)
{
if ((0 == List_Rem_Next(list, NULL, &data))&&(NULL != list->destory))
{
list->destory(data);
}
}
memset(list, 0, sizeof(List));
return ;
}
/*
*函数名:destory
*参数:data 动态申请内存的地址
*功能:释放动态申请内存函数
*返回值:无
*作者:AlbertoNo1
*日期:2016-04-14
*/
void destory(void *data)
{
free(data);
}
/*链式哈希表数据结构*/
typedef struct CHTbl_
{
int buckets; /*桶的个数*/
int (*hash_func)(const void *key);
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
int size;
List *table;
}CHTbl;
/*链式哈希表操作宏定义*/
#define chtbl_size(htbl) ((htbl)->size)
#define CHTBL_BUCKETS (100)
/*
*函数名:chtbl_hash
*参数:key 哈希键值
*功能:哈希函数
*返回值:哈希值
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_hash(const void *key)
{
int value = *((int*)key);
return value%CHTBL_BUCKETS;
}
/*
*函数名:chtbl_match
*参数:pKey1 指向第一个比较元素的地址
* pKey2 指向第二个比较元素的地址
*功能:比较两个元素的大小
*返回值:1 表示Key1 大于 Key2
* -1 表示Key1 小于 Key2
* 0 表示Key1 等于 Key2
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_match(const void *pKey1, const void *pKey2)
{
/*对两个整型数进行比较*/
if (*((int*)pKey1) > *((int*)pKey2))
{
return 1;
}
else if (*((int*)pKey1) < *((int*)pKey2))
{
return -1;
}
else
{
return 0;
}
}
/*
*函数名:chtbl_init
*参数:htbl 链式哈希表
* buckets 哈希表桶个数
* h_func 哈希函数
* m_func 元素比较函数
* d_func 元素动态申请内存释放函数
*功能:链式哈希表初始化函数
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_init(CHTbl *htbl, int buckets, int (*h_func)(const void *key),int (*m_func)(const void *key1, const void *key2),
void (*d_func)(void *data))
{
int i = 0;
/*为哈希表申请内存空间*/
htbl->table = (List*)malloc(buckets*sizeof(List));
if (NULL == htbl->table)
{
return -1;
}
/*初始化(链表)桶*/
htbl->buckets = buckets;
for (i = 0; i < buckets; i++)
{
List_Init(&(htbl->table[i]), destory);
}
htbl->hash_func = h_func;
htbl->match = m_func;
htbl->destroy = d_func;
htbl->size = 0;
return 0;
}
/*
*函数名:chtbl_destory
*参数:htbl 链式哈希表
*功能:链式哈希表销毁函数
*返回值:无
*作者:AlbertoNo1
*日期:2016-04-14
*/
void chtbl_destory(CHTbl *htbl)
{
int i = 0;
/*销毁(链表)桶*/
for (i = 0; i < htbl->buckets; i++)
{
List_Destory(&(htbl->table[i]));
}
/*释放哈希表内存*/
free(htbl->table);
memset(htbl, 0, sizeof(CHTbl));
return ;
}
/*
*函数名:chtbl_lookup
*参数:htbl 链式哈希表
* data 待查找元素数据
*功能:链式哈希表元素查找函数
*返回值:0 哈希表中存在此元素 -1 哈希表中不存在此元素
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_lookup(const CHTbl *htbl, void **data)
{
ListElmt *element = NULL;
int bucket = 0;
/*获得哈希值*/
bucket = htbl->hash_func(*data)%(htbl->buckets);
/*在(链表)桶中查找元素*/
for (element = LIST_HEAD(&(htbl->table[bucket])); element != NULL; element = LIST_NEXT(element))
{
if (htbl->match(*data, LIST_DATA(element)) == 0)
{/*找到该元素*/
*data = LIST_DATA(element);
return 0;
}
}
/*该元素未找到*/
return -1;
}
/*
*函数名:chtbl_insert
*参数:htbl 链式哈希表
* data 待插入桶中的元素
*功能:链式哈希表添加元素函数
*返回值:0 成功 1 失败
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_insert(CHTbl *htbl, const void *data)
{
void *temp = NULL;
int bucket = 0;
int retval = 0;
/*如果哈希表中已经存在该元素,直接返回*/
temp = (void*)data;
if (chtbl_lookup(htbl, &temp) == 0)
{
return 1;
}
/*获得哈希值*/
bucket = htbl->hash_func(data)%(htbl->buckets);
/*把元素插到对应的桶中*/
retval = List_Ins_Next(&(htbl->table[bucket]), NULL, (void*)data);
if (0 == retval)
{/*插入成功*/
htbl->size++;
}
return retval;
}
/*
*函数名:chtbl_remove
*参数:htbl 链式哈希表
* data 待从桶中删除的元素
*功能:链式哈希表删除元素函数
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-04-14
*/
int chtbl_remove(CHTbl *htbl, const void **data)
{
ListElmt *element = NULL;
ListElmt *prev = NULL;
int bucket = 0;
/*获得哈希值*/
bucket = htbl->hash_func(*data)%(htbl->buckets);
/*在对应的链表桶中查找该元素*/
for (element = LIST_HEAD(&(htbl->table[bucket])); element != NULL; element = LIST_NEXT(element))
{
if (htbl->match(*data, LIST_DATA(element)) == 0)
{/*找到该元素*/
/*从(链表)桶中移除该元素*/
if (List_Rem_Next(&(htbl->table[bucket]), prev, (void**)data) == 0)
{
htbl->size--;
return 0;
}
else
{
return -1;
}
}
prev = element;
}
/*哈希表中不存在想要删除的元素*/
return -1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int iRet = 0;
int iLoop = 0;
int *piData = NULL;
CHTbl stCHtbl = {0};
chtbl_init(&stCHtbl, CHTBL_BUCKETS, chtbl_hash, chtbl_match, destory);
for (iLoop = 0; iLoop < 10; iLoop++)
{
piData = (int*)malloc(sizeof(int));
*piData = iLoop;
iRet |= chtbl_insert(&stCHtbl,(void*)piData);
}
if (0 != iRet)
{
return -1;
}
piData = (int*)malloc(sizeof(int));
*piData = 9;
iRet = chtbl_lookup(&stCHtbl, (void**)&piData);
printf("%d \r\n", iRet);
free(piData);
piData = (int*)malloc(sizeof(int));
*piData = 10;
iRet = chtbl_lookup(&stCHtbl, (void**)&piData);
printf("%d \r\n", iRet);
free(piData);
piData = (int*)malloc(sizeof(int));
*piData = 9;
iRet = chtbl_remove(&stCHtbl, (const void**)&piData);
printf("%d \r\n", iRet);
free(piData);
piData = (int*)malloc(sizeof(int));
*piData = 9;
iRet = chtbl_lookup(&stCHtbl, (void**)&piData);
printf("%d \r\n", iRet);
free(piData);
chtbl_destory(&stCHtbl);
getchar();
return 0;
}