我们要知道哈希存储的原理,它类似于Python的字典,每个元素中都含有一个键和一个值,每个键唯一对应其代表的值,下面之所以在元素中有next指针的存在是因为可能会在同一个地址中存储多个值,
所以将每个元素都横向在组成一个单链条,这样就可以完美解决冲突问题。
#include <stdio.h>
#include <malloc.h>
typedef struct Node //第一步:创建于元素类型
{
int key;
int value;
struct Node *next;
}HashNode;
//这个类型中有key值和value值,以及一个指针next。将其取名为HashNode
typedef struct op //创建一个数组指针类型
{
HashNode **bucket;
int size;
}HashTable;
//这个类型中有一个二级指针(调用了HashNode类型)bucket和一个size值。将其取名为HashTable
void create_list(HashTable *table,int size)
//第三步创建数组:首先要确定这个数组有多大传入size值,和一个数组指针table指向数组的首地址
{
table->size = size;
//数组中的元素类型都是HashNode类型,那么只要确定这个数组中有多少个HashNode类型的空间
table->bucket = (HashNode**)malloc(size * sizeof(HashNode*));
//有size个HashNode类型的空间
for(int i = 0; i < table->size ; i++)
{
table->bucket[i] = NULL;
}
//数组创建好了之后要记得初始化,此处为初始化数组
}
int add(HashTable *table,int key,int value) //第四步增加一个元素
//既然要增加元素,少不了key和value,是在链表中增加元素,那就少不了链表的头指针
{
HashNode *p = (HashNode *)malloc(sizeof(HashNode));
//要去存元素,那么这个元素就要用HashNode类型定义的 设为(*p)
p->key=key;
p->next=NULL;
p->value=value;
//把key和value值赋给p,p->next必须要赋NULL,不然就会随机指向别的地方。
int index = key % table->size;
//这里是找到(要存入位置)的元组下标 ,table->bucket[index]指的就是(要存入位置)的链条的头节点
HashNode *q = NULL;
//因为再存入的时候会遇到一种情况,即这个位置后面跟着多个元素,也就是这个链条它里面有多个元素,但是要存入元素就必须在链条的最后存入,所以就需要一个HashNode类型的指针(*q)对这个链条进行遍历,使得q->next=NULL ,这样直接让q-next->p就ok了,就存入进去了。
if(table->bucket[index] == NULL)
{
table->bucket[index] = p;
}
//如果链条的第一个值为NULL,那直接就把p赋给table->bucket[index]
else
{
q = table->bucket[index];
while(q->next != NULL)
{
q = q->next;
}
q->next = p; //这个循环在定义q的时候已经解释了,不懂得回上文看一下。
}
return 1; //到这里在链表中增加一个元素就结束了 因为函数是int类型所以最后要返回值
}
int get(HashTable *table,int key) //第五步取值
//因为哈希存储类似于Python的字典,有了key就能把value通过算法求出来
//此时想要取出value,那么就要先传入key,又因为元素在数组中,所以也要传入数组指针,
(*table)
{
int index = key % table->size; //找到下标
//又因为一个元素链条可以存放多个key和value,每个key不同,所代表的value也不同。如果我就想取链条中间的那个value怎么办? 那么就要用到HashNode类型的指针(p)对链条进行遍历了,在遍历时,会出现要寻找的key值不存在,那么就加个条件使p不会无限遍历。同时还要让p->key=key;那么这个条件就是(p != NULL && p->key != key)
HashNode *p = NULL;
p = table->bucket[index];
while(p != NULL && p->key != key)
{
p = p->next;
}
if(p == NULL)//如果key不存在就返回-1
{
return -1;
}
return p->value;//如果key存在,就直接返回其所代表的值
}
int main()
{
HashTable table;//这里博主暂时不懂为什么这样写,弄明白了自然会更新并且说明其原因
create_list(&table,10); //这里要想到指针指的是地址
add(&table,3,5418);
printf("%4d",get(&table,3));
}
如果您觉得解释的还算合理的话请关注或点个赞鼓励一下博主吧! (●'◡'●)