哈希之开散列-哈希桶

本文详细解析了哈希桶与开散列的概念,通过头文件HashBucket.h和common.h,以及源文件HashBucket.c和common.c,阐述了这两种数据结构在哈希表实现中的应用和优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

头文件

  • HashBucket.h
#pragma once
#ifndef _HASHBUCKET_H_
#define _HASHBUCKET_H_

#define size_t unsigned long

typedef int K;

//typedef char* K;
typedef char* V;




typedef size_t(*PHF)(K key);

typedef struct Pair
{
    K _key;
    V _value;
}Pair;

typedef struct Node
{
    struct Node* _pNext;
    Pair _data;
}Node, *PNode;


typedef struct HashTable
{
    PNode* _table;
    unsigned long _capacity;
    unsigned long _size;
    PHF _DateToInt;
}HT;


void InitHashBucket(HT* ht, int capacity, PHF dataToInt);
int InsertHashBucketUnique(HT* ht, K key, V v);
int DeleteHashBucketUnique(HT* ht, K key);

void InsertHashBucketEqual(HT* ht, K key, V v);
int DeleteHashBucketEqual(HT* ht, K key);
PNode FindHashBucket(HT* ht, K key);
int ChechCapacity(HT* ht);
void DestroyHashBucket(HT* ht);
void ExtendCapacity(HT* ht);

int HashFunc(HT* ht, K key);
PNode BuyNode(K key, V value);
void PrintHashBucket(HT* ht);

#endif // !_HASHBUCKET_H_

  • common.h
#pragma once

#ifndef _COMMON_H_
#define _COMMON_H_

#include"HashBucket.h"

#pragma once


#define _PrimeSize  28
#define size_t unsigned long

static const unsigned long _PrimeList[_PrimeSize] =
{
    53ul, 97ul, 193ul, 389ul, 769ul,
    1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
    49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
    1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
    50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
    1610612741ul, 3221225473ul, 4294967291ul
};


unsigned long GetPrimeNumber(int Capacity);
static size_t BKDRHash(const char * str);

size_t IntToInt(K key);
size_t StrToInt(K key);

#endif // !_COMMON_H_

源文件

  • HashBucket.c
#include<stdio.h>
#include<assert.h>
#include"HashBucket.h"
#include"common.h"

#pragma warning(disable:4996); 

//初始化
void InitHashBucket(HT* ht, int capacity, PHF dataToInt)
{

    assert(ht);

    ht->_capacity = capacity;

    ht->_DateToInt = dataToInt;

    ht->_size = 0;

    ht->_table = (PNode*)malloc(sizeof(PNode) * ht->_capacity);

    for (int i = 0; i < ht->_capacity; i++)
    {
        ht->_table[i] = NULL;
    }
}

//插入唯一
int InsertHashBucketUnique(HT* ht, K key, V v)
{
    assert(ht);

    if (ChechCapacity(ht))
    {
        ExtendCapacity(ht);
    }

    size_t BucketNo = HashFunc(ht, key);

    PNode pCur = ht->_table[BucketNo];

    while (pCur)
    {
        if (pCur->_data._key == key)
            return 0;
        else
            pCur = pCur->_pNext;
    }

    pCur = BuyNode(key, v);

    pCur->_pNext = ht->_table[BucketNo];
    ht->_table[BucketNo] = pCur;
    ht->_size++;
    return 1;
}

//删除唯一
int DeleteHashBucketUnique(HT* ht, K key)
{
    assert(ht);

    size_t BucketNo = HashFunc(ht, key);

    PNode pCur = ht->_table[BucketNo];
    PNode pPre = ht->_table[BucketNo];

    if (ht->_table[BucketNo] && ht->_table[BucketNo]->_data._key == key)
    {
        ht->_table[BucketNo]= pCur->_pNext;
        ht->_size--;
        free(pCur);
        return 1;
    }

    pCur = ht->_table[BucketNo]->_pNext;
    pPre = ht->_table[BucketNo];

    while (pCur)
    {
        if (pCur->_data._key == key)
            break;
        else
        {
            pPre = pCur;
            pCur = pCur->_pNext;
        }

    }
    if (NULL == pCur)
        return 0;

    pPre->_pNext = pCur->_pNext;
    free(pCur);
    ht->_size--;
    return 1;


}

