- 哈希表
哈希表是基于数组的顺序结构,每一个存储目标都会存在一个key值,哈希表也称为散列表。为解决冲突问题(多个目标用hash函数计算出相同的位置),本代码用了拉链法,另外本代码还解决了字符串插入哈希表循环冲突拉链的问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10 //哈希表链的数量(key值最大数)
// typedef int (*HASH_FUN)(const char* ch);
//定义hash表存储元素类型 我用了双向链表
typedef struct node
{
char ch_value[100];//存储query
struct node * pre;//指向上一个节点指针
struct node * cur;//每个hash_table[k]的尾指针
//没有该指针 每次插入到对应的链都要从头到尾遍历,加入该指针,可解决循环冲突链表的问题
struct node * next;//指向下一个节点
}node;
//初始化哈希表
node ** init_hash_table()
{
node ** hash_table=(node **)malloc(N*sizeof(node*));
int i;
for(i=0;i<N;i++)
{
hash_table[i]=NULL;
}
return hash_table;
}
//定义hash 函数 这里用字符串的ASCII来哈希
int hash_fun(const char* ch)
{
int i;
int sum=0;
for(i=0;i<strlen(ch);i++)
{
sum+=ch[i];
}
return sum%N;
}
//把数据存入哈希表
void save_hash_table(const char * ch,node** hash_table)
{
//初始化哈希表
int key=hash_fun(ch);
node* ptr_new=(node*)malloc(1*sizeof(node));
strcpy(ptr_new->ch_value,ch);
ptr_new->pre=NULL;
ptr_new->next=NULL;
ptr_new->cur=NULL;
node *ptr_head=hash_table[key];
if(hash_table[key]==NULL)
{
hash_table[key]=ptr_new;
hash_table[key]->pre=NULL;
hash_table[key]->cur=ptr_new;
hash_table[key]->next=NULL;
}
else
{
hash_table[key]->cur->next=ptr_new;
ptr_new->pre=hash_table[key]->cur;
hash_table[key]->cur=ptr_new;
ptr_new->next=NULL;
ptr_new->cur=NULL;
}
}
//查找函数
node * find_hash(const char * ch,node** hash_table)
{
int key=hash_fun(ch);
node * ptr_new=hash_table[key];
if(hash_table[key]==NULL)
{
return NULL;
}
while(hash_table[key]!=NULL && ptr_new!=NULL)
{
int a=strcmp(hash_table[key]->ch_value,ch);
if(a==0)
{
return ptr_new;
}
ptr_new=ptr_new->next;
}
return NULL;
}
//释放哈希表每条链
void free_hash(node ** hash_table)
{
int i;
for(i=0;i<10;i++)
{
node* ptr_move=hash_table[i];
while(ptr_move!=NULL)
{
node* ptr_tmp=ptr_move;
ptr_move=ptr_move->next;
free(ptr_tmp);
ptr_tmp=NULL;
}
}
}
删除函数(在删除函数中调用查找函数)
int delete_hash(const char * ch,node** hash_table)
{
int key=hash_fun(ch);
node * ptr_new=hash_table[key];
node * ptr_tmp=find_hash(ch,hash_table);
if(hash_table[key]==NULL || ptr_tmp==NULL)
{
printf("error\n");
return 0;
}
if(ptr_tmp!=NULL)
{
if(ptr_new==ptr_tmp)
{
hash_table[key]=ptr_tmp->next;
free(ptr_tmp);
ptr_tmp=NULL;
}
else
{
while(ptr_new->next!=ptr_tmp)
{
ptr_new=ptr_new->next;
}
ptr_new->next=ptr_tmp->next;
free(ptr_tmp);
ptr_tmp=NULL;
hash_table[key]->cur=ptr_new;
ptr_new->next=NULL;
ptr_new->cur=NULL;
}
}
}
//打印每条链上的数据
void print_hash_table(node** hash_table)
{
int i;
for(i=0;i<N;i++)
{
node* ptr_tmp=hash_table[i];
printf("第%d条链:",i);
if(ptr_tmp!=NULL)
{
while(ptr_tmp!=NULL)
{
printf("%s\t",ptr_tmp->ch_value);
ptr_tmp=ptr_tmp->next;
}
}
printf("\n");
}
}
int main(int argc,const char* argv[])
{
node** hash_table=init_hash_table();
save_hash_table("456456",hash_table);
save_hash_table("sadashj",hash_table);
save_hash_table("2dasd4",hash_table);
save_hash_table("22222222",hash_table);
save_hash_table("arrabh23fff",hash_table);
save_hash_table("234",hash_table);
save_hash_table("22",hash_table);
save_hash_table("220",hash_table);
save_hash_table("23",hash_table);
save_hash_table("24",hash_table);
save_hash_table("25",hash_table);
save_hash_table("26",hash_table);
save_hash_table("27",hash_table);
save_hash_table("28",hash_table);
save_hash_table("29",hash_table);
save_hash_table("30",hash_table);
save_hash_table("31",hash_table);
save_hash_table("32",hash_table);
save_hash_table("33",hash_table);
// delete_hash("27",hash_table);
print_hash_table(hash_table);
if(find_hash("27",hash_table)!=NULL)//查找一个字符串
{
printf("find\n");
}
else
{
printf("not find\n");
}
free_hash(hash_table);//释放哈希表每条链
return 0;
}
调用delete函数删除字符串“27”运行结果:
没有调用delete函数也就是没删除字符串“27”运行结果:
对比可得哈希表可任意删除和查找任意的字符串