基本思想:利用数组链表结合,构建hash表,把相应数据储存进去,便于查找利用
来看源码:(已经加上注释)
采用了菜单形式:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#define HASH_SIZE 10//哈希表的大小
typedef struct HashNode{ //哈希表的节点
char key[1000];
char value[1000];
HashNode *next; //指向下一个节点的指针
}HashNode;
typedef struct hashtable{//哈希表,每一个数组单位
int item_size;
HashNode* head;//链表头节点
}HashTable;
char s[100][100];//查找储存数组
int num;//查找找到的个数
HashTable hashtable[HASH_SIZE];//初始化哈希表,即空的哈希表已经建立
int hash(char key[]);//哈希函数
void hash_input(char key[],char value[]);//把一个数据存储到哈希表中
void hash_search(char key[]);//查找哈希表中的数据
void hash_delete(char key[]);//删除哈希表中数据
void hash_print();//输出哈希表
void hash_destroy();//销毁哈希表
void menu_hash_delete();//菜单删除函数
void menu_hash_search();//菜单搜索函数
void menu_hash_input();//菜单输入函数
int main()//菜单的实现
{
int chioce;
do
{
printf("\n\t\t********************************\n");
printf("\t\t* 1.input datas *\n");
printf("\t\t* 2.delete datas *\n");
printf("\t\t* 3.search datas *\n");
printf("\t\t* 4.print hashtable *\n");
printf("\t\t* 5.distroy hashtable *\n");
printf("\t\t* 0.quit *\n");
printf("\t\t*********************************\n");
printf("\t\tplease input order:");
scanf("%d",&chioce);
switch(chioce)
{
case 1:
menu_hash_input();//输入
break;
case 2:
menu_hash_delete();//删除
break;
case 3:
menu_hash_search();//查找
break;
case 4:
hash_print();//打印
break;
case 5:
hash_destroy();//销毁
break;
default:
break;
}
}while(chioce!=0);
return 0;
}
int hash(char key[])//哈希函数——最简单的哈希函数——根据key值返回一个值
{
int index=0;
while(*key!='\0')
{
index+=*key;
key++;
}
return index%HASH_SIZE;//保证返回的数不超过哈希表大小
}
void hash_input(char key[],char value[])//输入函数
{
int index;
HashNode *newhashnode;
index=hash(key);//得到引索
HashNode* temp=hashtable[index].head;//得到头指针
if(temp==NULL)
{
newhashnode=(HashNode*)malloc(sizeof(HashNode));//如果不存在节点则建立
hashtable[index].head=newhashnode;
strcpy(newhashnode->key,key);
strcpy(newhashnode->value,value);
newhashnode->next=NULL;
return ;
}
while(temp->next!=NULL)//找到链表最后的一个节点,并把新节点连接到最后一个节点上
{
temp=temp->next;
}
newhashnode=(HashNode*)malloc(sizeof(HashNode));
strcpy(newhashnode->key,key);
strcpy(newhashnode->value,value);
newhashnode->next=NULL;//important,,注意!!
temp->next=newhashnode;
return ;
}
void hash_search(char key[])//搜索
{
num=0;
int index=hash(key);//找到引索
HashNode *head=hashtable[index].head;//找到头节点
while(head!=NULL)
{
if(strcmp(head->key,key)==0)//当两个值相等时,则把value值放到s当中
{
strcpy(s[num],head->value);
num++;//个数加
}
head=head->next;
} //直到遍历完链表
return ;
}
void hash_delete(char key[])//删除某个数据
{
int index=hash(key);//找到引索
HashNode* begin=hashtable[index].head,*temp=begin,*temp1;
while(begin!=NULL&&hashtable[index].head!=NULL)
{
if(strcmp(hashtable[index].head->key,key)==0)//当删除第一个节点时
{
temp1=hashtable[index].head;//删除第一个节点,并把head赋值给头指针
hashtable[index].head=hashtable[index].head->next;
free(temp1);
begin=hashtable[index].head;
temp=begin;
continue;
}
if(strcmp(begin->key,key)==0)//非第一个节点
{
temp->next=begin->next;//直接删除
free(begin);
begin=temp;
}
temp=begin;
begin=begin->next;
}
}
void hash_print()//打印哈希表
{
int index=0;
HashNode* head;
for(index=0;index<HASH_SIZE;index++)//遍历每一个引索
{
printf("index%d:\t",index);
head=hashtable[index].head;
while(head!=NULL)//把每一个引索后的链表遍历
{
printf("%s:%s\t",head->key,head->value);
head=head->next;
}
printf("\n");
}
}
void hash_destroy()//销毁链表
{
int index;
HashNode *next,*temp;
for(index=0;index<HASH_SIZE;index++)//遍历每一个引索
{
next=hashtable[index].head;
temp=next;
while(next!=NULL)//free每个节点
{
next=temp->next;
free(temp);
temp=next;
}
hashtable[index].head=NULL;//把引索头节点都改为NULL
}
}
void menu_hash_delete()
{
char key[100];
printf("\n\nplease input the key you want to delete:");
scanf("%s",key);
hash_delete(key);
}
void menu_hash_search()
{
char key[100];
int i;
printf("\nplease input key that you want to find:");
scanf("%s",key);
hash_search(key);
if(num==0)
printf("\nthere is no results you want to find!!");
else
{
printf("\nresults:");
for(i=0;i<num;i++)
{
printf("%s ",s[i]);
}
}
}
void menu_hash_input()
{
long i,n;
char key[100];
char value[100];
printf("\nplease input the number of datas:");
scanf("%ld",&n);
for(i=0;i<n;i++)
{
printf("please input key:");
scanf("%s",key);
printf("please input value:");
scanf("%s",value);
hash_input(key,value);
}
}
此hash函数比较简单:
int hash(char key[])//哈希函数——最简单的哈希函数——根据key值返回一个值
{
int index=0;
while(*key!='\0')
{
index+=*key;
key++;
}
return index%HASH_SIZE;//保证返回的数不超过哈希表大小
}
再来介绍几种稍微复杂点的hash函数:
1.RS
从Robert
Sedgwicks的
Algorithms in C一书中得到了。
我(原文作者)已经
添加了一些
简单的优化
的
算法,以
加快
其
散列
过程。
public long RSHash(String str)
{
int b = 378551;
int a = 63689;
long hash = 0;
for(int i = 0; i < strlen(str); i++)
{
hash = hash * a + str[i];
a = a * b;
}
return hash;
}
2.JS
Justin Sobel写的一个位操作的哈希函数。
public long JSHash(String str)
{
long hash = 1315423911;
for(int i = 0; i < strlen(str); i+)
{
hash ^= ((hash << 5) + str[i] + (hash >> 2));
}
return hash;
}
3.PJW
该散列
算法是基于贝尔实验室的
彼得J
温伯格
的的研究
。在Compilers一书中
(原则,
技术
和工具)
,
建议
采用这个算法的
散列
函数
的哈希
方法。
public long PJWHash(String str)
{
long BitsInUnsignedInt = (long)(4 * 8);
long ThreeQuarters = (long)((BitsInUnsignedInt * 3) / 4);
long OneEighth = (long)(BitsInUnsignedInt / 8);
long HighBits = (long)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
long hash = 0;
long test = 0;
for(int i = 0; i < strlen(str); i+)
{
hash = (hash << OneEighth) + str[i];
if((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
}
return hash;
}