//插入相同的
void InsertHashBucketEqual(HT* ht, K key, V v)
{
    assert(ht);

    if (ChechCapacity(ht))
    {
        ExtendCapacity(ht);
    }

    size_t BucketNo = HashFunc(ht, key);

    PNode pCur = BuyNode(key, v);

    pCur->_pNext = ht->_table[BucketNo];
    ht->_table[BucketNo] = pCur;

    ht->_size++;

}
//删除相同的
int DeleteHashBucketEqual(HT* ht, K key)
{
    assert(ht);

    int flag = ht->_size;

    size_t BucketNo = HashFunc(ht, key);

    PNode pCur = ht->_table[BucketNo];
    PNode pPre = ht->_table[BucketNo];

    while(ht->_table[BucketNo] && ht->_table[BucketNo]->_data._key == key)
    {
        ht->_table[BucketNo] = pCur->_pNext;
        ht->_size--;
        free(pCur);

        pCur = ht->_table[BucketNo];
    }
    if (pCur)
        pCur = ht->_table[BucketNo]->_pNext;

    while (pCur)
    {

         if (pCur->_data._key == key)
        {
            pPre->_pNext = pCur->_pNext;
            free(pCur);
            pCur = pPre->_pNext;
            ht->_size--;
        }
        else
        {
            pPre = pCur;
            pCur = pCur->_pNext;
        }
    }
    return flag != ht->_size ;
}
//搜索
PNode FindHashBucket(HT* ht, K key)
{
    assert(ht);

    int flag = ht->_size;

    size_t BucketNo = HashFunc(ht, key);

    PNode pCur = ht->_table[BucketNo];

    while (pCur)
    {
        if (pCur->_data._key == key)
        {
            break;
        }
        else
        {
            pCur = pCur->_pNext;
        }
    }
    return pCur;
}

//检查空间
int ChechCapacity(HT* ht)
{
    return ht->_capacity == ht->_size;
}

//销毁哈希桶
void DestroyHashBucket(HT* ht)
{
    assert(ht);

    PNode pDel;

    int BucketInd = 0;
    for (; BucketInd < ht->_capacity; BucketInd++)
    {
        pDel = ht->_table[BucketInd];

        while (pDel)
        {
            ht->_table[BucketInd] = pDel->_pNext;
            free(pDel);
            pDel = ht->_table[BucketInd];
        }
    }
    free(ht->_table);

    ht->_size = 0;

    ht->_capacity = 0;
}

//哈希函数
int HashFunc(HT* ht, K key)
{

    assert(ht);

    return ht->_DateToInt(key) % ht->_capacity;

}
//创建结点
PNode BuyNode(K key, V value)
{
    PNode pNewNode = (PNode)malloc(sizeof(Node));
    pNewNode->_data._key = key;
    pNewNode->_data._value = value;
    pNewNode->_pNext = NULL;
    return pNewNode;
}
//打印
void PrintHashBucket(HT* ht)
{
    assert(ht);

    PNode pCur;

    int BucketInd = 0;
    for (; BucketInd < ht->_capacity; BucketInd++)
    {
        printf("Hash Bucket No.%ld:", BucketInd);
        pCur = ht->_table[BucketInd];
        while (pCur)
        {
            printf("<%s, %s>\t", pCur->_data._key, pCur->_data._value);
            pCur = pCur->_pNext;
        }
        printf("\n");
    }
}

//打印
void PrintHashBucket_int(HT* ht)
{
    assert(ht);

    PNode pCur;

    int BucketInd = 0;
    for (; BucketInd < ht->_capacity; BucketInd++)
    {
        printf("Hash Bucket No.%ld:", BucketInd);
        pCur = ht->_table[BucketInd];
        while (pCur)
        {
            printf("<%d, %s>\t", pCur->_data._key, pCur->_data._value);
            pCur = pCur->_pNext;
        }
        printf("\n");
    }
}
//扩容
void ExtendCapacity(HT* ht)
{
    size_t NewCapacity = ht->_capacity + 5;

    PNode* pNewNode = (PNode*)malloc(sizeof(PNode) * NewCapacity);//申请新的空间

    for (int i = 0; i < NewCapacity; i++)
    {
        pNewNode[i] = NULL;
    }

    PNode pCur;

    size_t BucketInd = 0;

    for (; BucketInd < ht->_capacity; BucketInd++)//开始交换结点
    {
        if (ht->_table[BucketInd])
        {
            size_t BucketNo = 0;
            pCur = ht->_table[BucketInd];
            while (pCur)
            {
                //BucketNo = HashFunc(ht, pCur->_data._key);
                BucketNo = ht->_DateToInt(pCur->_data._key) % NewCapacity;

                ht->_table[BucketInd] = pCur->_pNext;

                pCur->_pNext = pNewNode[BucketNo];
                pNewNode[BucketNo] = pCur;

                pCur = ht->_table[BucketInd];
            }
        }
    }

    free(ht->_table);

    ht->_table = pNewNode;

    ht->_capacity = NewCapacity;
}

