哈希表C开源的uthash的简单初步封装(二)

概述:在上一篇博客中,简单封装了key为int类型的哈希表的增删,遍历等函数,但是在上一篇封装中,函数均是可见的,可能并不安全,所以这一次就将函数封装到结构体,像使用c++一样,直接通过结构体就可以运行函数。所有函数操作都是静态的,这样操作更加方便快捷。此次封装了key为int, char[],char * , void *四种类型的哈希表结构。在多线程中,依旧是不安全的,后期有时间会加入互斥锁,读写锁到里面,用于多线程。

1,这里就说一下key类型为char []的封装,先看.h文件,先封装一个hash的结构体,再定义一个hash控制结构体,将操作函数放在hash控制结构体,同时将hash的结构体也放入hash控制结构体。

#ifndef _SKY_HASH_H_
#define _SKY_HASH_H_

#include <stdlib.h>
#include "uthash.h"

#define KEY_ARR_SIZE      16
typedef struct hash_arr hash_arr_t;
typedef void (*hash_arr_cb_t)(hash_arr_t *, void *);

/*key 为char[]类型结构体封装*/
typedef hash_arr_t *(*hash_arr_find_t)(hash_arr_t **, char *);
typedef int (*hash_arr_add_t)(hash_arr_t **, char *, void *);
typedef int (*hash_arr_del_t)(hash_arr_t **, char *);
typedef void (*hash_arr_delall_t)(hash_arr_t **);
typedef int (*hash_arr_count_t)(hash_arr_t **);
typedef void (*hash_arr_ergodic_t)(hash_arr_t **, hash_arr_cb_t, void *);
typedef struct hash_arr_ctl hash_arr_ctl_t;


struct hash_arr {  
    char key[KEY_ARR_SIZE];    /* key */  
    void *data;                /*数据*/
    UT_hash_handle hh;         /* makes this structure hashable */  
};

struct hash_arr_ctl {
    hash_arr_t *hash;

    hash_arr_find_t find;
    hash_arr_add_t add;
    hash_arr_del_t del;
    hash_arr_delall_t delall;
    hash_arr_count_t count;
    hash_arr_ergodic_t ergodic;
};

/*char []类型key相关操作函数*/
void hash_arr_create(hash_arr_ctl_t *ha);

2,我们再看一下sky_hash.c文件,这个就没啥了,主要就是uthash的函数使用及简单封装,看uthash操作手册就可以看懂了。

#include <stdio.h>
#include <stdlib.h>
#include "uthash.h"
#include "sky_hash.h"

/*****************************************************************************
                    下方封装key为char []类型的增删,遍历等操作。
                                                            By Sky(Peace&Love)
******************************************************************************/

/*查找键值*/
hash_arr_t *hash_arr_find(hash_arr_t **hashlist, char key[])
{
    hash_arr_t *hd = NULL;
    HASH_FIND_STR(*hashlist,key,hd);
    return hd;
}

/*添加键值对*/
int hash_arr_add(hash_arr_t **hashlist, char key[], void *data)
{
    hash_arr_t *hd = hash_arr_find(hashlist,key);
    if (NULL == hd) {
        hd = (hash_arr_t *)malloc(sizeof(hash_arr_t));
        strncpy(hd->key,key,KEY_ARR_SIZE);
        hd->data = data;
        HASH_ADD_STR(*hashlist,key,hd);
    } else {
        return -1;
    }
    return 0;
}


/*删除指定键值对*/
static int hash_arr_del(hash_arr_t **hashlist, char key[])
{
    hash_arr_t *hd = hash_arr_find(hashlist,key);
    if (NULL == hd) {
        return -1;
    }
    HASH_DEL(*hashlist, hd);
    if (NULL != hd->data) {
        free(hd->data);
        hd->data = NULL;
    }
    free(hd);
    hd = NULL;
    return 0;
}

/*删除所有键值对*/
static void hash_arr_delall(hash_arr_t **hashlist)
{
    hash_arr_t *hd,*tmp;
    HASH_ITER(hh, *hashlist, hd, tmp) {
        HASH_DEL(*hashlist, hd);  
        if (NULL != hd->data) {
            free(hd->data);
            hd->data = NULL;
        }
        free(hd);
        hd = NULL;
    }
    if (NULL != *hashlist) {
        free(*hashlist);
        *hashlist = NULL;
    }
}

/*遍历哈希表*/
static void hash_arr_ergodic(hash_arr_t **hashlist, hash_arr_cb_t callback, void *arg)
{
    hash_arr_t *hd,*tmp;
    HASH_ITER(hh, *hashlist, hd, tmp) {
        callback(hd,arg);
    }
}

/*获取哈希表项目个数*/
static int hash_arr_count(hash_arr_t **hashlist)
{
    return HASH_COUNT(*hashlist);
}

/*key为char []类型的哈希表创建初始化*/
void hash_arr_create(hash_arr_ctl_t *ha)
{
    ha->hash = NULL;

    ha->find = hash_arr_find;
    ha->add = hash_arr_add;
    ha->del = hash_arr_del;
    ha->delall = hash_arr_delall;
    ha->count = hash_arr_count;
    ha->ergodic = hash_arr_ergodic;
}

