哈希公共服務(wù)

哈希鏈地址法

哈希的引入是數(shù)組和鏈表的結(jié)合體,有效解決了查詢/插入/刪除的性能問(wèn)題。但不可避免的引入了哈希沖突問(wèn)題,解決沖突的方法有多種,本文只針對(duì)鏈地址法的設(shè)計(jì)進(jìn)行描述。

鏈地址法

鏈地址法簡(jiǎn)而言之即將所有哈希地址相同的記錄都鏈接在同一鏈表中

算法設(shè)計(jì)

  • 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
/* 哈希單元定義 */
typedef struct {
    struct list_head list;
    void   *item;
} lib_hash_item_t;
/*  哈希表結(jié)構(gòu)定義 */
typedef struct {
    u_int32_t   hash_table_size;
    u_int32_t   hash_item_num;
    u_int32_t   hash_bucket_warn_size;
    u_int32_t   max_conflict_size;
    u_int8_t    *hash_bucket_size;
    struct list_head *hash_table;
    hash_get_index_func_t  hash_get_index;
    hash_cmp_key_func_t    hash_cmp_key;
} lib_hash_t;
  • 哈希函數(shù)聲明
/* 創(chuàng)建哈希表 */
lib_hash_t *lib_create_hash(u_int32_t item_num, hash_get_index_func_t hash_get_index,  hash_cmp_key_func_t hash_cmp_key);

/* 刪除哈希表 */
void lib_destroy_hash(lib_hash_t *hash);

/* 插入哈希單元 */
int lib_hash_insert_item(lib_hash_t * hash, void *item);

/* 刪除哈希單元 */
void lib_hash_del_item(lib_hash_t * hash, void *item);

/* 查找哈希單元 */
void *lib_hash_find_item(lib_hash_t * hash, void *item);
  • 哈希函數(shù)定義
/* 創(chuàng)建一張哈希表 */
lib_hash_t *lib_create_hash(u_int32_t item_num, hash_get_index_func_t hash_get_index, hash_cmp_key_func_t hash_cmp_key)
{
    int32_t     i;
    u_int32_t   hash_table_size;
    struct list_head *hash_table;
    lib_hash_t *hash;

    hash = malloc(sizeof(libss_hash_t));
    if (hash == NULL) {
        return NULL;
    }
    
    item_num = item_num == 0 ? MIN_HASH_SZ : item_num;
    hash_table_size = ((double)item_num) / HASH_GENE;
    hash_table = malloc(sizeof(struct list_head) * hash_table_size);
    if (hash_table == NULL) {
        free(hash);
        return NULL;
    }
    if ( (hash->hash_bucket_size = malloc( sizeof(hash->hash_bucket_size[0]) * 
     hash_table_size )) == NULL ){
        free(hash);
        free(hash_table );
        return NULL;
    }
        
    for (i = 0; i < hash_table_size; i++) {
        hash->hash_bucket_size[i] = 0;
        INIT_LIST_HEAD(&hash_table[i]);
    }
    
    hash->hash_item_num     = 0;
    hash->hash_table_size   = hash_table_size;
    hash->hash_table        = hash_table;
    hash->hash_get_index    = hash_get_index;
    hash->hash_cmp_key      = hash_cmp_key;
    hash->hash_bucket_warn_size = 0;
    hash->max_conflict_size = 0;
    
    return hash;
}
/* 刪除哈希表 */
void lib_destroy_hash(lib_hash_t *hash)
{
    free(hash->hash_bucket_size);
    free(hash->hash_table);
    free(hash);
    
    return;
}
/* 哈希表中插入一個(gè)單元 */
int32_t lib_hash_insert_item(lib_hash_t *hash, void *item)
{
    u_int32_t              index;
    lib_hash_item_t        *hash_item;

    hash_item = malloc(sizeof(lib_hash_item_t));
    if (hash_item == NULL) {
        return (-ENOMEM);
    }
    /* 獲取hash地址 */
    index = hash->hash_get_index(item) % hash->hash_table_size;
    hash_item->item = item;
   /* hash地址所在鏈表添加單元 */
    list_add(&hash_item->list, &hash->hash_table[index]);
    hash->hash_bucket_size[index]++;
   /* 更新hash沖突的最大節(jié)點(diǎn)數(shù) */
    if (hash->hash_bucket_size[index] > hash->max_conflict_size) {
        hash->max_conflict_size = hash->hash_bucket_size[index];
    }
    hash->hash_item_num++;

    return 0;
}
/* 哈希表中刪除一個(gè)單元 */
void lib_hash_del_item(lib_hash_t *hash, void *item)
{
    u_int32_t            index;
    struct list_head *pos, *n;
    lib_hash_item_t *hash_item;

    index = hash->hash_get_index(item) % hash->hash_table_size;
   /* 遍歷哈希地址所在鏈表 */
    list_for_each_safe(pos, n, &hash->hash_table[index]) {
        hash_item = list_entry(pos, lib_hash_item_t, list);
        if (hash->hash_cmp_key(hash_item->item, item) == 0) {
            hash->hash_bucket_size[index]--;
            hash->hash_item_num--;
            list_del(&hash_item->list);
            free(hash_item);
            break;
        }
    }
}
/* 查找哈希表單元 */
void *lib_hash_find_item(lib_hash_t *hash, void *item)
{
    u_int32_t index;
    struct list_head *pos;
    lib_hash_item_t *hash_item;

    index = hash->hash_get_index(item) % hash->hash_table_size;
    list_for_each(pos, &hash->hash_table[index]) {
        hash_item = list_entry(pos, libss_hash_item_t, list);
        if (hash->hash_cmp_key(hash_item->item, item) == 0) {
            return hash_item->item;
        }
    }
    return NULL;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一.概念 哈希表就是一種以 鍵-值(key-indexed) 存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),我們只要輸入待查找的值即key,即可...
    lfp901020閱讀 3,132評(píng)論 0 2
  • 哈希表定義 散列表(Hash table,也叫哈希表),是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)...
    n油炸小朋友閱讀 5,032評(píng)論 0 22
  • 哈希表:即散列存儲(chǔ)結(jié)構(gòu)。散列法存儲(chǔ)的基本思想:建立記錄關(guān)鍵碼字與其存儲(chǔ)位置的對(duì)應(yīng)關(guān)系,或者說(shuō),由關(guān)鍵碼的值決定數(shù)據(jù)...
    linbj閱讀 6,646評(píng)論 1 5
  • 如需轉(zhuǎn)載, 請(qǐng)咨詢作者, 并且注明出處.有任何問(wèn)題, 可以關(guān)注我的微博: coderwhy, 或者添加我的微信: ...
    coderwhy閱讀 11,942評(píng)論 19 122
  • 2018年6月26日,這是極其普通的一天,普通到我壓根兒就沒(méi)有記住到底是26號(hào)還是27號(hào)與L先生相遇的。 ...
    夏木佳佳閱讀 417評(píng)論 0 1

友情鏈接更多精彩內(nèi)容