開地址雜湊表(Hash Table)的介面定義與實現分析

來源:互聯網
上載者:User

開地址雜湊表(Hash Table)的介面定義與實現分析
開地址雜湊函數的介面定義

基本的操作包括:初始化開地址雜湊表、銷毀開地址雜湊表、插入元素、刪除元素、尋找元素、擷取元素個數。

各種操作的定義如下:

ohtbl_init

 int ohtbl_init (OHTbl *htbl, int positions, int (*h1) (const void *key), int (*h2)(const void *key),

                    int (*match)(const void *key1, const void *key2), void (*destroy)(void *data));

傳回值  如果雜湊表初始化成功,返回0;否則返回-1 。

描述  初始化開地址雜湊表htbl。在對雜湊表進行其他動作之前,必須首先進行初始化。

參數positions 指定表中的槽位個數。函數指標h1,h2用來指定使用者定義的輔助雜湊函數以完成雙散列過程。函數指標match指向一個使用者定義的函數,此函數用於判斷兩個鍵是否匹配,它的使用方法與chtbl_init中的match類似。函數指標destroy通過調用ohtbl_destroy來釋放動態分配的記憶體空間,同樣它與ohtbl_init中參數的使用方法類似。如果雜湊函數表中的資料不需要釋放,那麼destroy應該指向NULL。

複雜度  O(m),m是雜湊表中槽的個數。

ohtbl_destroy

 void ohtbl_destroy (OHTbl *htbl ) ;

傳回值  無 。

描述  銷毀htbl指定的開地址雜湊表。在調用ohtbl_destroy之後不再允許進行其他動作,除非再次初始化。

ohtbl_destroy會刪除雜湊表中的所有元素,並同時釋放ohtbl_init中參數destroy不為NULL的成員所佔用的記憶體空間。

複雜度  O(m),m是雜湊表中槽的個數。

ohtbl_insert

 int ohtbl_insert (OHTbl *htbl,const void *data ) ;

傳回值  如果插入元素成功,返回0;如果雜湊表中已經包含此元素,返回1;否則,返回-1 。

描述  向htbl指定的開地址雜湊表中插入一個元素。

新元素包含一個指向data的指標,因此只要元素仍然存在於雜湊表中,此指標就一直有效。與data相關的空間將由函數的調用者來管理。

複雜度  O(1)。

ohtbl_remove

 int ohtbl_remove (OHTbl *htbl,const void **data ) ;

傳回值  如果刪除元素成功,返回0;否則,返回-1 。

描述  從htbl指定的開地址雜湊表中刪除與data匹配的元素。

返回時,data指向已經刪除元素中儲存的資料。與data相關的記憶體空間將由函數調用者來管理。

複雜度  O(1)。

ohtbl_lookup

 int ohtbl_lookup (const OHTbl *htbl,const void **data ) ;

傳回值  如果在表中找到元素,返回0;否則,返回-1 。

描述  尋找htbl指定的開地址雜湊表中是否有與data匹配的元素。

如果找到,在函數返回時,data指向雜湊表中相匹配元素的資料。

複雜度  O(1)。

ohtbl_size

 int ohtbl_size (const OHTbl *htbl ) ;

傳回值  雜湊表中元素的個數。

描述  擷取雜湊表中元素個數的宏。

複雜度  O(1)。

開地址雜湊表的實現與分析

實現分為兩個檔案,一是開地址雜湊表的標頭檔,一是抽象資料類型的實現檔案。

樣本1:開地址雜湊表的標頭檔
/*ohtbl.h*/
#ifndef OHTBL_H #define OHTBL_H #include <stdlib.h>/*定義開地址雜湊表的資料結構*/typedef struct OHTbl_{ int positions; /*1指明雜湊表中分配的槽位元目*/ void *vacated; /*2指向一個特殊的地址空間,這個特殊的地址上曾經刪除過一個元素*/ int (*h1)(const void *key); /*3輔助雜湊函數*/ int (*h2)(const void *key); /*4輔助雜湊函數*/ int (*match)(const void *key1,const void *key2); /*5判斷兩個元素是否匹配*/ void (*destroy)(void *data); /*6銷毀函數*/ int size; /*7現有的元素數目*/ void **table; /*8儲存元素的數組*/ } OHTbl;
/*函數原型聲明*/
int ohtbl_init(OHTbl *htbl, int positions, int (*h1)(const void *key), int (*h2)(const void *key),
int (*match)(const void *key1,const void *key2),void (*destroy)(void *data));

void ohtbl_destroy(OHTbl *htbl);

