C语言中哈希表的简单使用

什么是哈希表

哈希表也叫散列表,是根据关键码值直接进行访问的数据结构。即通过关键值(key)映射到表中的某个位置,以便可以直接访问该节点,以提高查找速度

哈希表的实现

在C语言中直接使用哈希表的过程较为繁琐,所以这里介绍C语言中的一个哈希表库——Uthash函数,使用时只需包含头文件**“uthash.h”.**
首先介绍Uthash函数中的一些函数用法:

  1. HASH_FIND_INT

作用:查找整数键的元素(int key)

使用:(操作哈希表的头指针,查找特定的整数键(通过指针传递),将结果存入的地方)。

  1. HASH_ADD_INT

作用:添加一个以整数为键的值

使用:(操作哈希表的头指针,要加入的整数名,将结果存入参数)

  1. HASH_ITER

作用:遍历哈希表并支持在遍历中删除元素

使用:(hh,操作哈希表的头指针,当前遍历到的元素指针,临时指针变量temp)

  1. HAH_DEL

作用:从哈希表中删除元素

使用: (操作哈希表的头指针,要删除元素的指针)
在使用时的代码实现:

#include
#include"uthash.h"

typedef struct{
   int key;
   int value;
   UT_hash_haddle hh;
}map;

map* hashMap=NULL;

void hashMapAdd(int key,int value){
   map* s;
   HASH_FIND_INT(hashMap,key,s);
   if(s==NULL)
   {
       s=(map*)malloc(sizeof(map));
       s->key=key;
       HASH_ADD_INT(hashMap,key,s); //把key映射到哈希表中,此时 s->value 未初始化!
   }
   s->value=value; //如果该键的key已经存在,更改value的值,如果没有,则要讲value的值存入哈希表中
}
map* hashMapFind(int key){
   map* s;
   HASH_FIND_INT(hashMap,&key,s);
   return s;
}
void hashMapClean(){
   map* cur,*temp;
   HASH_ITER(hh,hashMap,cur,temp){
       HASH_DEL(hashMap,cur);
       free(cur);
   }
}
void hashPrint(){
   map* s;
   for(s=hashMap;s!=NULL;s=(map*)(s -> hh.next)) //s->hh.next表示指向哈希表当前元素的下一个元素,又因为hh.next是通用指针(void*类型),所以要进行显式类型转换
}

具体题目中的使用

1.两数之和
具体代码:

#include
#include"uthash.h"

typedef struct{
   int key;
   int value;
   UT_hash_haddle hh;
}map;

map* hashMap=NULL;

void hashMapAdd(int key,int value){
   map* s;
   HASH_FIND_INT(hashMap,key,s);
   if(s==NULL)
   {
       s=(map*)malloc(sizeof(map));
       s->key=key;
       HASH_ADD_INT(hashMap,key,s); //把key映射到哈希表中,此时 s->value 未初始化!
   }
   s->value=value; //如果该键的key已经存在,更改value的值,如果没有,则要讲value的值存入哈希表中
}
map* hashMapFind(int key){
   map* s;
   HASH_FIND_INT(hashMap,&key,s);
   return s;
}
void hashMapClean(){
   map* cur,*temp;
   HASH_ITER(hh,hashMap,cur,temp){
       HASH_DEL(hashMap,cur);
       free(cur);
   }
}
void hashPrint(){
   map* s;
   for(s=hashMap;s!=NULL;s=(map*)(s -> hh.next)) //s->hh.next表示指向哈希表当前元素的下一个元素,又因为hh.next是通用指针(void*类型),所以要进行显式类型转换
}
int *TwoSum(int *nums,int numsSzie,int target,int * returnSize){
   int i,*ans;
   map* hashMapRes;
   hashMap=NULL;   //重置哈希表指针,确保新的操作不会受到之前数据的影响
   ans=(int *)malloc(sizeof(int)*2);
   
   for(i=0;i<numsSize;i++){
       hashMapAdd(nums[i],i);
   }
   hashPrint(); //便于调试
   for(i=0;i<numsSize;i++){
       hashMapRes=hashMapFind(target-nums[i]);
       if(hashMapRes&&hashMapRes->value!=i) {
           ans[0]=i;
           ans[1]=hashMapRes->value;
           *returnSize=2;
           return ans;
       }
   }
   hashMapClean();
   return NULL;
}

2.四数相加

typedef struct{
   int key;
   int count;
   UT_hash_handle hh;
} map;


int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums3, int nums3Size, int* nums4, int nums4Size) {
   int count=0;
   map* hashMap=NULL;
   

   for(int i=0;i<nums1Size;i++){
       for(int j=0;j<nums2Size;j++){
          
           map* s;
           int presum=nums1[i]+nums2[j];
           HASH_FIND_INT(hashMap,&presum,s);
           if(s){
              s->count++;

           }
           else {
                s=(map*)malloc(sizeof(map));
               s->key=presum;
               s->count=1;
               HASH_ADD_INT(hashMap,key,s);
           }
       }
   }

   for(int i=0;i<nums3Size;i++){
       for(int j=0;j<nums4Size;j++){
          
           map* s;
           int presum=-nums3[i]-nums4[j];
           HASH_FIND_INT(hashMap,&presum,s);
           if(s){
               count+=s->count;
           }
       }
   }
   map*cur,*temp;
   HASH_ITER(hh,hashMap,cur,temp){
       HASH_DEL(hashMap,cur);
       free(cur);
   }
   return count;
}

注意事项

当上述的哈希表同时储存两个值,当一些关于哈希表的问题只需要对一个值进行操作,并且总数确定时,我们可以选择数组来代替哈希表(但思路仍为判断一个数是否出现在某个集合中。

一些示例

242.有效的字母异位词
383.赎金信

你可能感兴趣的:(哈希算法,散列表,算法)