Hashmap在C中按字母顺序排序键时不应';不要那样做

Hashmap在C中按字母顺序排序键时不应';不要那样做,c,linked-list,hashmap,C,Linked List,Hashmap,我是一名机械工程师的学生,我必须选修这门关于C编程的必修课,我对C编程知之甚少。其中一个任务是创建hashmap。现在,我的很多代码都是从不同的教程站点复制粘贴的,因为课程教授告诉我们要教自己如何用C语言编程,除了简单的基础知识外,什么都没有解释 这是我到目前为止的代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include &

我是一名机械工程师的学生,我必须选修这门关于C编程的必修课,我对C编程知之甚少。其中一个任务是创建hashmap。现在,我的很多代码都是从不同的教程站点复制粘贴的,因为课程教授告诉我们要教自己如何用C语言编程,除了简单的基础知识外,什么都没有解释

这是我到目前为止的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include "hashmap.h"


size_t key_space_global;

char *strdup (const char *s) {
    char *d = malloc (strlen (s) + 1);   
    if (d == NULL) return NULL;          
    strcpy (d,s);                        
    return d;                            
}

struct Bucket {
    const char* key;
    void* data;
    struct Bucket *next;
};

struct HashMap {
    size_t key_space;
    Bucket **hash_table;
    hashfunc hash;
};

unsigned int hash(const char *key) {
    unsigned int length, sum = 0, i;
    length = strlen(key);
    for(i = 0; i < length; i++) {
        sum = sum + key[i];
    }
    return (sum%key_space_global);
}

HashMap *create_hashmap(size_t key_space) {
    if(key_space < 1){
        printf("invalid size");
        return NULL;
    }
    HashMap *pointer = calloc(1, sizeof(HashMap));
    pointer -> key_space = key_space;
    key_space_global = key_space;
    pointer -> hash = hash;
    pointer -> hash_table = malloc(sizeof(Bucket*)*key_space);
    unsigned int i;
    for(i = 0; i < key_space; i++){
        pointer -> hash_table[i] = NULL;
    }
    return pointer;
}

Bucket *create_bucket(const char *key, void *data) {
    Bucket *pointer = calloc(1,sizeof(Bucket));
    pointer -> key = strdup(key);
    pointer -> data = data;
    pointer -> next = NULL;
    return pointer;
}

void insert_data(HashMap *hm , const char *key,void *data, void*  (*resolve_collision)(void *old_data, void *new_data)) {
    unsigned int index = hm -> hash(key);
    if(hm -> hash_table[index] == NULL){
        hm -> hash_table[index] = create_bucket(key,data);
    }else{ 
        Bucket *next = hm -> hash_table[index] -> next;
        while(next != 0){
            if(strcmp(key, hm -> hash_table[index] -> key) == 0){
                resolve_collision(next -> data, data);
                return;
            }
            next = next -> next;
        } 
        next = create_bucket(key,data);
        next -> next = hm -> hash_table[index]; 
        hm -> hash_table[index] = next; 
    }
}

void* get_data(HashMap *hm, const char *key) {
    unsigned int index;
    index = hm -> hash(key);
    Bucket *pointer = hm -> hash_table[index];
    if(pointer == NULL){
        return NULL;
    }else if(pointer != NULL){
        Bucket *next = hm -> hash_table[index];
        while(next != NULL){
            if(strncmp(hm -> hash_table[index] -> key, key, 5) == 0) {
                return pointer -> data;
            }
        }
    }
    return NULL;
}

void iterate(HashMap *hm, void (*callback)(const char *key, void *data)){
unsigned int i;
    for(i = 0; i < hm -> key_space; i++){
        Bucket *pointer;
        for(pointer = hm -> hash_table[i]; pointer !=NULL; pointer = pointer -> next){
            callback(pointer -> key,pointer -> data);
        }
    }
}

void remove_data(HashMap *hm, const char key[], void (*destroy_data)(void* data)) {
    unsigned int index = hm -> hash(key);
    Bucket *temp;
    Bucket *next = hm -> hash_table[index];
    if(hm -> hash_table[index] == NULL){
        return;
    }else{ 
        while(next != NULL){
            if(strcmp(key, next -> key) == 0){
                if(destroy_data != NULL){
                    destroy_data(next -> data);
                }
                temp = next;
                free(next -> next);
                next -> next = NULL;
                free(next -> key);
                next -> key = NULL;
                hm -> hash_table[index] -> key = NULL;
                free(next); 
            }
            next = NULL;
            hm -> hash_table[index] = NULL;
        }
    }
}

void delete_hash_table(HashMap *hm) {
    size_t i;
    for (i = 0; i < hm -> key_space; ++i) {
        Bucket *pointer;
        Bucket *next;
        for (pointer = hm -> hash_table[i]; pointer != NULL; pointer = next) {
            free(pointer -> key);
            pointer -> key = NULL;
            next = pointer -> next;
            free(pointer);
        }
        hm -> hash_table[i] = NULL;
    }
}