/////////////////////////////////////////////////-----测试
void test_str()
{
    HT ht;

    InitHashBucket(&ht, 5, StrToInt);

    InsertHashBucketUnique(&ht, "ac", "鹌鹑");
    InsertHashBucketUnique(&ht, "rg", "如果");
    InsertHashBucketUnique(&ht, "lm", "里面");
    InsertHashBucketUnique(&ht, "et", "儿童");
    InsertHashBucketUnique(&ht, "ht", "合同");
    PrintHashBucket(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketUnique(&ht, "pn", "陪你");
    InsertHashBucketUnique(&ht, "yn", "一年");
    InsertHashBucketUnique(&ht, "qn", "去年");
    InsertHashBucketUnique(&ht, "ynddd", "一年d");
    InsertHashBucketUnique(&ht, "qnqqd", "去年qdq");
    PrintHashBucket(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketUnique(&ht, "asdpn", "驴妈陪你");
    InsertHashBucketUnique(&ht, "asdyn", "的一年");
    InsertHashBucketUnique(&ht, "aedsdqn", "大去年");
    InsertHashBucketUnique(&ht, "fegynddd", "就看到一年d");
    InsertHashBucketUnique(&ht, "gefqnqqd", "按时去年qdq");
    PrintHashBucket(&ht);
    printf("---------------------------------------\n");
}

void FindTest(HT* ht, size_t key)
{
    PNode pNew = FindHashBucket(ht, key);
    printf("key = %ld: ", key);
    if (pNew)
    {
        printf("<%ld,%s>\n", pNew->_data._key, pNew->_data._value);
    }
    printf("\n");
}

void test_int()
{
    HT ht;

    InitHashBucket(&ht, 5, IntToInt);

    //插入,扩容测试
    InsertHashBucketUnique(&ht, 1, "鹌鹑");//1
    InsertHashBucketUnique(&ht, 4, "如果");//4
    InsertHashBucketUnique(&ht, 13, "里面");//3
    InsertHashBucketUnique(&ht, 25, "儿童");//0
    InsertHashBucketUnique(&ht, 103, "合同");//3
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketUnique(&ht, 32, "陪你");//2
    InsertHashBucketUnique(&ht, 19, "一年");//9
    InsertHashBucketUnique(&ht, 67, "去年");//7
    InsertHashBucketUnique(&ht, 28, "一年d");//8
    InsertHashBucketUnique(&ht, 97, "去年qdq");//7
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketUnique(&ht, 15, "驴妈陪你");//0
    InsertHashBucketUnique(&ht, 94, "的一年");//4
    InsertHashBucketUnique(&ht, 252, "大去年");//10
    InsertHashBucketUnique(&ht, 29, "就看到一年d");//14
    InsertHashBucketUnique(&ht, 27, "按时去年qdq");//13
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketUnique(&ht, 27, "按时去年qdq");//13
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    DeleteHashBucketUnique(&ht, 15);
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    InsertHashBucketEqual(&ht, 27, "aaaaaaaa");
    InsertHashBucketEqual(&ht, 27, "aaaaaaaa");
    InsertHashBucketEqual(&ht, 27, "aaaaaaaa");
    InsertHashBucketEqual(&ht, 27, "aaaaaaaa");
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    DeleteHashBucketEqual(&ht, 27);
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");

    size_t k = 1;
    while (  k)
    {
        scanf("%ld",&k);
        FindTest(&ht, k);
    }

    DestroyHashBucket(&ht);
    PrintHashBucket_int(&ht);
    printf("---------------------------------------\n");
}

int  main()
{
    //test_str();
    test_int();

    system("pause");
    return 0;

}
  • common.c
#include"common.h"

size_t GetPrimeNumber(int Capacity)//得到最接近的质数
{
    for (int i = 0; i < _PrimeSize; i++)
    {
        if (_PrimeList[i] > Capacity)
            return _PrimeList[i];
    }
    return _PrimeList[_PrimeSize];
}

static size_t BKDRHash(const char * str)//字符串哈希算法
{
    unsigned int seed = 131; // 31 131 1313 13131 131313
    unsigned int hash = 0;
    while (*str)
    {
        hash = hash * seed + (*str++);
    }
    return (hash & 0x7FFFFFFF);
}

size_t IntToInt(K key)
{
    return key;
}
size_t StrToInt(K key)
{
    return BKDRHash(key);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值