散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。查找时,根据这个确定的对应关系找到给定值key的映射f(key),若查找集合中 存在这个记录,则必定在f(key)的位置上。
1.哈希表实现方法及冲突解决方法
哈希表有多种实现方法,每种方法有不同的优缺点。
1.直接定法址:优点是简单均匀,不会产生冲突,但是需要事先直到关键字的分布情况,适合查找表小且连续的情况
2.数字分析法:通常适合处理关键字位数比较大的情况,如果事先知道关 键字的分布且关键字的若干位分布较均匀,就可以考虑用这个方法
3.平方取中法:平方取中法比较适合于不知道关键字的分 布,而位数又不是很大的情况
4.折叠法:折叠法事先不需要知道关键字的分布,适合关键字位数较多的情况
5.除留余数法:对于散列表长为m的散列函数公 式为: f(key)=key mod p(p≤m)
6.随机数法:选择一个随机数,取关键字的随机函数值为它的散列地址。也就是 f(key)=random(key)。这里random是随机函数。当关键字的长度不等 时,采用这个方法构造散列函数是比较合适的
处理散列冲突的方法:
1.开放定址法:所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地 址,只要散列表足够大,空的散列地址总能找到,并将记录存入
2.再散列函数法:每当发生散列地址冲突时,就换一个 散列函数计算,相信总会有一个可以把冲突解决掉掉。这种方法能够使 得关键字不产生聚集,但也增加了计算的时间
3.链地址法:用链表来存储,不存在所谓冲突,一旦有冲突,就在当前位置增加节点
4.公共溢出区法: 把有冲突的元素放在溢出区
这里使用除留余数法实现,用链地址法处理冲突。
#include"list.h"
typedef int ELEM_TYPE;
#define INITSIZE 12
//链地址法有效节点结构体设计
typedef struct List_Node
{
ELEM_TYPE data;
struct List_Node* next;
};
//链地址法整个的头节点结构体设计
typedef struct List_address
{
struct Node arr[INITSIZE];
};
1.哈希函数
获取值的关键字,对于相同的关键字,直接头插
int Hash(ELEM_TYPE val)
{
return val % INITSIZE;
}
2.初始化
将List_address申请的链表数组初始化
void Init_List_Address(List_address* head)
{
for(int i = 0 ; i < INITSIZE ; i++)
{
Init_list(&head->arr[i]);
}
}
3.插入值(头插)
bool Insert(List_address* head,ELEM_TYPE val)
{
assert(NULL != head);
int index = Hash(val);
struct Node* pnewnode = (Node*)malloc(sizeof(Node));
if(pnewnode == NULL) return false;
pnewnode->data = val;
//头插
pnewnode->next = head->arr[index].next;
head->arr[index].next = pnewnode;
return true;
}
4.删除值
bool Del(List_address* head,ELEM_TYPE val)
{
assert(NULL != head);
int index = Hash(val);
struct Node* q = head->arr[index].next;
for(;q != NULL; q = q->next)
{
if(q->data == val) break;
}
if(q == NULL) return false;
struct Node* p =&head->arr[index];
for (;p->next != q;p = p->next);
p->next = q->next;
free(q);
q = NULL;
return true;
}
5.查找值
通过关键字找到该值在哪个链表中,然后遍历链表
struct Node* Search(List_address* head,ELEM_TYPE val)
{
assert(NULL != head);
int index = Hash(val);
struct Node* q = head->arr[index].next;
for(;q != NULL; q = q->next)
{
if(q->data == val) break;
}
return q;
}