3,我们做一个测试程序,验证封装函数的正确性。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "./hash/sky_hash.h"


typedef struct sky sky_t;
/*只做测试使用,可以自定义*/
struct sky {
    int num;
    /*用户可以自己再增加字段*/
};

void callback_keyarr(hash_arr_t *hd, void *arg)
{
    sky_t *value = hd->data;
    printf("key:%s,num:%d\n",hd->key,value->num);
}

void test_keyarr()
{
    hash_arr_ctl_t *ha = (hash_arr_ctl_t *)malloc(sizeof(hash_arr_ctl_t));
    hash_arr_create(ha);

    char *key[] = {"bboy","born","sky","peace","love"};
    int i;
    /*哈希表中添加数据*/
    for (i = 0 ; i < 5 ; i ++) {
        sky_t *value = (sky_t *)malloc(sizeof(sky_t));
        value->num = i;
        if (0 != ha->add(&ha->hash,key[i],value)) {
            printf("hash add failed\n");
            free(value);
        }
    }
    printf("ha:%p\n",ha->hash);
    /*遍历哈希表*/
    ha->ergodic(&ha->hash,callback_keyarr,NULL);
    /*获取哈希表项目个数*/
    int count = ha->count(&ha->hash);
    printf("hash count:%d\n",count);
    /*查找哈希表*/
    char fkey[16] = {0};
    char *bb = "born";
    memcpy(fkey,bb,5);
    hash_arr_t *node = ha->find(&ha->hash,fkey);
    if (NULL != node) {
        sky_t *value = node->data;
        printf("find key[born] value num = %d\n",value->num);
        /*修改key对应的数据值*/
        value->num = 100;
    } else {
        printf("not found\n");
    }
    /*删除指定项目*/
    ha->del(&ha->hash,"bboy");
    /*遍历哈希表*/
    ha->ergodic(&ha->hash,callback_keyarr,NULL);
    /*删除整个哈希表*/
    ha->delall(&ha->hash);
    printf("ha:%p\n",ha->hash);
    free(ha);
}

int main()
{
    test_keyarr();
    return 0;
}

4,运行结果如下:
这里写图片描述

5,所有代码传到码云,develop分支。需要的话可以看下。地址在上一篇有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种常用的数据结构,可以高效地存储和查找数据。在通讯录中使用哈希表可以快速地定位需要查找的联系人信息。 在C语言中,哈希表的设计主要分为两个部分:哈希函数和哈希表结构。 哈希函数是将关键字映射到哈希表中的位置的函数。常用的哈希函数有取余法、乘法散列法、平方取中法等。在通讯录中,我们可以使用联系人姓名或者电话号码作为关键字,通过哈希函数将其映射到哈希表中。 哈希表结构包含了哈希表的基本元素,包括哈希表数组、存储数据的结构体以及相关操作函数。在通讯录中,我们可以使用一个结构体来存储联系人的信息,如姓名、电话号码等,然后将其存储到哈希表中。同时,我们需要设计插入、删除、查找等操作函数来对哈希表进行操作。 以下是一个简单哈希表通讯录的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LEN 100 // 姓名最大长度 #define HASH_SIZE 101 // 哈希表大小 // 联系人结构体 typedef struct Contact { char name[MAX_LEN]; char phone[MAX_LEN]; struct Contact *next; } Contact; // 哈希表结构体 typedef struct HashTable { Contact *table[HASH_SIZE]; } HashTable; // 哈希函数 int hash(char *name) { int len = strlen(name); int sum = 0; for (int i = 0; i < len; i++) { sum += name[i]; } return sum % HASH_SIZE; } // 初始化哈希表 void init(HashTable *ht) { for (int i = 0; i < HASH_SIZE; i++) { ht->table[i] = NULL; } } // 插入联系人 void insert(HashTable *ht, char *name, char *phone) { int index = hash(name); Contact *node = (Contact *)malloc(sizeof(Contact)); strcpy(node->name, name); strcpy(node->phone, phone); node->next = NULL; if (ht->table[index] == NULL) { ht->table[index] = node; } else { Contact *temp = ht->table[index]; while (temp->next != NULL) { temp = temp->next; } temp->next = node; } } // 查找联系人 Contact *find(HashTable *ht, char *name) { int index = hash(name); Contact *temp = ht->table[index]; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { return temp; } temp = temp->next; } return NULL; } // 删除联系人 void delete(HashTable *ht, char *name) { int index = hash(name); Contact *temp = ht->table[index]; if (temp == NULL) { return; } else if (strcmp(temp->name, name) == 0) { ht->table[index] = temp->next; free(temp); return; } while (temp->next != NULL && strcmp(temp->next->name, name) != 0) { temp = temp->next; } if (temp->next != NULL) { Contact *del = temp->next; temp->next = del->next; free(del); return; } } int main() { HashTable ht; init(&ht); // 插入联系人 insert(&ht, "张三", "123456"); insert(&ht, "李四", "234567"); // 查找联系人 Contact *contact1 = find(&ht, "张三"); if (contact1 != NULL) { printf("姓名:%s,电话:%s\n", contact1->name, contact1->phone); } // 删除联系人 delete(&ht, "张三"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值