【问题标题】:C - How to assign multiple values to the same key in a hashmap?C - 如何将多个值分配给哈希图中的同一个键?
【发布时间】:2019-04-14 09:01:48
【问题描述】:

作为一名新手程序员,我开始阅读The C Programming Language 以了解有关pointersstructs 的更多信息。

我目前正在学习 C 中的 hashmap。按照书中的示例,我创建了自己的 hashmap 来保存键值对:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STRING_SIZE 100
#define HASHSIZE 101

static struct map *hashtab[HASHSIZE]; /* pointer table */
unsigned hash(char *);  /* hashing function: form hash value for string s. used by both lookup and install*/
char *strdup(char *);

struct map {        /* creating a map structure */
    struct map *next;
    char *KEY;          /* KEY - pointer to a char - member of nlist*/
    char *object1;      /* object - pointer to a char - member of nlist*/
};

/* lookup function takes a pointer to char - s as an argument and returns a pointer to map structure */
struct map *lookup(char *s) {
    struct map *np;

    for (np = hashtab[hash(s)]; np != NULL; np = np->next) {
        if (strcmp(s, np->KEY) == 0) {
            return np;
        }
    }
    return NULL;
}

/* install function takes a pointer to a char - KEY, object and returns a pointer to map structure */
struct map *install(char *KEY, char *object1) {
    /* install: put (name, defn) in */
    /* Install uses lookup to determine whether the KEY being installed
       is already present. Proceeds to create a new entry or update*/
    struct map *np;
    unsigned hashval;

    if ((np = lookup(KEY)) == NULL) {
        np = (struct map *) malloc(sizeof(*np));
        if (np == NULL || (np->KEY = strdup(KEY)) == NULL) {
            return NULL;
        }
        hashval = hash(KEY);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    }
    else {
        free((void *)np->object1);
    }
    if ((np->object1 = strdup(object1)) == NULL) {
        return NULL;
    }
    return np;
}

然后我给键赋值如下:

int main(void) {

    struct map *table[4] = {
        (install("key1", "value1")),
        (install("key2", "value2")),
        (install("key3", "value3")),
        (install("key4", "value4"))
    };

    int i;

    for (i = 0; i < 4; i++) {
        printf("%s->%s\n", table[i]->KEY, table[i]->object);
    }
    printf("\n");
    return 0;
}

上面的代码运行良好,我可以分别将value1, ..., value4 分配给key1, ...,key4。但是,这不允许我为同一个键分配多个值。

假设我从一个文本文件中读取了以下内容:

key1 9000 600 Test1
key2 2000 600 Test2
key3 3000 120 Test3
key4 4000 120 Test4
.
.
key10 1000 560 Test10

我希望能够存储每个键并为其分配多个值。由于列数是固定的,也许我可以有一个表示一行的结构并将其放入地图中。

为此,需要修改install 以便能够为同一个键添加多个值。由于键是唯一的,lookupuninstall(我创建的用于删除键的函数)应该保持不变。

上面的代码完美运行,但是我正在寻找一个通用的解决方案来为同一个键添加多个值。

我应该如何继续打电话:

struct map *table[4] = {
    (install("key1", "9000" ,"600", "Test1")),   //key, object1, object2, object3
    (install("key2", "2000" ,"600", "Test2")),
    (install("key3", "3000" ,"120", "Test3")),
    (install("key4", "4000" ,"120", "Test4"))
};

另一个想法是:

/* key points to this struct */
struct Value {
    int i;
    int k;
    char *c;
};

typedef struct map {        /* creating a map structure */
    struct map *next;
    char *KEY;
    struct Value value;  /* place multiple values inside a struct*/
};

这是我卡住的地方:

struct map *insert(char *KEY, struct *Value) {
    struct map *np;
    unsigned hashval;

    if ((np = lookup(KEY)) == NULL) {
        np = (struct map *) malloc(sizeof(*np));
        if (np == NULL || (np->KEY = strdup(KEY)) == NULL) {
            return NULL;
        }
        hashval = hash(KEY);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    }
    else {
        free((struct Value*)np->value); //type cast cannot convert from 'Value' to 'Value*'

    }
    if ((np->Value = strdup(Value)) == NULL) { //map has no field value
        return NULL;
    }

    return np;
}

我搜索了以下问题,但无法提取有关如何在 C 中实现此功能的相关信息。

Hashmaps having multiple keys with multiple values

How can I assign multiple values to a hash key?

HashMap with multiple valued keys

如何实现一个接受分配给同一个键的多个值的哈希图?


编辑

正如 cmets 中所指出的,我使用的结构实际上可能不是哈希图,而是链表。但是book 明确表示第 144 页是一个哈希图。

【问题讨论】:

  • 提示:插入时,对待任何重复的键和对待冲突的方式完全相同。
  • 感谢会调查它。另外,为什么用指向同一个键的多个值实现一个哈希映射被认为是广泛的?如何改进我的问题?
  • 你这里的结构其实不是hash nap,它是一个链表。有很多方法可以实现你的目标,但传统的方法是:实际实现一个 hash nap,然后当你有一个 key 冲突时,在这个 key 下实现一个对象的链表。
  • 感谢您的评论。我不明白为什么我期望与我的示例(10)中这样少量的键发生键冲突。另外,为什么我所指的书将结构称为hasmap?这让我很困惑。
  • 一个实际的哈希表或哈希映射将每个键与精确的 one 值相关联。否则如何合理地从这样的数据结构中检索对象?但是一个值可以是您选择的任何类型,特别是可以是可以包含多个其他对象的类型,例如链表(或一个链表的头部)。

标签: c algorithm pointers data-structures linked-list


【解决方案1】:

这可能不是最好的解决方案,但由于上述 cmets,我得到了一些工作。我将多个值声明为指向char 的指针。如果我能改进这一点,请告诉我。

我还没有实现碰撞校正。

struct map {        /* creating a map structure */
    struct map *next;
    char *KEY;
    char *value1;
    char *value2;
    char *value3;
}; 

然后我将这些传递给插入函数。

struct map *insert(char *KEY, char *value1, char *value2, char *value3) {
    /* install: put (name, defn) in */
    /* Install uses lookup to determine whether the KEY being installed
       is already present. Proceeds to create a new entry or update*/
    struct map *np;
    unsigned hashval;

    if ((np = lookup(KEY)) == NULL) {
        np = (struct map *) malloc(sizeof(*np));
        if (np == NULL || (np->KEY = strdup(KEY)) == NULL) {
            return NULL;
        }
        hashval = hash(KEY);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    }
    else {
        free((void *)np->value1); //type cast cannot convert from 'Value' to 'Value*'
        free((void *)np->value2);
        free((void *)np->value3);
    }
    if ((np->time = strdup(value1)) == NULL) { //map has no field value
        return NULL;
    }
    if ((np->description = strdup(value2)) == NULL) { //map has no field value
        return NULL;
    }
    if ((np->duration = strdup(value3)) == NULL) { //map has no field value
        return NULL;
    }

    return np;
}

打印这些将给出指向四个值的键。

key1-&gt;value1 value2 value3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2015-02-08
    • 2012-02-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多