鏈式哈希表的接口定義
關於哈希表與鏈式哈希表的描述可以參閱:http://www.cnblogs.com/idreamo/p/7990860.html
鏈式哈希表的操作與屬性有:初始化、銷毀、插入元素、刪除元素、查找元素、獲取哈希表中無數的個數。
chtbl_init
int cltbl_init(CHTbl *htbl, int buckts, int (*h)(const void *key), int (*match)(const void *key1,const void *key2), void (*destroy)(void *data));
返回值:如果哈希表初始化成功,返回0,否則返回-1。
描述: 初始化htbl指定的鏈式哈希表。
在對鏈式哈希表執行其他操作之前,必須要先初始化。哈希表中所分配的“桶”的個數將由buckets指定。函數指針h指向一個用戶定義的哈希函數,此函數會將鍵進行散列。函數指針match指向一個用戶定義的函數,此函數用於判斷兩個鍵是否匹配。如果key1等於key2,返回1;否則返回其他值。參數destroy是一個函數指針,通過調用chtbl_destroy來釋放動態分配的內存空間。如果哈希表中的數據不需要釋放,那么destroy應該指向NULL。
復雜度: O(m),m是哈希表中“桶”的個數。
chtbl_destroy
void cltbl_destroy(CHTbl *htbl);
返回值:無。
描述: 銷毀htbl指定的鏈式哈希表。
在調用chtbl_destroy之后不再允許進行其他操作,除非再次調用chtbl_init。chtbl_destroy會刪除哈希表中的所有元素,並同時釋放chtbl_init中參數destroy不為NULL的成員所占用的內存空間。
復雜度: O(m),m是哈希表中“桶”的個數。
chtbl_insert
int cltbl_insert(CHTbl *htbl,const void *data);
返回值:如果插入元素成功則返回0;如果哈希表中已經包含此元素,返回1;否則返回-1。
描述: 向htbl指定的鏈式哈希表中插入一個元素。
新元素包含一個指向data的指針,只要元素仍然存在於哈希表中,此指針就一直有效。與data相關的內存空間將由函數的調用者來管理。
復雜度: O(m),m是哈希表中“桶”的個數。
chtbl_remove
int cltbl_remove(CHTbl *htbl,const void **data);
返回值:如果刪除元素成功則返回0;否則返回-1。
描述: 從htbl指定的鏈式哈希表中刪除與data匹配的元素。
返回時data指向已經刪除元素中存儲的數據。與data相關的內存空間將由函數的調用者來管理。
復雜度: O(1)
chtbl_lookup
int cltbl_lookup(const CHTbl *htbl,const void **data);
返回值:如果在哈希表中找到元素則返回0;否則返回-1。
描述: 查找htbl指定的鏈式哈希表中與data相匹配的元素。
如果找到,在函數返回時,data將指向哈希表中相匹配元素中的數據。
復雜度: O(1)
chtbl_size
int cltbl_size(CHTbl *htbl);
返回值:哈希表中的元素個數。
描述: 獲取htbl指定的鏈式哈希表的元素個數的宏。
復雜度: O(1)
鏈式哈希表的實現與分析
示例:鏈式哈希表抽象數據類型的頭文件
#ifndef CHTBL_H #define CHTBL_H #include <stdlib.h> #include "list.h" /*為哈希表定義一個數據結構*/ typedef struct CHTbl_ { int buckets; /*1、表中分配的“桶”的個數*/ int (*h)(const void *key); /*2、指向哈希函數*/ int (*match)(const void *key1, const void *key2); /*3、指向match函數*/ int (*destroy)(void *data); /*4、指向銷毀函數*/ int size; /*5、表中元素的數量*/ List *table; /*6、存儲“桶”的數組*/ }CHTbl; /*公用接口*/ int chtbl_init(CHTbl *htbl, int buckets, int(*h)(void *key), int (*match)(const void *key1, const void *key2), void(*destroy)(void *data)); int chtbl_destroy(CHTbl *htbl); int chtbl_insert(CHTbl *htbl, const void *data); int chtbl_remove(CHTbl *htbl,void **data); int chtbl_lookup(const CHTbl *htbl,void **data); #define chtbl_size(htbl)((htbl)->size) #endif // CHTBL_H
示例:鏈式哈希表的實現
#include <stdlib.h> #include <string.h> #include "list.h" #include "chtbl.h" /*chtbl_init 初始化鏈式哈希表*/ int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int (*match)(const void *key1,const void *key2),void (*destroy)(void *data)) { int i; /*首先,為“桶”分配空間*/ if((htbl->table = (List *)malloc(buckets*sizeof(List)))==NULL) return -1; /*然后,調用list_init初始化這些桶*/ htbl->buckets = buckets; for(i=0;i<htbl->buckets;i++) list_init(&htbl->table[i],destroy); /*接着,封裝h,match,destroy函數*/ htbl->h = h; htbl->match = match; htbl->destroy = destroy; /*最后,將size值設置為0*/ htbl->size = 0; return 0; } /*chtbl_destroy 銷毀鏈式哈希表*/ void chtbl_destroy(CHTbl *htbl) { int i; /*首先,刪除每個“桶”中的元素*/ for(i=0;i<htbl->buckets;i++) { list_destroy(&htbl->table[i]); } /*然后,釋放由chtbl_init分配的內存空間*/ free(htbl->table); /*最后,哈希表不再允許任何操作,清除這一結構作為錯誤預防*/ memset(htbl,0,sizeof(CHTbl)); return ; } /*chtbl_insert 向鏈式哈希表中插入元素*/ int chtbl_insert(CHTbl *htbl,const void *data) { void *temp; int bucket,retval; /*首先,調用chtbl_lookup檢查哈希表中是否已經存有該元素*/ temp = (void *)data; if(chtbl->lookup(htbl,&temp)==0) return 1; /*如果未存有該元素,接着將新元素的鍵散列*/ bucket = htbl->h(data) % htbl->buckets; /*然后,根據哈希編碼將新元素插入哈希表中相應位置的“桶”中*/ if((retval = list_ins_next(&htbl->table[bucket],NULL,data))==0) htbl->size++; return retval; }
/*chtbl_remove 刪除表中的元素*/
int chtbl_remove(CHTbl *htbl,void **data)
{
ListElmt *element,*prev;
int bucket;
/*首先,哈希(散列)元素的鍵*/
bucket = htbl->h(*data)%htbl->buckets;
/*接着,查找與元素的鍵相匹配的桶*/
prev = NULL;
for(element = list_head(&htbl->table[bucket]);element != NULL; element = list_next(element))
{
if(htbl->match(*data,list_data(element)))
{
/*然后,調用list_rem_next刪除元素*/
if(list_rem_next(&htbl->table[bucket],prev,data) == 0)
{
htbl->size--;
return 0;
}
else
{
return -1;
}
}
prev = element;
}
/*遍歷結束后,沒有找到元素,返回-1*/
retrun -1;
}
/*chtbl_lookup 查找元素*/
int chtbl_lookup(const CHTbl *htbl,void **data)
{
ListElmt *element;
int bucket;
/*首先,散列要查找元素的鍵*/
bucket = htbl->h(*data) % htbl->buckets;
/*接着,查找與元素相匹配的桶*/
for(element = list_head(&htbl->table[bucket]; element != NULL; list_next(element))
{
if(htbl->match(*data,list_data(element))
/*從表中返回該元素*/
*data = list_data(element);
return 0;
}
/*遍歷結束后,沒有找到元素,則返回-1*/
return -1;
}