散列 - 分离链接法

散列 - 分离链接法

通过某种特定的函数/算法(称为散列函数/算法)将要检索的项与用来检索的索引(称为散列,或者散列值)关联起来,生成一种便于搜索的数据结构(称为散列表)。也译为散列。
这里写图片描述

这里写图片描述

我们需要将输入的字符串进行转换, 将其转换成数字, 在插入保存的数, 当然, 也可能会存在不同字符串对应相同的数字, 这时, 为了保证不冲突, 我们将字符串对应相同的数字用链表表示, 用链表保存我们要存储的东西. 字符串是钥匙, 只能打开对应的箱子, 而箱子里也有其他物品, 我们在搜索箱子就能找到我们想要的

//HashTbld代表的是钥匙, 而ListNode代表的是物品, 因为有多个钥匙, 所以HashTbl我们用数组链表表示
struct ListNode;
struct HashTbl;
typedef struct ListNode *Position;
typedef struct HashTbl *HashTabl;
const int N = 10;

struct ListNode
{
    char *ch;
    Position next;
};

struct HashTbl
{
    int The_SIZE;
    Position *The_ListNode;
};

字符串转换


unsigned int Hash(char *key, int SIZE)
{
    unsigned int HashSIZE = 0;

    while (*key != '\0')
        HashSIZE = (HashSIZE << 5) + *key++;

    return HashSIZE % SIZE;
}

初始化钥匙跟箱子, 跟链表初始化一样的, 差别只是在于对HashTbl的初始化是数组


void Creat(int SIZE, HashTabl &H)
{
    //初始化HashTbl
    H = (HashTabl)malloc(sizeof(struct HashTbl));
    if (H == NULL)
        exit(0);

    H->The_SIZE = SIZE;

    //初始化HashTbl的数组, 即初始化钥匙
    H->The_ListNode = (Position *)malloc(sizeof(Position) * SIZE);
    if (H->The_ListNode == NULL)
        exit(0);

    for (int i = 0; i < SIZE; i++)
    {
        //对每个数组的链表初始化, 也就是初始化箱子
        H->The_ListNode[i] = (Position)malloc(sizeof(struct ListNode));
        if (H->The_ListNode[i] == NULL)
            exit(0);
        H->The_ListNode[i]->next = NULL;
    }
}

对于初入与删除, 就像链表的插入跟删除一样, 唯一不同的是, 插入(放物品)我们需要计算他的位置, 需要用Hash计算来找到位置(找到他的钥匙, 才能确定放的对应的宝箱), 找到用链表插入的方式, 将他插入链表即可, 删除也一样

void Inset(HashTabl H, char *key)
{
    if (!Find(H, key))
    {
        Position L, temp;
        temp = (Position)malloc(sizeof(struct ListNode));
        if (temp == NULL)
            exit(0);

        //找到对应的钥匙
        L = H->The_ListNode[Hash(key, H->The_SIZE)];

        //插入, 放入宝箱中
        temp->ch = key;
        temp->next = L->next;
        L->next = temp;
    }
}
//删除
void Dele(HashTabl H, char *key)
{
    if (Find(H, key))
    {
        //找到钥匙
        Position P, L;
        P = H->The_ListNode[Hash(key, H->The_SIZE)];

        //宝箱中查找我们要的物品, 即搜寻链表
        while (P->next != NULL && P->next->ch != key)
            P = P->next;

        L = P->next;
        P->next = L->next;
    }

}

源代码


#include <stdio.h>
#include <stdlib.h>

struct ListNode;
struct HashTbl;
typedef struct ListNode *Position;
typedef struct HashTbl *HashTabl;
const int N = 10;

struct ListNode
{
    char *ch;
    Position next;
};

struct HashTbl
{
    int The_SIZE;
    Position *The_ListNode;
};

//初始化钥匙跟箱子
void Creat(int SIZE, HashTabl &H)
{
    //初始化HashTbl
    H = (HashTabl)malloc(sizeof(struct HashTbl));
    if (H == NULL)
        exit(0);

    H->The_SIZE = SIZE;

    //初始化HashTbl的数组, 即初始化钥匙
    H->The_ListNode = (Position *)malloc(sizeof(Position) * SIZE);
    if (H->The_ListNode == NULL)
        exit(0);

    for (int i = 0; i < SIZE; i++)
    {
        //对每个数组的链表初始化, 也就是初始化箱子
        H->The_ListNode[i] = (Position)malloc(sizeof(struct ListNode));
        if (H->The_ListNode[i] == NULL)
            exit(0);
        H->The_ListNode[i]->next = NULL;
    }
}

//字符串转换
unsigned int Hash(char *key, int SIZE)
{
    unsigned int HashSIZE = 0;

    while (*key != '\0')
        HashSIZE = (HashSIZE << 5) + *key++;

    return HashSIZE % SIZE;
}


Position Find(HashTabl H, char *key)
{
    Position P;
    P = H->The_ListNode[Hash(key, H->The_SIZE)];
    while (P != NULL && P->ch != key)
        P = P->next;

    return P;
}

//对于初入与删除, 就像链表的插入跟删除一样, 唯一不同的是, 插入(放物品)我们需要计算他的位置, 
//需要用Hash计算来找到位置(找到他的钥匙, 才能确定放的对应的宝箱), 找到用链表插入的方式, 
//将他插入链表即可, 删除也一样
void Inset(HashTabl H, char *key)
{
    if (!Find(H, key))
    {
        Position L, temp;
        temp = (Position)malloc(sizeof(struct ListNode));
        if (temp == NULL)
            exit(0);

        //找到对应的钥匙
        L = H->The_ListNode[Hash(key, H->The_SIZE)];

        //插入, 放入宝箱中
        temp->ch = key;
        temp->next = L->next;
        L->next = temp;
    }
}

//删除
void Dele(HashTabl H, char *key)
{
    if (Find(H, key))
    {
        //找到钥匙
        Position P, L;
        P = H->The_ListNode[Hash(key, H->The_SIZE)];

        //宝箱中查找我们要的物品, 即搜寻链表
        while (P->next != NULL && P->next->ch != key)
            P = P->next;

        L = P->next;
        P->next = L->next;
    }

}


int main()
{
    HashTabl H = NULL;
    int SIZE = 10, i;
    Creat(SIZE, H);
    char key[10];
    for (i = 0; i < SIZE; i++)
    {
        scanf("%s", key);
        Inset(H, key);
    }
    scanf("%s", key);
    Dele(H, key);

    scanf("%s", key);
    Position t = Find(H, key);
    printf("%s", t->ch);

    system("pause");
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值