静态哈希

本文哈希函数为:除留余数法。
本文哈希冲突的处理方法:
闭散列:也叫开放地址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到表中 “下一个” 空位中去 。
二次探测:二次探查法在表中寻找“下一个”空位置的公式为:Hi+1 = Hi + (i + 1)^2,Hi =H0 + i^2 。化简后为Hi+1 = i * 2 + 1。

HashTable.h

#pragma once

#include<Windows.h>
#include<assert.h>
#include<stdio.h>

#define N 10
typedef enum{EMPTY,DELET, EXIST}State;  //三种状态,空,删除,存在

typedef int DataType;

typedef struct HTEmle
{
    DataType _data;
    int State;
}HTEmle;

typedef struct HashTable
{
    HTEmle _arr[N];
    int _size; //有效数据
    int _totle;  //总数据个数,包括无效的
    int _IsLineDetect; //是否为线性探测, 1为线性探测,2为二次探测
}HashTable, HT;

//线性探测
int IsLineDetect(HT *ht,int addr);
//二次探测
int IsLineDetect2(HT *ht, int addr);

//计算地址
int HashTableAddr(DataType data);
//哈希表的初始化
void HashTableInit(HT *ht, int IsLine);
//哈希表的插入
void HashTableInsert(HT *ht, DataType data);
//哈希表的删除
void HashTableDelete(HT *ht, DataType data);
//查找哈希表中某个元素
int HashTableFind(HT *ht, DataType data);
//计算哈希表中元素的个数
int HashTableSize(HT *ht);
//判断哈希表是否为空
int HashTableEmpty(HT *ht);

HashTable.c

#include"HashTable.h"

//线性探测
int IsLineDetect(HT *ht, int addr)
{
    //判断地址是否合法
    while (EMPTY != ht->_arr[addr].State)
    {
        //不合法,则找合法地址
        ++addr;
        if (addr >= N)
            addr = 0;
    }

    return addr;
}

//二次探测
int IsLineDetect2(HT *ht, int addr)
{
    int times = 0;
    while (EMPTY != ht->_arr[addr].State)
    {
        addr += times * 2 + 1;

        if (addr >= N)
            addr = addr % N;

        times++;
    }
    return addr;
}


//计算地址
int HashTableAddr(DataType data)
{
    return data % N;
}

//哈希表的初始化
void HashTableInit(HT *ht, int IsLine)
{
    int i = 0;
    assert(ht);

    for (; i < N; ++i)
        ht->_arr[i].State = EMPTY;

    ht->_size = 0;
    ht->_totle = 0;
    if (1 == IsLine)
        ht->_IsLineDetect = 1;
    if(2 == IsLine)
        ht->_IsLineDetect = 2;
}

//哈希表的插入
void HashTableInsert(HT *ht, DataType data)
{
    assert(ht);

    int times = 0;

    if (N == ht->_totle)
    {
        printf("该哈希表已满,无法插入\n");
        return;
    }

    //计算地址
    int addr = HashTableAddr(data);

    //如果是线性探测
    if(1 == ht->_IsLineDetect)
        addr = IsLineDetect(ht, addr);

    //如果是二次探测
    if (2 == ht->_IsLineDetect)
        addr = IsLineDetect2(ht, addr);

    //地址已合法,可以插入
    ht->_arr[addr]._data = data;
    ht->_arr[addr].State = EXIST;
    ++ht->_size;
    ++ht->_totle;
}

//哈希表的删除
void HashTableDelete(HT* ht, DataType data)
{
    int del = 0;
    assert(ht);

    if (0 == ht->_size)
    {
        printf("该哈希表为空,不能删除\n");
        return;
    }

    del = HashTableFind(ht, data);
    ht->_arr[del].State = DELET;
    ht->_size--;
}

//查找哈希表中某个元素
int HashTableFind(HT *ht, DataType data)
{
    assert(ht);
    if (0 == ht->_size)
    {
        printf("哈希表为空,则该元素不在此哈希表中\n");
        return -1;
    }

    依次遍历
    //int i = 0;
    //for (; i < N; ++i)
    //{
    //  if (EXIST == ht->_arr[i].State && data == ht->_arr[i]._data)
    //  {
    //      printf("该元素的下标为:%d\n", i);
    //      return i;
    //  }
    //}

    //printf("该元素不在此哈希表中\n");
    //return -1;

    int addr = HashTableAddr(data);
    int sign = addr; //标志初始位置

    //线性探测
    if (1 == ht->_IsLineDetect)
    {
        while (EMPTY != ht->_arr[addr].State)
        {
            //如果该位置的状态是存在,并且数据相等则找到了
            if (EXIST == ht->_arr[addr].State && data == ht->_arr[addr]._data)
            {
                printf("该数据在此哈希表中,下标为:%d\n", addr);
                return addr;
            }

            ++addr;
            if (addr >= N)
                addr = 0;

            if (sign == addr) //如果找了一遍没找到,则不存在
            {
                printf("该数据不在次哈希表中\n");
                return -1;
            }
        }

        printf("该数据不在次哈希表中\n");
        return -1;
    }

    //二次探测
    int times = 0;
    if(2 == ht->_IsLineDetect)
    {
        while (EMPTY != ht->_arr[addr].State)
        {
            //如果该位置的状态是存在,并且数据相等则找到了
            if (EXIST == ht->_arr[addr].State && data == ht->_arr[addr]._data)
            {
                printf("该数据在此哈希表中,下标为:%d\n", addr);
                return addr;
            }

            //如果该位置状态为删除,则直接退出
            if (DELETE == ht->_arr[addr].State)
            {
                printf("该数据不在次哈希表中\n");
                return -1;
            }

            addr += times * 2 + 1;
            if (addr >= N)
                addr = addr % N;
            times++;

            if (sign == addr) //如果找了一遍没找到,则不存在
            {
                printf("该数据不在次哈希表中\n");
                return -1;
            }
        }

        printf("该数据不在次哈希表中\n");
        return -1;
    }
}

//计算哈希表中元素的个数
int HashTableSize(HT *ht)
{
    assert(ht);

    return ht->_size;
}

//判断哈希表是否为空
int HashTableEmpty(HT *ht)
{
    assert(ht);

    return ht->_size;
}

test.c

#include"HashTable.h"

void test()
{
    HashTable ht;
    HashTableInit(&ht, 2);

    HashTableInsert(&ht, 13);
    HashTableInsert(&ht, 23);
    HashTableInsert(&ht, 16);
    HashTableInsert(&ht, 26);
    HashTableInsert(&ht, 19);
    HashTableInsert(&ht, 29);

    HashTableFind(&ht, 26);
    HashTableFind(&ht, 5);

    HashTableDelete(&ht, 16);
    HashTableFind(&ht, 16);

    printf("该哈希表中的元素个数为:%d\n", HashTableSize(&ht));

    int ret = HashTableEmpty(&ht);
    if (0 == ret)
        printf("该哈希表为空\n");
    else
        printf("该哈希表不为空\n");
}

int main()
{
    test();

    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值