哈希表概念
决定一个哈希表的主要是哈希函数与处理冲突的方法。而按照设定的哈希函数和处理冲突的方法将一组关键字key 映射到有限的地址集合中,这就是哈希表。可以根据处理冲突的方法不同,给哈希表不同的命名,如:链式哈希表,开放址哈希表。
哈希函数构造方法
直接定义法:代码块如下:
int hash1(int key){
return a*key + b; //a 缩放, b 平移
}
除留取余法:(我接触最多的)
区间长度为 m 的哈希表,取 不大于 m 的数 x 为模, H(key) = key % p。(理论上,p 取最接近 m 的素数最好了)
int hash2(int key){
return key % p;
}
数字分析法:了解不多,貌似没用到过。
折叠法:
移位折叠
int hash3(int key){
itn i , j= 1, qu , sum = 0;
for (i = 0; i < w; i++)
j * = 10;//按照w 位分割
while (key != 0){
qu = key % j;
sum += qu;
key /= j;
}
return sum;
}
平方取中法 :接触的很少(没有)
#include
#include
//宏定义相关常量
#define Max 10
#define Size 10
typedef struct Sqlist{
int *data;
int length;//长度
}Sqlist;//顺序表
typedef struct HashSqlist{
int *data;
int length;
}HashSqlist;//哈希表
int hash (int key){
return key%10;
} //哈希函数
void InitSqlist(Sqlist &l){ //这里l 还没定义,所以要加 &
printf("Please int the length of the hashTable\n");
scanf("%d",&l.length);
l.data = (int *)malloc (Max * sizeof(int));
printf("Please int %d numbers\n",l.length);
for (int i = 0; i < l.length ; i ++)
scanf("%d",&l.data[i]);
}//建立一个顺序表,通过顺序表给哈希表赋值
void InitHashSqlist(Sqlist l,HashSqlist &hl){
hl.data = (int *)malloc (Max * sizeof (int ));
hl.length = Size;
int i,j,key;
for (i = 0; i < hl.length; i ++)
hl.data[i] = 0;
for (i = 0; i < l.length ; i ++){
key = hash(l.data[i]);
if (hl.data [key] != NULL){
for (j = 1; hl.data[key] != NULL; j ++)
key = hash(l.data[i] + j);
}
hl.data[key] = l.data[i] ;
printf("%d ----%d \n",key,hl.data[key]);//顺便输出,方便检验
}
}
int main (){
Sqlist l;
HashSqlist hl;
InitSqlist(l);
InitHashSqlist(l,hl);
return 0;
}
//目前只是初始化并且输出一个哈希表,有时间(学会后)再补上:查找、删除、替换等功能。
链式哈希表
#include
#include
#define Max 10
#define Size 10
typedef struct Sqlist {
int *data;
int length;
}Sqlist;
typedef struct HashSqlist{
int *data;
int length;
}HashSqlist;
typedef struct Lnode{
int data;
struct Lnode * next;
}Lnode,*HLinklist; //单链表
typedef struct Hnode {
Lnode *first;
}Hnode,Hlist[Max];//定义一个指向链表第一个地址的哈希链表
typedef struct HashTable{
Hlist arr;//哈希表链地址
int listNumber;//哈希地址个数
}HashTable;
int hash(int key ){
return key % 10;
}
void InitSqlist(Sqlist &l){
printf("Please int the length of the hashTable\n");
scanf("%d",&l.length);
l.data = (int *)malloc (Max * sizeof(int ));
printf("Please int %d numbers\n",l.length);
for (int i = 0; i < l.length ; i ++)
scanf("%d",&l.data[i] );
}
void InitHashTable(Sqlist l,HashTable &ht){
Lnode *p,*q;
ht.listNumber = l.length;
int i , j , key;
for (i = 0; i < ht.listNumber; i ++)
ht.arr[i].first = NULL;
for(i = 0;i < l.length;i++){
p=(Lnode*)malloc(sizeof(Lnode));
p->data=l.data[i];
p->next=NULL;
key=hash(l.data[i]);
if (key > ht.listNumber)
ht.listNumber = key;
q=ht.arr[key].first;
if(q){
while(q->next){
q=q->next ;
}
q->next=p;
}
else
ht.arr[key].first=p;
}
return;
}
void Output(HashTable ht){
int i;
HLinklist p,q;
for(i=0;i<=ht.listNumber;i++){
p=ht.arr[i].first;
printf("%d----",i);
while(p){
printf("%d->",p->data);
p=p->next;
}
printf("\n");
}
return ;
}
int main(){
Sqlist l;
HashTable ht;
InitSqlist(l);
InitHashTable(l,ht);// 链地址法解决冲突
Output(ht);
return 0;
}
//同样的,这个也只实现了初始化并且输出。学会后再更新。