int ohtbl_insert(OHTbl *htbl, const void *data);

int ohtbl_remove(OHTbl *htbl, void **data);

int ohtbl_lookup(const OHTbl *htbl, void **data);

#define ohtbl_size(htbl)((htbl)->size)
#endif // OHTBL_H
 樣本2:開地址雜湊表抽象資料類型的實現
/*ohtbl.c*/#include <stdlib.h>
#include <string.h>

#include "ohtbl.h"

/*為空白出的元素預留一個特殊的記憶體位址*/
static char vacated;

/*ohtbl_init 初始化htbl指定的開地址雜湊表*/
int ohtbl_init(OHTbl *htbl,int positions, int (*h1)(const void *key), int (*h2)(const void *key),
int (*match)(const void *key1, const void *key2),void (*destroy)(void *data))
{
int i;
/*為空白分配空間*/
if((htbl->table = (void **)malloc(positions * sizeof(void *))) == NULL)
return -1;

/*初始化每個槽位,把每個槽位的指標設定為NULL*/
htbl->positions = positions;
for(i=0; i<htbl->positions; i++)
htbl->table[i] = NULL;

  /*將空出的成員設定為為此保留的特殊記憶體位址*/
    htbl->vacated = &vacated;
   
    /*封裝4個函數*/
    htbl->h1 = h1;
    htbl->h2 = h2;
    htbl->match = match;
    htbl->destroy=destroy;
   
    /*初始化元素數量*/
    htbl->size = 0;
   
    return 0;
}

/*ohtbl_destroy 銷毀htbl指定的開地址式雜湊表*/
void ohtbl_destroy(OHTbl *htbl)
{
int i;

if(htbl->destroy != NULL)
{
for(i=0; i < htbl->positions; i++)
{
if(htbl->table[i] != NULL && htbl->table[i] != htbl->vacated)
htbl->destroy(htbl->table[i]);
}
}
/*釋放資料表空間*/
free(htbl->table);

/*清除資料結構*/
memset(htbl,0,sizeof(OHTbl);

return;
}

/*ohtbl_insert 向表中插入元素*/
int ohtbl_insert(OHTbl *htbl,const void *data)
{
void *temp;
int position,i;

/*因為開地址雜湊表有固定的大小,所以在插入之前必須保證有足夠的空間放置元素*/
if(htbl->size == htbl->positions)
return -1;

/*相同的鍵不允許重複插入表中,插入之前調用htbl_lookup檢查是否有相同的元素*/
temp = (void *)data;
if(ohtbl_lookup(htbl,temp) == 0)
return 1;

/*滿足以上條件,使用雙散列法在表中尋找未被佔用的槽*/
for(i=0; i< htbl->positions; i++)
{
position = (htbl->h1(data) + (i*htbl->h2(data))) % htbl->positions;

if(htbl->table[position]==NULL || htbl->table[position]==htbl->vacated)
{
/*將元素插入表中*/
htbl->table[position] = (void *)data;
htbl->size++;
return 0;
}
}
/*選用了錯誤的雜湊函數*/
return -1;
}

/*ohtbl_remove 刪除htbl指定表中與data相匹配的元素*/
int ohtbl_remove(OHTbl *htbl,void **data)
{
int position,i;

/*通過雙散列定位到要刪除元素的位置*/
for(i=0; i<htbl->positions; i++)
{
position = (htbl->h1(*data) + (i * h2(*data))) % htbl->positions ;

if(htbl->table[position] == NULL)
{
/*沒有找到匹配的資料*/
return -1;
}
else if (htbl->table[position] == htbl->vacated)
{
/*尋找到了突出的位置,繼續搜尋*/
continue;
}
else if (htbl->match(htbl->table[position],*data))
{
/*將data指向正在刪除的資料*/
*data = htbl->table[position];
/*將此槽位的地址放到vacated成員中*/
htbl->[position] = htbl->vacated;
htbl->size--;
return 0;
}
}
/*如果沒有找到元素,則返回-1*/
return -1;
}

/*ohtbl_lookup 尋找htbl指定的表中,與data相匹配的元素*/
int ohtbl_lookup(const OHTbl *htbl,void **data)
{
int position,i;

for(i=0; i<htbl->positions; i++)
{
position = (htbl->h1(*data) + (i * htbl->h2(*data)))% htbl->positions;

if(htbl->table[position] == NULL)
{
/*沒有找到資料*/
retun -1;
}
else if(htbl->match(htbl->table[position],*data))
{
/*將data指向找到的資料*/
*data = htbl->table[position];
return 0;
}
}
return -1;
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.