数据结构之哈希冲突解决方法(开放地址法)

首先我们来了解一下什么叫做哈希表
在顺序搜序偶以及二叉搜索树种,元素存储位置和元素个关键码之间没有对应关系,因此在查找一个元素时,必须要经过关键码的多次比较。
而我们理想的搜索方法:可以不经过任何比较,一次直接可以从表中得到想要的元素

当向一个结构中
*插入元素时:根据待插入元素的关键码,以此桉树计算出钙元素的存储位置,并按该位置存放
*搜索元素时,根据元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素,比较,若关键码相等则说明搜索成功

这种方法就叫做哈希方法,其中用到的函数就是哈希函数,构建出来的结构称为哈希表

哈希冲突

**哈希冲突是怎么出现的呢?
我们来举个例子
对于两个数据元素的关键字K(i),K(j).有k(i) != k(j)但是通过哈希函数计算出来相同的哈希地址,这种现象就称为哈希冲突。**

下面我们就来说一种哈希冲突的解决方法:闭散列,也叫开放地址法。当发生哈希冲突时,如果哈希表未被装满,说明哈希表中必然还有空位置,那么就可以吧key存放到表中“下一个”空位中去

下面看具体的代码实现

hash.h

#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

#define HASHMAXSIZE 1000

typedef enum{
    Empty,
    Valid,
    Removed
}stat;

typedef int keytype;
typedef int valtype;

typedef int(*HashFunc)(keytype key);
typedef struct HashElem{
    keytype key;
    valtype value;
    stat stat;
}HashElem;
typedef struct HashTable{
    HashElem data[HASHMAXSIZE];
    size_t size;
    HashFunc func;
}HashTable;
void HashInit(HashTable *ht,HashFunc hash_func);
int HashFuncDefault(keytype key);
void HashInsert(HashTable *ht,keytype key,valtype value);
int HashFind(HashTable *ht,keytype key,valtype *value);
void HashRemove(HashTable *ht,keytype key);
void Hashdestroy(HashTable *ht);

hash.c

#include "hash.h"
void HashInit(HashTable *ht,HashFunc hash_func)
{
    if(ht == NULL)
    {
        return;
    }
    ht->size = 0;
    ht->func = hash_func;
    size_t i = 0;
    for(;i < HASHMAXSIZE;i++)
    {
        ht->data[i].stat = Empty;
    }
    return;
}
int HashFuncDefault(keytype key)
{
    return (key % HASHMAXSIZE);
}
void HashInsert(HashTable *ht,keytype key,valtype value)
{
    if(ht == NULL)
    {
        return;
    }
    //判断哈希表是否可以插入

    if((ht->size) >= (0.8 * HASHMAXSIZE))
    {
        return;//满了
    }
    size_t offset = HashFuncDefault(key);
    while(1)
    {
        if(ht->data[offset].stat != Valid)
        {
            ht->data[offset].stat = Valid;
            ht->data[offset].key = key;
            ht->data[offset].value = value;
            ++ht->size;
            return;
        }
        else if(ht->data[offset].stat == Valid && ht->data[offset].key == key)
        {
            return;
        }
        else
        {
            ++offset;
            if(offset >= HASHMAXSIZE)
            {
                offset = 0;
            }
        }
    }
}
int HashFind(HashTable *ht,keytype key,valtype *value)
{
    if(ht == NULL)
    {
        return 0;
    }
    int offset = HashFuncDefault(key);
    while(1)
    {
        if(ht->data[offset].stat == Valid && ht->data[offset].key == key)
        {
            *value = ht->data[offset].value;
            return 1;
        }
        else if(ht->data[offset].stat == Empty)
        {
            return 0;
        }
        else
        {
            ++offset;
            if(offset >= HASHMAXSIZE)
            {
                offset = 0;
            }

        }
    }
}
void HashRemove(HashTable *ht,keytype key)
{
    if(ht == NULL)
    {
        return;
    }
    valtype value;
    int offset = HashFuncDefault(key);
    int ret = HashFind(ht,key,&value);
    if(ret == 0)
    {
        return;
    }
    else if(ret == 1)
    {
        ht->data[offset].stat = Removed;
        --ht->size;
    }
    //else
    //{
    //    ++offset;
    //    if(offset >= HASHMAXSIZE)
    //    {
    //        offset = 0;
    //    }
    //}
}
void Hashdestroy(HashTable *ht)
{
    if(ht == NULL)
    {
        return;
    }
    ht->size = 0;
    size_t i = 0;
    for(;i < HASHMAXSIZE;i++)
    {
        ht->data[i].stat = Empty;
    }
    return;
}

/////////
//test
/////////
#define HEADER printf("\n==========%s==========\n",__FUNCTION__);
void Hashprint(HashTable *ht)
{
    if(ht == 0)
    {
        return;
    }
    size_t i = 0;
    for(;i < HASHMAXSIZE;i++)
    {
        if(ht->data[i].stat != Valid)
        {
            continue;
        }
        printf("%d:%d\n",ht->data[i].key,ht->data[i].value);
    }
    printf("\n");
}
void testinsert()
{
    HEADER;
    HashTable hash;
    HashInit(&hash,HashFuncDefault);
    HashInsert(&hash,1,1);
    HashInsert(&hash,2,2);
    HashInsert(&hash,2,10);
    HashInsert(&hash,11,11);
    HashInsert(&hash,12,12);
    Hashprint(&hash);
}
void testfind()
{
    HEADER;
    HashTable hash;
    HashInit(&hash,HashFuncDefault);
    HashInsert(&hash,1,1);
    HashInsert(&hash,2,2);
    HashInsert(&hash,2,10);
    HashInsert(&hash,11,11);
    HashInsert(&hash,12,12);
    Hashprint(&hash);
    valtype value;
    int ret = HashFind(&hash,2,&value);
    printf("查找key为2的元素\n");
    printf("excpted ret is 1,actul is %d\n",ret);
    printf("excpted value is 2,actul is %d\n",value);

}
void testremove()
{
    HEADER;
    HashTable hash;
    HashInit(&hash,HashFuncDefault);
    HashInsert(&hash,1,1);
    HashInsert(&hash,2,2);
    HashInsert(&hash,2,10);
    HashInsert(&hash,11,11);
    HashInsert(&hash,12,12);
    HashInsert(&hash,1002,1002);
    Hashprint(&hash);
    valtype value;
    printf("删除key为2的元素\n");
    HashRemove(&hash,2);
    int ret = HashFind(&hash,1002,&value);
    printf("查找key为1002的元素\n");
    printf("excpted ret is 1,actul is %d\n",ret);
    printf("excpted value is 1002,actul is %d\n",value);
}
int main()
{
    testinsert();
    testfind();
    testremove();
    return 0;
}

下面就是测试结果
这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章