一、学习要点:
1.哈希表是一个很神奇的东西,即解决了数组的增删的繁琐,也解决了链表的查找问题;
2.哈希表的哈希函数;
3.哈希表的冲突问题解决;什么叫做闭散列,什么叫做开散列;闭,严重遵守哈希内涵。开,有点开放的意味,解决冲突靠链表,有点变味的哈希;
二、相关数据结构解读:
1.构造一种存储结构,通过某种函数使元素的存储位置与它的关键码之间建立一种一一映射的关系,那么在查找时通过该函数可以很快找到该元素;
2.哈希函数是用来得到给定key值在哈希表中的存储位置的;
3.哈希函数也并不是固定的,可以自己根据情况来定,一般常用常见的有直接定制法,除留余数法,平方取中法,折叠法,随机数法,数学分析法。
4.当向该结构插入元素时,存在根据关键码和哈希函数来计算出位置,当搜索时,也是根据给定的码值,用哈希函数进行转化得到存储位置进行查找,将得到位置的值和要查找的关键码进行比对,若关键码相同,则搜索成功,否则根据解决冲突的方法,继续查找;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define OK 1;
#define ERROR 0;
#define SUCCESS 1
#define UNSUCCESS 0
#define Status int
#define HASHSIZE 12 //定义散列表长为数组的长度
#define NULLKEY -32768
typedef struct
{
int *elem; //数据元素存储基址,动态分配数组
int count; //当前数据元素个数
}HashTable;
int m = 0; //散列表表长,全局变量
//初始化散列表
Status InitHashTable(HashTable *H)
{
int i;
m = HASHSIZE;
H->count = m;
H->elem = (int *)malloc(m*sizeof(int));
for(i = 0; i < m;i ++)
H->elem[i] = NULLKEY;
return OK;
}
//散列函数
int Hash(int key)
{
return key % m; //除留余法
}
// 输入关键字进散列表
void InsertHash(HashTable *H,int key)
{
int addr = Hash(key);//求散列地址
while(H->elem[addr] != NULLKEY) //如果不为空,则冲突
addr = (addr + 1) % m; //开放定址法的线性探测
H->elem[addr] = key; //直到有空位后插入关键字
}
//散列表查找关键字
Status SearchHash(HashTable H,int key,int *addr)
{
*addr = Hash(key); //求散列地址
while(H.elem[*addr] != key) //如果不为空,则冲突
{
*addr = (*addr + 1) % m; //开放地址法的线性探测
if(H.elem[*addr] == NULLKEY || *addr == Hash(key))
{//如果循环回到原点
return UNSUCCESS; //则说明关键字不存在
}
}
return *addr; //返回查找到地址
}
int main()
{
int a[12] = {12,67,56,16,25,37,22,29,15,47,48,34};
HashTable H;
InitHashTable(&H);
for(int i = 0;i < m; i++)
InsertHash(&H,a[i]);
printf("---插入之后的哈希表为:-------\n");
for(int i = 0;i < m ;i ++)
printf("%d ",H.elem[i]);
int addr,j;
j = SearchHash(H,a[5],&addr);
printf("搜索到a[5]的地址是:%d",j);
return 0;
}