链式哈希表介绍
待补充
链式哈希表实现
// 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; }