哈希表之闭散列

了解哈希的基本概念可以看这里:搜索结构之哈希

闭散列代码:闭散列

#pragma once
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include"Comm.h"

typedef int DataType;

typedef enum State
{
    EMPTY,  //当前位置为空
    EXIST,  //当前位置有元素
    DELETE  //当前位置被删除
}State;

//元素
typedef struct Elem
{
    DataType _data;
    State _state;
}Elem;

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

typedef size_t(*PDT)(DataType str);

typedef struct HashTable
{
    Elem* _table;
    int _capacity;  //容量
    int _size;      //存在位元素个数
    int _total;     //存在位和删除位总共的个数
    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 HashTableSize(HashTable* ht);
int HashTableEmpty(HashTable* ht);
void HashTableDestroy(HashTable* ht);

int HashFind(HashTable* ht, DataType data);
#include"Hash.h"

//哈希函数
DataType HashFunc(HashTable* ht, DataType data)
{
    assert(ht);
    return data % ht->_capacity;
}

//检测容量
int CheckCapacity(HashTable* ht)
{
    assert(ht);

    if ((ht->_total * 10) / (ht->_capacity) > 7)
        return 1;

    return 0;
}

//线性探测
int IsLineDete(HashTable* ht, DataType 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 = HashAddr%ht->_capacity;

    return HashAddr;
}

void _Swap(int* newht, int* ht)
{
    int temp = *newht;
    *newht = *ht;
    *ht = temp;
}

//交换哈希表
void Swap(HashTable* newht, HashTable* ht)
{
    assert(newht);
    assert(ht);

    Elem* pTemp = newht->_table;
    newht->_table = ht->_table;
    ht->_table = pTemp;

    _Swap(&newht->_capacity, &ht->_capacity);
    _Swap(&newht->_size, &ht->_size);
    _Swap(&newht->_total, &ht->_total);
}

void BuyCapacity(HashTable* ht)
{
    assert(ht);

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

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

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

    //交换
    Swap(&newht, ht);
    HashTableDestroy(&newht);
}

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

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

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

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

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

    //判断负载因子
    if (CheckCapacity(ht))
    {
        BuyCapacity(ht);
    }

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

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

        //线性探测
        if (ht->_Dete == _IsLine)
            HashAddr = IsLineDete(ht, HashAddr);
        else
            HashAddr = DeteTwo(ht, HashAddr, ++i);
    }

    //状态为空,直接插入
    ht->_table[HashAddr]._data = data;
    ht->_table[HashAddr]._state = EXIST;
    ++ht->_size;
    ++ht->_total;
}
void HashTableDelete(HashTable* ht, DataType data)
{
    assert(ht);
    int ret = HashFind(ht, data);
    if (ret != -1)
    {
        ht->_table[ret]._state = DELETE;
        --ht->_size;
    }
}

int HashTableSize(HashTable* ht)
{
    assert(ht);

    return ht->_size;
}

int HashTableEmpty(HashTable* ht)
{
    assert(ht);

    return 0 == ht->_size;
}

int HashFind(HashTable* ht, DataType data)
{
    assert(ht);
    int starAddr = 0;
    DataType HashAddr = 0;
    int i = 0;

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

    starAddr = HashAddr;

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

        //线性探测
        if (ht->_Dete == _IsLine)
        {
            HashAddr = IsLineDete(ht, HashAddr);
            //未找到
            if (HashAddr == starAddr)
                return -1;
        }
        else
            HashAddr = DeteTwo(ht, HashAddr, ++i);
    }

    return -1;
}

void HashTableDestroy(HashTable* ht)
{
    assert(ht);
    free(ht->_table);
    ht->_capacity = 0;
    ht->_size = 0;
    ht->_total = 0;
    ht->_table = NULL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值