C语言中实现hash表

引入所需的头文件

一般高级语言都会有封装好的hash存储结构,使用c语言的时候同样也可以实现hash,我们自己实现的话逻辑会非常复杂,并且可能会出错,这里我们需要利用一个第三方开源的头文件uthash.h来实现,大家可以在github或者码云上面找到这个文件。

另外,在官网也有它的用法介绍,链接附上

在这里插入图片描述
下面我们利用这个头文件来实现一个hash结构,实现添加元素、删除元素、统计元素个数、遍历元素等功能。

hash的实现

官方文档说我们需要实现这样的一个结构体,以便我们实现hash表这个结构。UT_hash_handle hh;是我们把这个结构体变成hash表所必须的一个字段,我们只需要在结构体中定义即可。
在这里插入图片描述

#include <stdio.h>   /* gets */
#include <stdlib.h>  /* atoi, malloc */
#include <string.h>  /* strcpy */
#include "uthash.h"

struct MyStruct{
    
    
	int key;
	char value[10];
	UT_hash_handle hh;
};

首先我们需要声明一个hash,

struct MyStruct *g_user = NULL;   /* important! initialize to NULL */

添加元素

void addUser(int ikey,char * ivalue){
    
    
	struct MyStruct *s;
	HASH_FIND_INT(g_user,&ikey,s);
	if(s==NULL){
    
    
		s=(struct MyStruct *)malloc(sizeof(struct MyStruct));
		s->key=ikey;
		HASH_ADD_INT(g_user,key,s); 
	}
	strcpy(s->value,ivalue);
}

根据key获取元素

struct MyStruct * getUser(int key){
    
    
	struct MyStruct *s;
	HASH_FIND_INT(g_user,&key,s);
	return s;
}

根据key删除元素

void deleteUser(int key){
    
    
	struct MyStruct *s = NULL;
	HASH_FIND_INT(g_user,&key,s);
	if(s!=NULL){
    
    
		HASH_DEL(g_user,s);
		free(s);
	}
}

获取元素的总个数

int getNum(){
    
    
	return HASH_COUNT(g_user);
}

删除所有的元素

void delAll(){
    
    
	struct MyStruct *current,*temp;
	HASH_ITER(hh,g_user,current,temp){
    
    
		HASH_DEL(g_user,current);
		free(current);
	}
	
}

判断是否包含某个键值为key的元素

int containUser(int key){
    
    
	struct MyStruct *s = NULL;
	HASH_FIND_INT(g_user,&key,s);
	return s!=NULL;
}

遍历输出所有的元素

void printUsers() {
    
    
    struct MyStruct *s;
    for(s=g_user; s != NULL; s=(struct MyStruct*)(s->hh.next)) {
    
    
        printf("user id %d: name %s\n", s->key, s->value);
    }
}

基础的演示

int main(int argc, char *argv[]) {
    
    
    char in[10];
    int id=1, running=1,i;
    struct MyStruct  *s;
    unsigned num_users;

    while (running) {
    
    
        printf(" 1. add user\n");
        printf(" 2. contain user?\n");
        printf(" 3. find user\n");
        printf(" 4. delete user\n");
        printf(" 5. delete all users\n");
        printf(" 6. print users\n");
        printf(" 7. count users\n");
        printf(" 8. quit\n");
        gets(in);
        switch(atoi(in)) {
    
    
            case 1:
                printf("name?\n");
                addUser(id++, gets(in));
                break;
            case 2:
                printf("id?\n");
                i=atoi(gets(in));
                i = containUser(i);
                if(i)printf("Contain !\n");
                else printf("NO contain !\n");
                break;
            case 3:
                printf("id?\n");
                s = getUser(atoi(gets(in)));
                printf("user: %s\n", s ? s->value : "unknown");
                break;
            case 4:
                printf("id?\n");
                i = atoi(gets(in));
                deleteUser(i);
                break;
            case 5:
                delAll();
                break;
            case 6:
	            printUsers();
	            break;
            case 7:
                num_users=HASH_COUNT(g_user);
                printf("there are %u users\n", num_users);
                break;
            case 8:
                running=0;
                break;
        }
    }

//    delete_all();  /* free any structures */
    return 0;
}

另外,对于hash的实现,键值可以是不同的类型,可以是指针,也可以是另一个结构体类型,等等。官网介绍非常详细,可以直接参阅。

猜你喜欢

转载自blog.csdn.net/qq_45401910/article/details/130439440