笔者最近学习数据结构中的哈希表,并用C语言简单实现了。
此博客旨在交流心得。
这篇博客介绍的是开放地址法构造的哈希表
哈希表原理可以参考这篇文章:哈希表原理介绍
如果要参考拉链法构造的哈希表,请参考这篇文章:C语言实现哈希表(拉链法)
结构体说明
typedef struct element
{
int key; // key值 唯一不重复
int data; // data 域
}Element;
其中data域可以改为自定义的结构体(当然后续 main函数 部分代码需要做相应修改)
key 值经由哈希函数的计算会得到一个映射的地址
typedef struct table
{
Element **elm; //
int count; // 记录表中记录的数据个数
int size; // 哈希表的大小 = SIZE = 50
}Table;
注意:elm 为一个指向 Element结构体的指针数组 的指针(请好好理解),即创建了一个 Element 类型的指针数组,而 elm 指向这个数组的头地址 故声明为二级指针(指向指针的指针) 。
部分函数说明:
创建哈希表函数:
Table * init_Table()
{
Table *t = (Table*)malloc(sizeof(Table));
t->size = REMAINDER;
t->count = 0;
t->elm = (Element **)malloc(SIZE*sizeof(Element*));
/*
创建一个长度为13的指针数组,类型为Element*
并将数组头地址赋值给 elm 的二级指针
*/
int i;
for(i=0 ; i<t->size ; i++)
{
t->elm[i] = NULL; // 将数组的每个域赋空
}
return t;
}
声明 Table 类型的变量,为其开辟空间,并返回其地址。
在初始化时,对指针类型的变量要注意初始化(有的编译器会帮你赋空,有的则不会)
插入函数
void Insert(Table *t,Element * k) //将key值插入到哈希表中
{
int i;
int position;
position = hash(k->key);
for(i=1 ; t->elm[position]!=NULL && i<t->size ;i++ )
{
position=(hash(position)+i)%t->size;
}
t->elm[position] = k;
t->count += 1;
return ;
}
开放地址法的一般形式为:
其中 H(key)是哈希函数,m为表的长度
此种方法容易造成堆积。解决方法是改进哈希函数或用使用拉链法(各有优劣)。
查找函数:
int serch(Table *t, Element * k) //查找 value 并返回其所在的地址
{
int position=hash(k->key);
while(t->elm[position]->key != k->key)
{
position = hash(position+1);
if(t->elm[position]==NULL || position == hash(k->key))
/*
出现以下几种情况即判断查找失败
1.对应的 position 位置的地址为空
2.遍历整个表都没有对应的 key 值
*/
return -1;
}
return position;
}
出现以下几种情况即判断查找失败
1.对应的 position 位置的地址为空
2.遍历整个表都没有对应的 key 值
完整代码:
#include<stdio.h>
#include<stdlib.h>
#define REMAINDER 13
#define SIZE 50
typedef struct element
{
int key; // key值 唯一不重复
int data; // data 域
}Element;
typedef struct table
{
Element **elm; //
int count; // 记录表中记录的数据个数
int size; // 哈希表的大小 = SIZE = 50
}Table;
int hash(int key)
{
return key%REMAINDER;
}
Table * init_Table()
{
Table *t = (Table*)malloc(sizeof(Table));
t->size = SIZE;
t->count = 0;
t->elm = (Element **)malloc(SIZE*sizeof(Element*));
/*
创建一个长度为13的指针数组,类型为Element*
并将数组头地址赋值给 elm 的二级指针
*/
int i;
for(i=0 ; i<t->size ; i++)
{
t->elm[i] = NULL; // 将数组的每个域赋空
}
return t;
}
void Insert(Table *t,Element * k) //将key值插入到哈希表中
{
int i=0;
int position;
position = hash(k->key);
for(i=1 ; t->elm[position]!=NULL && i<t->size ;i++ )
{
position=(hash(position)+i)%t->size;
}
t->elm[position] = k;
t->count += 1;
return ;
}
int serch(Table *t, Element * k) //查找 value 并返回其所在的地址
{
int position=hash(k->key);
while(t->elm[position]->key != k->key)
{
position = hash(position+1);
if(t->elm[position]==NULL || position == hash(k->key))
/*
出现以下几种情况即判断查找失败
1.对应的 position 位置的地址为空
2.遍历整个表都没有对应的 key 值
*/
return -1;
}
return position;
}
void Print_Table(Table *t) //打印部分哈希表
{
int i;
for(i=0 ; i<13 ; i++)
{
if(t->elm[i])
printf("[%d %d] ",t->elm[i]->key , t->elm[i]->data);
else printf("NULL ");
}
printf("\n");
}
int main()
{
Table *t = init_Table();
Element a[]={{12,99},{13,98},{26,87},{14,77},{15,100},{10,59}};
int length = sizeof(a)/sizeof(Element);
int i;
for(i=0 ; i<length ; i++)
{
Insert(t,&a[i]);
}
Print_Table(t);
printf("a[3] is locat %d\n",serch(t,&a[3]));
free(t);
}
运行截图:
谢谢观看~