繁体   English   中英

C - 单独的链接 Hash 表 - Output 和空间问题

[英]C - Separate Chaining Hash Table - Output and Space Issues

所以基本上我写了一个程序来初始化、插入和 output 整个 hash 表。 我认为我做得很好,但有很多问题。

第一个问题是,有些名字显示有一个额外的奇怪字符,为什么?

第二个问题是,我只能输入 <8 的大小参数(用于初始化(大小)函数)。 高于 7 的任何东西都会 output “空间不足?” 但是为什么?:我认为我在大学里学到的东西很好地管理了这个空间:((

请帮忙!

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

typedef struct list_node *node_ptr;

struct list_node
{
    node_ptr next;
    char *key;
    char *value;
    
};

typedef node_ptr LIST;
typedef node_ptr position;

struct hash_table
{
    LIST *list_ptr_arr;
    unsigned int table_size;
};

typedef struct hash_table *HASHTABLE;

unsigned long long int
hash(const char *key, unsigned int hash_size)
{

    unsigned long long int hash;

    for(int i = 0; key[i]; i++)
    {
        hash = (hash<<32)+key[i];
    }

    return (hash%hash_size);

}

unsigned int 
next_prime(int number)
{

    int j;

    for(int i = number; ; i++)
    {
        for(j = 2; j<i; j++)
        {
            if(i%j == 0){break;}
        }

        if(i==j){return j;}
    }
}

HASHTABLE
initialize(unsigned int table_size)
{
    HASHTABLE H;

    H = (HASHTABLE) malloc(sizeof(struct hash_table));
    if(H==NULL){printf("Out of Space!"); return 0;}

    H->table_size = next_prime(table_size);

    H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
    if(H->list_ptr_arr==NULL){printf("Out of Space!"); return 0;}

    H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);

    for(unsigned int i = 0; i<H->table_size; i++)
    {
        if(H->list_ptr_arr[i]==NULL){printf("Out of Space!"); return 0;}

        H->list_ptr_arr[i]=NULL;
    }


    return H;
    
}

position
set(const char *key, const char *value)
{
    position entry = (position) malloc(sizeof(struct list_node));
    entry->value = (char*) malloc(strlen(value)+1);
    entry->key = (char*) malloc(strlen(key)+1);
    strncpy(entry->key,key,strlen(key));
    strncpy(entry->value,value,strlen(value));
    entry->next = NULL;

    return entry;
}

void
insert(const char *key, const char *value, HASHTABLE H)
{
    unsigned int slot = hash(key, H->table_size);
    node_ptr entry = H->list_ptr_arr[slot];

    node_ptr prev;

    if(entry==NULL)
    {
        
        H->list_ptr_arr[slot] = set(key, value);
        return;
    }

    while(entry!=NULL)
    {
        if(strcmp(entry->key, key)==0)
        {
            free(entry->value);
            entry->value = malloc(strlen(value)+1);
            strncpy(entry->value,value,strlen(value));
            return;
        }

        prev = entry;
        entry = prev->next;

    }

    
    prev->next = set(key, value);

}

void
dump(HASHTABLE H)
{

    for(unsigned int i = 0; i<H->table_size; i++)
    {
        position entry = H->list_ptr_arr[i];

        if(H->list_ptr_arr[i]==NULL){continue;}

        printf("slot[%d]: ", i);

        for(;;)
        {
            printf("%s|%s -> ", entry->key, entry->value);

            if(entry->next == NULL)
            {
                printf("NULL");
                break;
            }

            entry = entry->next;
        }

        printf("\n");

    }

}


int main()
{
    
    HASHTABLE H = initialize(7);
    insert("name1", "David", H);
    insert("name2", "Lara", H);
    insert("name3", "Slavka", H);
    insert("name4", "Ivo", H);
    insert("name5", "Radka", H);
    insert("name6", "Kvetka", H);
    dump(H);
  
    return 0;   
    
}

然后我试着改变一下:

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

typedef struct list_node *node_ptr;

struct list_node
{
    node_ptr next;
    char *key;
    char *value;
    
};

typedef node_ptr LIST;
typedef node_ptr position;

struct hash_table
{
    LIST *list_ptr_arr;
    unsigned int table_size;
};

typedef struct hash_table *HASHTABLE;

unsigned long long int
hash(const char *key, unsigned int hash_size)
{

    unsigned long long int hash;

    for(int i = 0; key[i]; i++)
    {
        hash = (hash<<32)+key[i];
    }

    return (hash%hash_size);

}

unsigned int 
next_prime(int number)
{

    int j;

    for(int i = number; ; i++)
    {
        for(j = 2; j<i; j++)
        {
            if(i%j == 0){break;}
        }

        if(i==j){return j;}
    }
}

HASHTABLE
initialize(unsigned int table_size)
{
    HASHTABLE H;

    H = (HASHTABLE) malloc(sizeof(struct hash_table));
    if(H==NULL){printf("Out of Space!1"); return 0;}

    H->table_size = next_prime(table_size);

    H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
    if(H->list_ptr_arr==NULL){printf("Out of Space!2"); return 0;}

    H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);

    for(unsigned int i = 0; i<H->table_size; ++i)
    {
        if(H->list_ptr_arr[i]==NULL){printf("Out of Space!3"); return 0;}

        H->list_ptr_arr[i]->value="HEAD";
        H->list_ptr_arr[i]->next=NULL;
    }


    return H;
    
}


