利用链表法解决冲突构建的一个hash表,最终的示意图如下图所示。
下面的代码实现的功能为:将一个网址进行hash,并存放于hash表中,利用hash表统计每个网址的访问次数。
链表节点包含三个元素:1)存放指向存放网址的指针。2)该网址出现的次数。3)指向下一个节点的指针。
/*******************************************
=================JJ日记=====================
作者: JJDiaries(阿呆)
邮箱:JJDiaries@gmail.com
日期: 2013-11-13
============================================
哈希表:为实现快速查找而生。
实现一个散列表,并用链表法解决冲突。
应用实例:用一个hashTable记录网站中每个页面的访问量。
*******************************************/
/*================JJ日记=====================
作者: JJDiaries(阿呆)
邮箱:JJDiaries@gmail.com
日期: 2013-11-13
============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABLELEN 1024 //hash表大小
#define SITELEN 256 //每个网址的最大长度
struct node{
char *website; //存放网址
int counts; //存放该网址访问次数
struct node *next; //指向下一个节点
};
static struct node *HashTable[TABLELEN]={NULL};
//将网址字符串转换成一个整数
unsigned long hash(char *key)
{
unsigned long h=0;
while(*key)
{
h=(h<<4)+*key++;
unsigned long g=h&0Xf0000000L;
if(g) h^=g>>24;
h&=~g;
}
return h%TABLELEN;
}
//将一个节点存入hash表
int insert(struct node *T[],char *website)
{
if(website==NULL)
return -1;
int index=hash(website);
//为空,说明此前没有此类记录,分配一个节点,用于存放新的网址,并将其链入hash表
if(HashTable[index]==NULL){
struct node *tmp=(struct node*)malloc(sizeof(struct node));
if(tmp==NULL)
return -1;
tmp->website=(char*)malloc(strlen(website)+1);
if(tmp->website==NULL)
return -1;
strncpy(tmp->website,website,strlen(website)+1);
//将新分配的节点链到hash表的某一个槽的链表头部
tmp->next=NULL;
HashTable[index]=tmp;
tmp->counts=1;
}
else{//index槽不为空,则需要比较该网址内容,判断其是否已经存在。
struct node *tmp=HashTable[index];
while(tmp!=NULL && strcmp(website,tmp->website)!=0)
tmp=tmp->next;
if(tmp)//说明website已经存在,将其counts加1
tmp->counts++;
else{
tmp=(struct node*)malloc(sizeof(struct node));
if(tmp==NULL)
return -1;
tmp->website=(char*)malloc(strlen(website)+1);
if(tmp->website==NULL)
return -1;
strncpy(tmp->website,website,strlen(website)+1);
//将新分配的节点链到hash表的某一个槽的链表头部
tmp->next=HashTable[index]->next;
HashTable[index]->next=tmp;
tmp->counts=1;
}
}
return 0;
}
//查看网址website是否有访问记录,如果有,则返回其访问次数,否则返回-1
int search(struct node *T[],char *website)
{
int index=hash(website);
//为空,说明此前没有此website记录
if(HashTable[index]==NULL)
return -1;
struct node *tmp=HashTable[index];
while(tmp!=NULL && strcmp(website,tmp->website)!=0)
tmp=tmp->next;
if(tmp)//说明website已经存在,将其counts加1
return tmp->counts;
return -1;
}
//free resources that allocated with malloc
void finit_table(struct node *T[])
{
int i;
struct node *tmp,*del;
for(i=0;i<TABLELEN;++i){
if(T[i]==NULL)
continue;
tmp=T[i]->next;
while(tmp!=NULL){
del=tmp;
tmp=tmp->next;
free(del);
}
free(T[i]);
}
}
int main()
{
char * websites[]={"www.baidu.com",
"www.google.com",
"www.google.com",
"www.bing.com",
"www.google.com",
"www.jjdiaries.com",
"www.baidu.cn"};
int i;
for(i=0;i<7;++i)
insert(HashTable,websites[i]);
printf("www.google.com accessed times is :%d\n",search(HashTable,"www.google.com"));
printf("www.baidu.com accessed times is :%d\n",search(HashTable,"www.baidu.com"));
//note:free resource
finit_table(HashTable);
}
/***************************************
viidiot@ubuntu:$ ./hash
www.google.com accessed times is :3
www.baidu.com accessed times is :1
***************************************/