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

上一篇我们了解了哈希表与哈希冲突的基本概念,并且展示了一种哈希冲突的解决方法,今天我们来了解第二种哈希冲突的解决方法
开散列法,又叫链地址法
开散列法:首先对关键码集合用散列函数计算出散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个无头结点的单链表连接起来,各链表的头结点存储在哈希表中,也就相当于,此时存储各个头结点的这个数组,是一个指针数组,这个数组里面存的是每一个单链表头结点指针

下面就是具体的代码实现

hash.h

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

#define HASHMAXSIZE 1000


typedef int keytype;
typedef int valtype;

typedef int(*HashFunc)(keytype key);

typedef struct HashElem{
    keytype key;
    valtype value;
    struct HashElem *next;
    struct HashElem *pre;
}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,HashElem **pre);
void HashRemove(HashTable *ht,keytype key);
void Hashdestroy(HashTable *ht);

hash.c

#include <stdio.h>
#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] = NULL;
    }
    return;
}
int HashFuncDefault(keytype key)
{
    return key % HASHMAXSIZE;
}
HashElem *creat(keytype key,valtype value)
{
    HashElem *newnode = (HashElem *)malloc(sizeof(HashElem));
    newnode->key = key;
    newnode->value = value;
    newnode->next = NULL;
    return;
}
void HashInsert(HashTable *ht,keytype key,valtype value)
{
    if(ht == NULL)
    {
        return;
    }
    int offset = HashFuncDefault(key);
    HashElem* cur = ht->data[offset];
    while(1)
    {
        while(cur != NULL)
        {
            if(cur->key = key)
            {
                return;
            }
            cur = cur->next;
        }
        HashElem *newnode = creat(key,value);
        newnode ->next = ht->data[offset];
        ht->data[offset] = newnode;
        ht->size++;
        return;
    }
    ++ht->size;
    return;
}
int HashFind(HashTable *ht,keytype key,valtype *value,HashElem **pre)
{
    if(ht == NULL)
    {
        return 0;
    }
    int offset = HashFuncDefault(key);
    HashElem* cur = ht->data[offset];
    HashElem *prev = NULL;
    while(cur != NULL)
    {
        if(cur->key == key)
        {
            *value = cur->value;
            *pre = prev;
            return 1;
        }
        prev = cur;
        cur = cur->next;
    }
    return 0;

}
void HashRemove(HashTable *ht,keytype key)
{
    if(ht == NULL)
    {
        return;
    }
    int offset = HashFuncDefault(key);
    HashElem* cur = ht->data[offset];
    HashElem *pre = NULL;
    valtype value;
    int ret = HashFind(ht,key,&value,&pre);
    if(ret == 1)
    {
        while(cur != NULL)
        {
            if(cur->value == ht->data[offset]->value)
            {
                ht->data[offset] = cur->next;
                free(cur);
                return;
            }
            else
            {
                pre->next = cur->next;
                free(cur);
                return;
            }
        }
    }
    return;
}
void Hashdestroy(HashTable *ht)
{
    if(ht == NULL)
    {
        return;
    }
    size_t i = 0;
    for(;i < HASHMAXSIZE;i++)
    {
        ht->data[i] = NULL;
    }
    return;
}
///////
//test
///////
#define HEADER printf("\n==========%s==========\n",__FUNCTION__)
void Hashprint(HashTable *ht)
{
    if(ht == NULL)
    {
        return;
    }
    size_t i = 0;
    for(;i < HASHMAXSIZE;i++)
    {
        HashElem* cur = ht->data[i];
        while(cur != NULL) {
            printf("%d [%d|%d]  ",i, cur->key, cur->value);
            cur = cur->next;
        }
    }
    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;
    HashElem *pre;
    int ret = HashFind(&hash,11,&value,&pre);
    printf("expected is 1 ,actul is %d\n",ret);
    printf("expected is 11 ,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);
    Hashprint(&hash);
    HashRemove(&hash,2);
    Hashprint(&hash);
    //valtype value;
    //int ret = HashFind(&hash,11,&value);
    //printf("expected is 1 ,actul is %d\n",ret);

}
int main()
{
    testinsert();
    testfind();
    testremove();
    return 0;
}

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

猜你喜欢

转载自blog.csdn.net/mignatian/article/details/80395531