數據結構 鏈式哈希表(Hash Table)的接口定義與實現分析(完整代碼)


鏈式哈希表的接口定義

關於哈希表與鏈式哈希表的描述可以參閱: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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM