哈希表也叫散列表,是根据关键码值直接进行访问的数据结构。即通过关键值(key)映射到表中的某个位置,以便可以直接访问该节点,以提高查找速度。
在C语言中直接使用哈希表的过程较为繁琐,所以这里介绍C语言中的一个哈希表库——Uthash函数,使用时只需包含头文件**“uthash.h”.**
首先介绍Uthash函数中的一些函数用法:
HASH_FIND_INT
作用:查找整数键的元素(int key)
使用:(操作哈希表的头指针,查找特定的整数键(通过指针传递),将结果存入的地方)。
HASH_ADD_INT
作用:添加一个以整数为键的值
使用:(操作哈希表的头指针,要加入的整数名,将结果存入参数)
HASH_ITER
作用:遍历哈希表并支持在遍历中删除元素
使用:(hh,操作哈希表的头指针,当前遍历到的元素指针,临时指针变量temp)
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.赎金信