void delete_hashmap(HashMap *hm, void (*destroy_data)(void* data)) {
    if(hm == NULL)
    return;
    if(destroy_data != NULL){
        destroy_data(hm -> hash);
        hm -> hash = NULL;
        free(create_hashmap(hm -> key_space));
        delete_hash_table(hm);
    }
    free(hm -> hash_table);
    free(hm);
}
它必须通过教授提供的测试计划:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "hashmap.h"

#ifdef COUNTING_WORDS
#include "wordcount.h"
#endif

size_t mystrlen(const char *str) {
    return strlen(str) + 1;
}

void print_element(const char *key, void *data) {
    printf("(\"%s\", %s)\n", key, (char*)data);
}

void *resolve_collision(void *old_value, void *new_value) {
    return new_value;
}

unsigned your_own_hash(const char *key) {
    return (unsigned) strlen(key) + (unsigned) *key;
}

int main() {
    unsigned int key_space = 1024;
    HashMap * hm = create_hashmap(key_space);

    char * string_1 = "TI2725-C";
    char * string_2 = "Embedded";
    char * string_3 = "Software";
    const char * key_1    = "ab";
    const char * key_2    = "cd";
    const char * key_3    = "ad";
    const char * key_4    = "xy";

    // Insert ("ab" -> "TI2725-C").
    insert_data(hm, key_1, string_1, resolve_collision);
    assert(memcmp(get_data(hm, key_1), string_1, mystrlen(string_1)) == 0);

    // Insert ("cd" -> "Embedded").
    insert_data(hm, key_2, string_2, resolve_collision);
    assert(memcmp(get_data(hm, key_2), string_2, mystrlen(string_2)) == 0);

    // Insert ("ad" -> "Software").
    insert_data(hm, key_3, string_3, resolve_collision);
    assert(memcmp(get_data(hm, key_3), string_3, mystrlen(string_3)) == 0);

    // Insert ("ab" -> "Embedded").
    insert_data(hm, key_1, string_2, resolve_collision);
    assert(memcmp(get_data(hm, key_1), string_2, mystrlen(string_2)) == 0);

    // Get data for a not inserted key.
    assert(get_data(hm, key_4) == NULL);

    // Iterate the hash map
    iterate(hm, print_element);

    #ifdef NEW_HASH
    set_hash_function(hm, your_own_hash);

    printf("\nHERE WE GO AGAIN!\n\n");

    // Iterate the hash map 
    iterate(hm, print_element);
    #endif

    // Delete key "ab".
    remove_data(hm, key_1, NULL);
    assert(get_data(hm, key_1) == NULL);

    // Delete key "cd".
    remove_data(hm, key_2, NULL);
    assert(get_data(hm, key_2) == NULL);

    // Delete key "ad".
    remove_data(hm, key_3, NULL);
    assert(get_data(hm, key_3) == NULL);

    // Delete the hash map.
    delete_hashmap(hm, NULL);

    #ifdef COUNTING_WORDS
    // Create a temporary file
    FILE *stream = tmpfile();

    // Write to the stream
    fprintf(stream, "foo bar_, baz!\n");
    fprintf(stream, "foo\t\"bar\".\n");
    fprintf(stream, "foo?\n");

    // Set the position to the start of the stream
    fseek(stream, 0, SEEK_SET);

    // Count the words
    count_words(stream);

    // Close the file
    fclose(stream);
    #endif

    return 0;
}
虽然它应该给我这个:

("ab", TI2725-C)
("cd", Embedded)
("ad", Software)
("ab", Embedded)
我注意到我得到的结果是按字母顺序排序的,据我所知,这不是hashmap应该做的。我认为我的链表有问题,它是在insert_data()函数中设置的,或者在get_data()函数中读取数据有问题。有人能帮我吗


此外,我们必须使用valgrind作为调试工具,每当我使用它时,它告诉我我有10个alloc和9个free,它告诉我strdup函数中的malloc从未被释放过,我读到strdup函数中的malloc是一个很难释放的工具,我仍然没有弄清楚这一点。有人能帮我吗?

如果你有时间的话,这可能会有帮助,一位教授告诉你要自学C???他的工作是什么?你确定顺序对测试很重要吗?我认为这应该没问题,因为它正在传递所有的
断言
扫描。您提供的任何引用都不能对映射进行排序?hashmap从不随机存储数据(注意该术语),而是使用算法来计算散列。但是,即使是随机的,为什么不包括存储按偶然性排序的键呢?如果你有时间的话,这可能会有所帮助,一位教授的课程告诉你要自学C???他的工作是什么?你确定顺序对测试很重要吗?我认为这应该没问题,因为它正在传递所有的
断言
扫描。您提供的任何引用都不能对映射进行排序?hashmap从不随机存储数据(注意该术语),而是使用算法来计算散列。但即使是随机的,为什么不包括存储按偶然性排序的密钥呢?
("ab", Embedded)
("ab", TI2725-C)
("ad", Software)
("cd", Embedded)
("ab", TI2725-C)
("cd", Embedded)
("ad", Software)
("ab", Embedded)