11、开地址哈希表

来源:互联网 发布:mac必备软件知乎 编辑:程序博客网 时间:2024/06/06 02:46

开地址哈希表本质上是一个数组,数组的优势在于可以使用下标随机访问成员。**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;}