算法精解----11、开地址哈希表

开地址哈希表本质上是一个数组,数组的优势在于可以使用下标随机访问成员。**data表示存着指针的数组。开地址哈希表数组每个元素是存入的具体节点。链式哈希表数组的每个元素是桶。
链式哈希表中,每个元素放在桶中,桶的深度可扩展所以元素m不限。开地址哈希表把元素存放在表本身,如果顺序插入则随着元素的增多效率越低。每个表有其编号,根据哈希函数决定插入方式,可以更早找到空位,可以提升效率。

链式哈希表的最坏情况是所有元素散列在同一个桶中。开地址哈希表最坏情况是表全满而且要查找的元素不在表中。

//开地址哈希表就是把元素直接存于数组中,根据值确定开始查找空位的位置
typedef  struct OHTbl_
{
    int positions;//数组长度
    int size;//已经放进数的数组元素个数
    void **table;//数组
    void *vacated;//指向曾经删除过元素的地址
    int (*h1)(const void *key);
    int (*h2)(const void *key);
    int (*match)(const void *key, const void *key2);
    void (*destroy)(void *data);
}OHTbl;

1、初始化

int ohtbl_init(OHTBL *htbl, int position, int (*h1)(const void *key), int (*h2)(const void *key), int (*match)(const void *key, const void *key2),void (*destroy)(void *data))  
{
    int i;
    if((htbl->table =(void **)malloc(positions * sizeof(void *))) == NULL)
        return -1;
    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;   
}

2、释放哈希表

void ohtbl_destroy(OHTBL *htbl)
{
    int i;
    if(htbl->destroy != NULL)
    {
        for(i = 0; i < htbl->position; i++)
        {
            //已经删除的地方不再删除
            if(htbl->table[i] != NULL && htbl->table[i] != vacated)
                htbl->destroy(htbl->table[i]);
        }
    }

    free(htbl->table);
    memset(htbl, 0, sizeof(OHTBL));
    return;
}       

3、插入元素

int ohtbl_insert(OHTBL *htbl, const void *data)
{
    void *temp;
    int position, i;
    //是否已经满了
    if(htbl->size == htbl->position)
        return -1;
    temp = (void *)data;

    //数据已经存在
    if(ohtbl_lookup(htbl, &temp) == 0)
        return 1;
    for(i = 0; i < htbl->position; i++)
    {
        position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->position;
        //该位置无元素
        if(htbl->table[position] == null || htbl->table[position] == htbl->vacated)
        {
            htbl->table[position] = (void *)data;
            htbl->size++;
            return 0;
        }
    }
    return -1;
}

4、删除元素

int ohtbl_remove(OHTBL *htbl, const void **data)
{
    int position, i;
    for(i = 0; i < htbl->position; i++)
    {
        position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->position;
        if(htbl->table[position] == null)
        {
            return -1;
        }
        else if(htbl->table[position] == htbl->vacated)
        {
            continue;
        }
        else if(htbl->match(htbl->table[position], *data))
        {
            //只是数组,无链表不需要释放内存
            *data = htbl->position;
            htbl->table[position] = htbl->vacated;
            htbl->size--;
            return 0;
        }
    }
    return -1;
}
//判断元素是否存在表中
int ohtbl_lookup(OHTBL *htbl, const void **data)
{
    int position, i;
    for(i = 0; i < htbl->position; i++)
    {
        position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->position;
        if(htbl->table[position] == null)
        {
            return -1;
        }
        else if(htbl->match(htbl->table[position], *data))
        {
            *data = t=htbl->position;
            return 0;
        }
    }
    return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值