C演算法精解—–雜湊表(2)

來源:互聯網
上載者:User
  前面對鏈式雜湊表的定義、實現、分析的一下,感覺也不是想象中的那麼難,只要把思路理清,在草稿紙上畫下他的實現思路,代碼閱讀起來也就一目瞭然了。下次再看時,只要把當初畫的草圖一拿出來就知道,當初定義的函數介面:插入、刪除、尋找是怎麼實現的。資料結構本身就是很抽象的東西。對初學者來說,畫草圖是很容易理解代碼實現思路。  下面介紹另外一種雜湊表的實現方法 :開地址雜湊表的描述。  在鏈式雜湊表中,元素存在在每個地址的桶中。而開地址雜湊表,元素存放在表本身中。因為註定不能和鏈式雜湊表一樣解決衝突。在開地址雜湊表中解決衝突的方式就是探查這個表,直到找個放這個元素的槽,或者找到這個元素。當然如果遍曆完整個表也沒有找到這個元素,說明元素沒有在表中。  檢索雜湊表的效率主要有2個因素有關:雜湊表的負載因子(元素的總個數處於桶的個數)和 元素均勻分布的程度。線性探查  線性探查的雜湊函數定義:h(k,i) = (h`(k)+i)mod m ,k是鍵(插入的元素),i表示探查的次數,i是大於等於0小於m.m槽個數。h`是一個輔助雜湊函數。h`=k mod m.下面一個簡單例子介紹下:雙散列  最有效探查開地址雜湊表的方法之一,就是通過計算兩個輔助雜湊函數雜湊編碼的和來得到雜湊編碼。雙散列的雜湊函數定義為:h(k,i) = (h1(k) + ih2(k)) mod m    h1和 h2是兩個輔助雜湊函數

開地址雜湊表的實現和分析疑問:就是結構體中定義的一個變數vacated 在代碼中的作用:個人理解沒有起到什麼實質的作用,就是儲存了上一次刪除操作的一個位置~。有其他更好理解的給解釋下~

 

/*ohtbl.h*/#ifndef OHTBL_H#define OHTBL_H#include <stdlib.h>/*定義開地址雜湊表結構體*/typedef struct Ohtbl_{    int positions;/*槽位的個數*/    void *vacated;/*指標將被初始化來指向一個特殊的地址空間,                         來證明這個特殊地址上曾經刪除過一個元素*/    int (*h1)(const void * key);    int (*h2)(const void *key);    int (*match)(const void *key1,const void *key2);    void (*destroy)(void *data);    int size;/*元素的個數*/    void **table;/*儲存元素的數組(malloc申請)*/}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.c*/#include <stdlib.h>#include <string.h>#include "./include/ohtbl.h"/*預訂一個記憶體地位為騰出的元素*/static char vacated;/*結構體初始化  *return 初始化成功: 0,  失敗:-1.  */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;    /*初始化每個positions*/    htbl ->positions = positions;    for (i = 0; i < htbl->positions; i++)        htbl -> table[i] = NULL;    /*設定騰出成員的記憶體位址*/    htbl->vacated = &vacated;    /*初始化封裝的函數*/    htbl -> h1 = h1;    htbl -> h2 = h2;    htbl ->match = match;    htbl ->destroy = destroy;    /*初始化元素個數*/    htbl ->size = 0;    return 0;}/*開地址雜湊表銷毀  *  *  */  int 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]);                     }    }    /*釋放table 記憶體*/    free(htbl ->table);    /*清空雜湊表結構體*/    memest(htbl,0,sizeof(Ohtbl));    return;}/* 雜湊表中插入元素  *return 初始化成功: 0,  失敗:-1.  *  資料已經在雜湊表內返回:1  */int ohtbl_insert(Ohtbl * htbl, const void * data){    void *temp;    int position = 0;    int  i = 0;    /*但雜湊表已經滿的話返回-1*/    if (htbl ->size == htbl ->positions)        return -1;    /*如果資料已經在雜湊表內,返回1*/    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;}/* 刪除雜湊表數值  *return 初始化成功: 0,  失敗:-1.  */int ohtbl_remove(Ohtbl * htbl, void * * data){    int i = 0;    int position = 0;    if (htbl ->size == 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){/*表明元素未存放到雜湊表內*/            return -1;        } else if (htbl ->table[position] == htbl ->vacated){            /*搜尋vacated 之外*/            continue;        } else if(htbl -> match(htbl->table[position],*data)){            *data = htbl->table[position];            htbl->table[position] = htbl ->vacated;            htbl->size --;            return 0;        }    }    return -1}/*尋找資料  *return 初始化成功: 0,  失敗:-1.  */int ohtbl_lookup(const Ohtbl * htbl, void * * data){    int position = 0;    int i = 0;    for (i = 0; i <htbl -> positions; i++){        /*獲得雜湊編碼值*/        position = (htbl->h1(data) + i * htbl ->h2(data)) %htbl ->positions;        if (htbl ->table[position] == NULL){/*表明元素未存放到雜湊表內*/            return -1;        } else if(htbl -> match(htbl->table[position],*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.