C语言实现HashMap

C语言实现HashMap

       在做算法题时,需要使用到HashMap这种数据结构,虽然高级语言中大都实现了这种数据结构,但是为了理解HashMap的底层原理,于是打算自己实现HashMap,使用C语言实现了HashMap的创建(CreateHashMap)、取键值对(Get)、插入键值对(Put)、输出(PrintHashMap)以及销毁(DestoryHashMap),具体程序如下:

1.结点类型定义:

typedef struct{
	int key;  //键
	int val;  //值
}DataType; //对基本数据类型进行封装,类似泛型
typedef struct{
	DataType data;
	struct HashNode *next;  //key冲突时,通过next指针进行连接
}HashNode;
typedef struct{
	int size;
	HashNode *table;
}HashMap,*hashmap;

2.HashMap基本操作:

①CreateHashMap

//f1_createHashMap
//将给定的整形数组构建为HashMap,size为数组长度
HashMap *CreateHashMap(int *nums,int size){
	//分配内存空间
	HashMap *hashmap=(HashMap*)malloc(sizeof(HashMap));
	hashmap->size=2*size;
	//hash表分配空间
	hashmap->table=(HashNode *)malloc(sizeof(HashNode)*hashmap->size);
	//初始化
	int j=0;
	for(j=0;j<hashmap->size;j++){
		hashmap->table[j].data.val=INT_MIN;
		hashmap->table[j].next=NULL;
	}
	int i=0;
	//建立HashMap
	while(i<size){
	    //根据数组元素的值计算其在hashMap中的位置
		int pos=abs(nums[i])%hashmap->size;
		//判断是否冲突
		if(hashmap->table[pos].data.val==INT_MIN){
		    //不冲突
		    //把元素在数组中的索引作为key
			hashmap->table[pos].data.key=i;
			//把元素值作为value
			hashmap->table[pos].data.val=nums[i];
		}
		//冲突
		else{
		    //给当前元素分配一个结点,并为结点复制
			HashNode *lnode=(HashNode*)malloc(sizeof(HashNode)),*hashnode;
			lnode->data.key=i;
			lnode->data.val=nums[i];
			lnode->next=NULL;
			//从冲突位置开始,遍历链表
			hashnode=&(hashmap->table[pos]);
			while(hashnode->next!=NULL){
				hashnode=hashnode->next;
			}
			//将当前结点连接到链表尾部
			hashnode->next=lnode;
		}
		//处理下一个元素
		i++; 	
	}
	//处理完成,返回HashMap
	return hashmap;
}

       对于hashmap->size=2*size; hashmap中table的长度为什么是给定数组长度的2倍?这涉及到hash表的装填因子,详细可以参考严蔚敏《数据结构》中第九章查找的哈希表章节,这里做简单介绍:

哈希的装填因子:
        其中n 为关键字个数,m为表长.

       装填因子是表示Hsah表中元素的填满的程度。加载因子越大,填满的元素越多,空间利用率提高,但冲突的机会加大了。反之,加载因子越小,填满的元素越少,冲突的机会减小了,但空间浪费多了。冲突的机会越大,则查找的成本越高。反之,查找的成本越小.因而,查找时间就越小.因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡。

②Get

//f2_GetHashNode
int Get(HashMap hashmap,int value){
    //根据元素值,计算其位置
	int pos=abs(key)%hashmap.size;
	HashNode *pointer=&(hashmap.table[pos]);
	//在当前链表遍历查找该结点
	while(pointer!=NULL){
			if(pointer->data.value==value) 
	            return pointer->data.key;
	        else
	        	pointer=pointer->next;
		} 
	//未找到,返回-1
	return -1;
}

③Put

