1、哈希表概念
1、让查找与数据规模无关,是常数级查找
2、依据Key,精确匹配地址,找到这条记录。
3、根据选取的Hash函数H(key)和处理冲突的方法,将一组记录(R1 R2……Rn)映象到记录的存储空间,所得到的记录表称为Hash表
2、关于Hash表的讨论关键是两个问题
1、构造(或选取)Hash函数的方法
1、直接地址法
2、平方取中法
3、叠加法
4、保留除数法
5、随机函数法
2、确定解决冲突的方法
1、冲突是指:表中某地址j中已存放有记录,而另一个记录的H(key)值也是j。
2、处理冲突的方法:在地址j的前面或者后面找一空闲空间存放冲突的记录,或将相冲突的诸记录拉成链表等
3、为减少冲突可引入一个装填因子a,a=n/m,
其中m为表长,n为表中记录个数。
一般a取0.7——0.8之间。
4、开放地址法
当发生冲突时,在H(key)的前后找一个空闲单元来存放冲突的记录,即在H(key)的基础上
获取下一地址:Hi=(H(key)+di)%m
5、链地址法
发生冲突时,将各冲突记录链在一起,即同义词的记录存于同一链表。
3、算法思路
1、对给定k,根据造表时选取的H(key)求H(k);
2、若H(k)单元=^,则查找失败;
3、否则k与该单元存放的key比较,若相等,则查找成功;
4、若不等,则根据设定的处理冲突方法,找下一地址Hi,直到查找到或等于空为止。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 100
#define PRIME 97
enum res
{
ERROR = -5,
NULLERROR,
MALLOCREEOR,
HASHNULL,
HASHERROR,
OK
};
//定义数据域结构体类型
typedef int data_type;
//定义节点的结构体类型
typedef struct node
{
data_type data;//数据域
struct node *next;//指针域
}Node;
//定义hash表的结构体类型
typedef struct hash
{
Node *hash[SIZE];//指针数组,数组元素为链表地址
int count;//记录个数
}Hash;
//菜单
void menu(void);
//创建hash函数
int HashFunc(data_type pData);
//创建hash表
Hash *createHash(void);
//创建一个新节点
Node *createNode(void);
//在hash表中添加数据
int insertItemHash(Hash *pHash,data_type pData);
//查找
int searchItemHash(Hash *pHash,data_type pData);
int main(void)
{
Hash *pHash = NULL;
pHash = createHash();
data_type pData;
int op = 0;
int ret = 0;
while(1)
{
menu();
printf("请输入要操作的选项:\n");
scanf("%d",&op);
if(-1 == op)
{
break;
}
switch(op)
{
case 1://添加数据
printf("请输入要添加的数据:\n");
scanf("%d",&pData);
ret = insertItemHash(pHash, pData);
if(OK == ret)
{
printf("添加成功\n");
}
else
{
printf("添加失败\n");
}
break;
case 2://查找数据
printf("请输入要查找的数据:\n");
scanf("%d",&pData);
ret = searchItemHash(pHash, pData);
if(ret == HashFunc(pData))
{
printf("该数据存放在Hash表中的第%d位\n",ret);
}
break;
default:
printf("输入有误!\n");
}
}
return 0;
}
//菜单
void menu(void)
{
printf("1................插入\n");
printf("2................查找\n");
printf("-1...............退出\n");
}
//创建hash函数
int HashFunc(data_type pData)
{
return pData % PRIME;
}
//创建hash表
Hash *createHash(void)
{
Hash *pHash = NULL;
pHash = (Hash *)malloc(sizeof(Hash));
if(NULL == pHash)
{
perror("malloc hash error!");
return NULL;
}
memset(pHash, 0, sizeof(Hash));
return pHash;
}
//创建一个新结点
Node *createNode(void)
{
Node *pNode = NULL;
pNode = (Node *)malloc(sizeof(Node));
if(NULL == pNode)
{
perror("malloc node error!");
return NULL;
}
memset(pNode, 0, sizeof(Node));
return pNode;
}
//在hash表中添加数据
int insertItemHash(Hash *pHash, data_type pData)
{
if(pHash == NULL)
{
return HASHERROR;
}
int key = 0;
Node *pTmp = NULL;
Node *pNew = createNode();
if(NULL == pNew)
{
return NULLERROR;
}
pNew -> data = pData;
key = HashFunc(pData);
pTmp = pHash -> hash[key];
if(pTmp != NULL)
{
while(pTmp -> next != NULL)
{
pTmp = pTmp -> next;
}
pTmp -> next = pNew;
}
else
{
pHash -> hash[key] = pNew;
}
pHash -> count ++;
return OK;
}
//在hash表中查找数据
int searchItemHash(Hash *pHash, data_type pData)
{
if(pHash == NULL)
{
printf("hash error");
return HASHERROR;
}
if(0 == pHash -> count)
{
printf("hash null");
return HASHNULL;
}
int key = 0;
key = HashFunc(pData);
Node *pTmp = pHash -> hash[key];
while(1)
{
if(NULL == pTmp)
{
printf("找不到该数据");
return ERROR;
}
if(pData == pTmp -> data)
{
break;
}
pTmp = pTmp -> next;
}
return key;
}