`
bcyy
  • 浏览: 1824894 次
文章分类
社区版块
存档分类
最新评论

C算法精解-----哈希表(2)

 
阅读更多

前面对链式哈希表的定义、实现、分析的一下,感觉也不是想象中的那么难,只要把思路理清,在草稿纸上画下他的实现思路,代码阅读起来也就一目了然了。下次再看时,只要把当初画的草图一拿出来就知道,当初定义的函数接口:插入、删除、查找是怎么实现的。数据结构本身就是很抽象的东西。对初学者来说,画草图是很容易理解代码实现思路。

下面介绍另外一种哈希表的实现方法 :开地址哈希表的描述。

在链式哈希表中,元素存在在每个地址的桶中。而开地址哈希表,元素存放在表本身中。因为注定不能和链式哈希表一样解决冲突。在开地址哈希表中解决冲突的方式就是探查这个表,直到找个放这个元素的槽,或者找到这个元素。当然如果遍历完整个表也没有找到这个元素,说明元素没有在表中。

检索哈希表的效率主要有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;
}
分享到:
评论

相关推荐

    算法精解-c语言描述

    《算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!全书共分为三部分:第一部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法中最常用的技术...

    算法精解-经典算法书籍

    算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!《算法精解:C语言描述》共分为三部分:第一部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法中...

    算法精解.C语言描述

    《算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!全书共分为三部分:部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法中最常用的技术——...

    算法精解C描述

    《算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!全书共分为三部分:第一部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法中最常用的技术...

    算法精解:C语言描述

    命名规则适用于全书所有的代码,所有的代码都包含大量注释……《算法精解:C语言描述》内容包括:数据结构和算法的概念,以及使用它们的原因和意义 指针和递归算法分析常用数据结构:链表、栈、队列、集合、哈希表、...

    算法精解:C语言描述 PDF

    算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!全书共分为三部分:部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法中最常用的技术——指针...

    算法精解(C语言描述)Kyle Loudon 机械工业出版

    第二部分对链表、栈、队列、集合、哈希表、堆、图等常用数据结构进行了深入阐述;第三部分对排序、搜索数值计算、数据压缩、数据加密、图算法、几何算法等经典算法进行了精辟的分析和讲解。 本书的众多特色使得它在...

    C算法精解部分代码

    C语言算法精解的部分代码,包括链表、哈希等,以及进程通信管道的部分。

    算法精解:C语言描述 chm

    《算法精解》本书绝不同于之前的相关书籍。当我们在学习数据结构和算法时,往往花费了大量的时间纠结于各种公式和理论证明上,学究气息过于浓厚而少了几分实践感。相关 主题的书籍多是以伪码的形式来表达算法思路,...

    算法精解:c语言描述(高清带标签可复制文本)

     《Reilly精品图书系列·算法精解:C语言描述》内容包括:  · 数据结构和算法的概念,以及使用它们的原因和意义  · 指针和递归  · 算法分析  · 常用数据结构:链表、栈、队列、集合、哈希表、树、堆、...

    算法精解:C语言描述中文版(高清)

    本书是数据结构和算法领域...第二部分对链表、栈、队列、集合、哈希表、堆、图等常用数据结构进行了深入阐述;第三部分对排序、搜索数值计算、数据压缩、数据加密、图算法、几何算法等经典算法进行了精辟的分析和讲解。

    《算法精解:C语言描述》(Kyle Loudon[美] 著,肖翔、陈舸 译)

    第二部分对链表、栈、队列、集合、哈希表、堆、图等常用数据结构进行了深入阐述;第三部分对排序、搜索数值计算、数据压缩、数据加密、图算法、几何算法等经典算法进行了精辟的分析和讲解。 本书的众多特色使得它在...

    算法精解:C语言描述 chm 英文版

    第二部分对链表、栈、队列、集合、哈希表、堆、图等常用数据结构进行了深入阐述;第三部分对排序、搜索数值计算、数据压缩、数据加密、图算法、几何算法等经典算法进行了精辟的分析和讲解。 本书的众多特色使得它在...

    C语言描述(中文),完整扫描版

    《算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!《算法精解:C语言描述》共分为三部分:第一部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法...

    mastering algorithm with c

    《算法精解:C语言描述》是数据结构和算法领域的经典之作,十余年来,畅销不衰!《算法精解:C语言描述》共分为三部分:第一部分首先介绍了数据结构和算法的概念,以及使用它们的原因和意义,然后讲解了数据结构和算法...

Global site tag (gtag.js) - Google Analytics