//f3_Put,与建立HashMap时插入元素的方法相同
int Put(HashMap hashmap,int key,int value){
     int pos=abs(value)%hashmap.size;
     HashNode *pointer=&(hashmap.table[pos]);
     if(pointer->data.val==INT_MIN) 
        {
         pointer->data.val=value;
         pointer->data.key=key;
        }
	else{
        while(pointer->next!=NULL)
             pointer=pointer->next;
        HashNode *hnode=(HashNode *)malloc(sizeof(HashNode));
        hnode->data.key=key;
        hnode->data.val=value;
        hnode->next=NULL;
        pointer->next=hnode;
   } 
   return 1;
}	

④PrintHashMap

//f4_PrintHashMap 
void PrintHashMap(HashMap* hashmap){
    printf("%===========PrintHashMap==========\n");
	int i=0;
	HashNode *pointer;
	while(i<hashmap->size){
		pointer=&(hashmap->table[i]);
		while(pointer!=NULL){
            if(pointer->data.val!=INT_MIN)
              printf("%10d",pointer->data.val);
			else 
              printf("        [ ]");
			pointer=pointer->next;
		}
        printf("\n---------------------------------");
		i++;
		printf("\n");
	}
    printf("===============End===============\n");
}

⑤DestoryHashMap

//f5_DestoryHashMap
void DestoryHashMap(HashMap *hashmap){
    int i=0;
    HashNode *hpointer;
    while(i<hashmap->size){
        hpointer=hashmap->table[i].next;
        while(hpointer!=NULL){
            
            hashmap->table[i].next=hpointer->next;
            //逐个释放结点空间,防止内存溢出
            free(hpointer);
            hpointer=hashmap->table[i].next;
            }
        //换至下一个结点
        i++;
    }
    free(hashmap->table);
    free(hashmap);
    printf("Destory hashmap Success!");
}

3.运行示例

主函数如下:

int main(int argc, char **argv)
{
		int nums[]={34,54,32,32,56,78};
		//创建HashMap
   	    HashMap *hashmap=CreateHashMap(nums,6);
    	PrintHashMap(hashmap);
    	//查找元素
    	printf("%d\n",Get(*hashmap,78));

    	DestoryHashMap(hashmap);
    	getchar();
		return 0;
}

运行结果:

HashMap运行结果

  • 17
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
实现哈希表(Hashmap)的基本思路是将键值对存储在一个数组中,通过哈希函数将键转换为数组的索引,然后将值存储在该索引处。 下面是一个简单的C语言实现哈希表的例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define TABLE_SIZE 100 typedef struct { char* key; int value; } hash_node; hash_node* hash_table[TABLE_SIZE]; int hash_function(char* key) { int hash = 0; for (int i = 0; i < strlen(key); i++) { hash += key[i]; } return hash % TABLE_SIZE; } void insert(char* key, int value) { int index = hash_function(key); if (hash_table[index] == NULL) { hash_table[index] = malloc(sizeof(hash_node)); hash_table[index]->key = strdup(key); hash_table[index]->value = value; } else { hash_node* node = hash_table[index]; while (node->next != NULL) { node = node->next; } node->next = malloc(sizeof(hash_node)); node->next->key = strdup(key); node->next->value = value; } } int search(char* key) { int index = hash_function(key); hash_node* node = hash_table[index]; while (node != NULL) { if (strcmp(node->key, key) == 0) { return node->value; } node = node->next; } return -1; } int main() { insert("apple", 1); insert("banana", 2); insert("orange", 3); printf("apple = %d\n", search("apple")); printf("banana = %d\n", search("banana")); printf("orange = %d\n", search("orange")); return 0; } ``` 这个例子中,我们使用一个简单的哈希函数,将字符串中所有字符的ASCII码之和作为哈希值。我们将哈希表的大小设为100,即数组的长度为100。如果两个不同的键具有相同的哈希值,我们采用链表的方式来处理冲突。 在主函数中,我们插入了三个键值对,然后通过搜索函数查找对应的值。运行程序,可以得到以下输出: ``` apple = 1 banana = 2 orange = 3 ``` 这表明我们的哈希表实现是正确的。当然,这只是一个简单的实现,实际应用中需要考虑更多的因素,例如哈希函数的设计、冲突处理的效率等。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值