再探hash——自写哈希程序

基本思想:利用数组链表结合,构建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;  
   }  


你可能感兴趣的:(链表,注释,hash)