void
insert(const char *key, const char *value, HASHTABLE H)
{
    unsigned int slot = hash(key, H->table_size);
    LIST entry = H->list_ptr_arr[slot], newNode;



   

    newNode = (position) malloc(sizeof(struct list_node));
    if(newNode==NULL){printf("Out of Space4!"); return;}
    newNode->next = entry->next;
    strncpy(newNode->key,key,strlen(key));
    strncpy(newNode->value,value,strlen(value));
    entry->next = newNode;

}

void
dump(HASHTABLE H)
{

    for(unsigned int i = 0; i<H->table_size; i++)
    {
        position entry = H->list_ptr_arr[i];
        position p = entry->next;

        if(p==NULL){continue;}

        printf("slot[%d]: ", i);

        for(;;)
        {
            printf("%s|%s -> ", p->key, p->value);

            if(p->next == NULL)
            {
                printf("NULL");
                break;
            }

            p = p->next;
        }

        printf("\n");

    }

}


int main()
{
    
    HASHTABLE H = initialize(4);
    insert("name1", "David", H);
    insert("name2", "Lara", H);
    insert("name3", "Slavka", H);
    insert("name4", "Ivo", H);
    insert("name5", "Radka", H);
    insert("name6", "Kvetka", H);
    dump(H);
  
    return 0;   
    
}

   

谢谢!

我修改了第二段代码,它在我的电脑上运行正常。

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

#define MAX_SIZE 256

// typedefing struct list_node multiple times is confusing, so I remove these typedefs
struct list_node {
    struct list_node *next;
    // strings need storage space in the memory,
    // declaring key and value as array here can save some calls to malloc()
    char key[MAX_SIZE];
    char value[MAX_SIZE];
};

struct hash_table {
    struct list_node **list_ptr_arr;
    unsigned int table_size;
};

// it's better not to hide pointer type using typedef
typedef struct hash_table HASHTABLE;

unsigned long long int hash(const char *key, unsigned int hash_size) {
    // hash is not initialized originally (the value is choosed randomly)
    unsigned long long int hash = 5;

    for (int i = 0; key[i]; i++) {
        hash = (hash << 32) + key[i];
    }

    return (hash%hash_size);
}

unsigned int next_prime(int number) {
    int j;

    for (int i = number; ; i++) {
        for (j = 2; j < i; j++) {
            if (i%j == 0) { break; }
        }

        if (i == j) { return j; }
    }
}

HASHTABLE *initialize(unsigned int table_size) {
    HASHTABLE *H;

    // you don't need to type cast malloc() result in C
    H = malloc(sizeof(*H));

    H->table_size = next_prime(table_size);
    
    // I suppose list_ptr_arr is a pointer to an array of struct list_node * object
    H->list_ptr_arr = malloc(sizeof(*(H->list_ptr_arr)) * H->table_size);

    for (unsigned int i = 0; i < H->table_size; ++i) {
        // malloc() for H->list_ptr_arr only allocated area for struct list_node * array, the struct list_node pointed to is not allocated yet, so malloc() here
        H->list_ptr_arr[i] = malloc(sizeof(*(H->list_ptr_arr[i])));
        strcpy(H->list_ptr_arr[i]->value, "HEAD");
        H->list_ptr_arr[i]->next = NULL;
    }

    return H;
}


void insert(const char *key, const char *value, HASHTABLE *H) {
    unsigned int slot = hash(key, H->table_size);
    struct list_node *entry = H->list_ptr_arr[slot], *newNode;

    newNode = malloc(sizeof(*newNode));

    newNode->next = entry->next;
    // strlen() doesn't count the '\0', just use strcpy here
    strcpy(newNode->key, key);
    strcpy(newNode->value, value);
    entry->next = newNode;
}

void dump(HASHTABLE *H) {

    for (unsigned int i = 0; i < H->table_size; i++) {
        struct list_node *entry = H->list_ptr_arr[i];
        struct list_node *p = entry->next;

        if (p == NULL) { continue; }

        printf("slot[%d]: ", i);

        for (;;) {
            printf("%s|%s -> ", p->key, p->value);

            if (p->next == NULL) {
                printf("NULL");
                break;
            }

            p = p->next;
        }

        printf("\n");
    }
}


int main() {

    HASHTABLE *H = initialize(4);
    insert("name1", "David", H);
    insert("name2", "Lara", H);
    insert("name3", "Slavka", H);
    insert("name4", "Ivo", H);
    insert("name5", "Radka", H);
    insert("name6", "Kvetka", H);
    dump(H);

    return 0;
}

PS 不要忘记释放哈希表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM