哈希之闭散列(线性探测/二次探测)

HashTable.h
#include <assert.h>
#include <stdio.h>
#include <malloc.h>
#include "Common.h"

//哈希表位置的状态
typedef enum State
{
    EMPTY,  //当前位置为空
    EXIST,  //当前位置有元素
    DELETE  //档期那位置被删除
}State;

typedef int DataType;
//typedef char* DataType;

//转换Int函数指针
typedef size_t(*PDT)(DataType str);

//键值对
typedef struct Elem
{
    DataType _data;
    State _state;
}Elem;

typedef enum 
{
    _IsLine,            //线性探测
    _IsNotLine      //二次探测
}IsLine;


//哈希表
typedef struct HashTable
{
    Elem * _table;      
    int _capacity;      //容量
    int _size;      //EX的个数
    int _total;         //EX/DE总共的个数
    IsLine _Dete;           //探测方法
    PDT  _setData;      //将数据转化为整型,
}HashTable;


//初始化
void HashTableInit(HashTable * ht, int capacity, IsLine _Dete, PDT setData);

//插入
void HashTableInsert(HashTable *ht, DataType data);

//删除
void HashTableDelete(HashTable *ht, DataType data);

//查找
int HashTableFind(HashTable *ht, DataType data);

//元素个数
int HashTableSize(HashTable *ht);

//判空
int HashTableEmpty(HashTable *ht);

// 销毁哈希表
void HashTableDestory(HashTable* ht);

/////////////////////////////////////////////
//辅助方法

//哈希函数
int HashFunc(HashTable* ht, int data);
//线性探测
int IsLineDete(HashTable* ht, int HashAddr);
//二次探测
int DeteTwo(HashTable * ht, int HashAddr, int i);

//测试

void TestHashData();
void TestHashStr();
HashTable.c
#include "HashTable.h"



//初始化
void HashTableInit(HashTable * ht, int capacity, IsLine Dete, PDT setData)
{
    assert(ht);

    capacity = GetCapacity(capacity);
    ht->_table = (Elem*)malloc(sizeof(Elem)*capacity);

    if (NULL == ht->_table)
        return;

    for (int i = 0; i < capacity; i++)
        ht->_table[i]._state = EMPTY;

    ht->_capacity = capacity;
    ht->_size = 0;
    ht->_total = 0;
    ht->_setData = setData;
    ht->_Dete = Dete;
}



//检测容量
int CheckCapacity(HashTable *ht)
{
    if ((ht->_total) * 10 / (ht->_capacity) > 7)
        return 1;

    return 0;
}

//交换
void _Swop(int * newht, int* oldht)
{
    int temp = *newht;
    *newht = *oldht;
    *oldht = temp;
}


void Swop(HashTable* newht, HashTable* oldht)
{
    Elem * pTemp = newht->_table;
    newht->_table = oldht->_table;
    oldht->_table = pTemp;

    _Swop(&newht->_capacity, &oldht->_capacity);
    _Swop(&newht->_size, &oldht->_size);
    _Swop(&newht->_total, &oldht->_total);

}


//扩容
void BuyCapacity(HashTable * ht)
{
    assert(ht);

    HashTable newht;
    int NewCapacity = GetCapacity(ht->_capacity);

    //初始化新的哈希表
    HashTableInit(&newht, NewCapacity, ht->_Dete, ht->_setData);

    //拷贝元素
    for (int i = 0; i < ht->_capacity; ++i)
    {
        if (ht->_table[i]._state == EXIST)
            HashTableInsert(&newht, ht->_table[i]._data);
    }

    //交换
    Swop(&newht, ht);
    HashTableDestory(&newht);
}

//插入
void HashTableInsert(HashTable *ht, DataType data)
{
    int HashAddr = 0;
    int i = 0;
    assert(ht);

    //判断负载因子,检测容量
    if (CheckCapacity(ht))
    {
        BuyCapacity(ht);
    }

    int Newdata = ht->_setData(data);
    HashAddr = HashFunc(ht, Newdata);


    while (EMPTY != ht->_table[HashAddr]._state)
    {

        if (ht->_table[HashAddr]._state == EMPTY)
        {
            if (ht->_table[HashAddr]._data == data)
                return;
        }


        if (ht->_Dete == _IsLine)
            HashAddr = IsLineDete(ht, HashAddr);
        else
            HashAddr = DeteTwo(ht, HashAddr, ++i);
    }

    //说明状态为空,可以直接插入
    ht->_table[HashAddr]._state = EXIST;
    ht->_table[HashAddr]._data = data;
    ht->_size++;
    ht->_total++;
}


//查找元素,找到返回地址
int HashTableFind(HashTable * ht, DataType data)
{
    int HashAddr = 0;
    int StartAddr = 0;
    int i = 0;
    assert(ht);

    int Newdata = ht->_setData(data);
    HashAddr = HashFunc(ht, Newdata);

    StartAddr = HashAddr;

    while (EMPTY != ht->_table[HashAddr]._state)
    {
        if (ht->_table[HashAddr]._state == EXIST)
        {
            if (ht->_table[HashAddr]._data == data)
                return HashAddr;
        }

        //线性探测
        if (ht->_Dete == _IsLine)

        {
            HashAddr = IsLineDete(ht, HashAddr);
            //找一圈都没找到,退出
            if (HashAddr == StartAddr)
                return -1;

        }
        else//二次探测
            HashAddr = DeteTwo(ht, HashAddr, ++i);

    }

    return -1;
}


//删除
void HashTableDelete(HashTable *ht, DataType data)
{
    assert(ht);
    if (-1 == HashTableFind(ht, data))
        return;

    ht->_table[HashTableFind(ht, data)]._state = DELETE;

    ht->_size--;
}


//元素个数
int HashTableSize(HashTable *ht)
{
    assert(ht);

    return ht->_size;
}

//判空
int HashTableEmpty(HashTable *ht)
{
    assert(ht);

    if (0 == ht->_size)
        return 1;

    return 0;
}


// 销毁哈希表
void HashTableDestory(HashTable* ht)
{
    assert(ht);
    free(ht->_table);
    ht->_table = NULL;
    ht->_capacity = 0;
    ht->_size = 0;
    ht->_total = 0;
}



//哈希函数
int HashFunc(HashTable* ht, int data)
{
    assert(ht);

    return data % (ht->_capacity);
}


//线性探测
int IsLineDete(HashTable* ht, int HashAddr)
{

    HashAddr = HashAddr + 1;
    if (HashAddr == ht->_capacity)//如果越界
        HashAddr = 0;

    return HashAddr;
}

//二次探测
int DeteTwo(HashTable * ht, int HashAddr, int i)
{
    HashAddr = HashAddr + 2 * i + 1;

    //越界
    if (HashAddr >= ht->_capacity)
        HashAddr %= ht->_capacity;
    return HashAddr;
}


void TestHashData()
{
    HashTable ht;
    HashTableInit(&ht, 10, _IsLine, DataToInt);
    HashTableInsert(&ht, 5);
    HashTableInsert(&ht, 9);
    HashTableInsert(&ht, 13);
    HashTableInsert(&ht, 10);
    HashTableInsert(&ht, 2);
    HashTableInsert(&ht, 13);
    HashTableInsert(&ht, 10);
    HashTableInsert(&ht, 2);
    HashTableInsert(&ht, 8);
    int size = HashTableSize(&ht);
    DataType data = ht._table[HashTableFind(&ht, 9)]._data;

    HashTableDelete(&ht, 13);//删除
    size = HashTableSize(&ht);

    HashTableDestory(&ht);
}


#if 0
void TestHashStr()
{
    HashTable ht;
    HashTableInit(&ht, 10, _IsLine, StrToInt);
    HashTableInsert(&ht, "b");
    HashTableInsert(&ht, "ca");
    HashTableInsert(&ht, "a");
    HashTableInsert(&ht, "ac");

    int size = HashTableSize(&ht);
    DataType data = ht._table[HashTableFind(&ht, "ac")]._data;

    HashTableDelete(&ht, "a");//删除
    size = HashTableSize(&ht);

    HashTableDestory(&ht);
}
#endif
Common.c
#include "Common.h"

int GetCapacity(size_t capacity)
{
    int i = 0;
    for (; i < 28; i++)
    {
        if (capacity < _PrimeList[i])
            return _PrimeList[i];
    }

    return _PrimeList[27];
}

//将字符串转换为整数
size_t StrToInt(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 DataToInt(int data)
{
    return data;
}
Common.h


#pragma once

#define  size_t unsigned long
#define  _PrimeSize 28

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
};

//用来获取容量,使每次都是素数
int GetCapacity(size_t capacity);

size_t StrToInt(const char * str);

size_t DataToInt(int data);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值