Hashmap在C中按字母顺序排序键时不应';不要那样做
我是一名机械工程师的学生,我必须选修这门关于C编程的必修课,我对C编程知之甚少。其中一个任务是创建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 &
#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)