【问题标题】:hash table with linked list with bug带有带错误的链表的哈希表
【发布时间】:2013-07-23 09:04:50
【问题描述】:

我正在尝试用链表实现一个哈希表,但有一件事不能正常工作。 首先我制作了链表代码并确保它按预期工作,所以我发现它必须与哈希表实现或它们之间的交互有关。

我可以添加几个对象并再次找到它们而没有问题。但是如果两个或多个对象使用相同的键进行哈希处理,它们应该创建一个链表,但由于某种原因,我只能在链表中找到最新添加的对象。

之前添加的对象在那里,因为我可以成功删除我无法使用“lookup_string”函数找到的对象,因此我知道该对象存储在该位置。

所以函数“lookup_string”应该传递我在哈希表中搜索的对象,而“搜索”函数是我只实现链表时使用的函数。值得一提的是,“搜索”功能用于删除过程,但不在我只想查找对象的过程中,我不确定这是否重要,因为我相信“查找字符串”应该能够找到没有“搜索”功能的对象。

所以为了简单起见,我存储了两个对象:

对象 1:

name(key) = bcd
telephone number = 123

对象 2:

name(key) = ace
telephone number = 910

现在对象 1 和 2 都将获得相同的哈希键值,因此它们将存储在哈希表的同一个槽中。他们应该创建一个链接列表,但是当我搜索对象(菜单中的选择号 3)时,我只能找到最新添加的对象,即对象 2。 但是我仍然可以删除对象 1,它会告诉我对象 1 已成功删除。

代码:

struct post
{   
    char name[30];          
    int tel;                
    struct post *next;      
};

typedef struct post Post;

Post *head = NULL;  
Post *current;  

struct hash_table
{
    Post **table;
    int size;
};

typedef struct hash_table Post_table;

unsigned int Hash(Post_table *hash_table, char tempname[30])
{
    int i;
    int sum;
    int key;
    for(i = 0; i < strlen(tempname); i++)
    {
        sum += (int)tempname[i];
    }

    key = sum % hash_table->size;
    return key;
}

Post_table *create_hash_table(int size)
{
    int i;
    Post_table *new_table;

    if (size < 1)
    {
        return NULL;
    }

    //attempt to allocate memory for the table structure
    if ((new_table = malloc(sizeof(Post_table))) == NULL)
    {
        return NULL;
    }

    //attempt to allocate memory for the table itself
    if ((new_table->table = malloc(sizeof(Post *) * size)) == NULL)
    {
        return NULL;
    }

    //Initialize the elements of the table
    for(i = 0; i < size; i++)
    {
        new_table->table[i] = NULL;
        new_table->size = size;
    }
    return new_table;
}

Post *lookup_string(Post_table *hash_table, char tempname[30])
{
    Post *list;
    unsigned int hashkey = Hash(hash_table, tempname);

    for(list = hash_table->table[hashkey]; list != NULL; list = list->next)
    {
        if (strcmp(tempname, list->name) == 0)
        {
            return list;
        }
    }
    return NULL;
}

int add_string(Post_table *hash_table, char tempname[30], int temptel)
{
    Post *new_list;
    Post *current_list;
    unsigned int hashkey = Hash(hash_table, tempname);

    /* Attempt to allocate memory for list */
    if ((new_list = malloc(sizeof(Post))) == NULL)
    {
        return 1;
    }

    /* Does item already exist? */
    current_list = lookup_string(hash_table, tempname);
    /* item already exists, don't insert it again. */
    if (current_list != NULL)
    {
        return 2;
    }
    /* Insert into list */

    printf("\nHash-key: %d\n", hashkey); 
    hash_table->table[hashkey] = AddList(tempname, temptel);

    return 0;
}

Post* CreateList(char tempname[30], int temptel)
{   
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);    
    ptr->tel = temptel;
    ptr->next = NULL;

    printf("\n creating list with headnode as [%s]\n",tempname);

    head = current = ptr;
    return ptr;
}

Post* AddList(char tempname[30], int temptel)
{
    if (NULL == head)
    {
        return (CreateList(tempname, temptel));
    }

    printf("\n Adding node to end of list with value [%s]\n",tempname);
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);
    ptr->tel = temptel;
    ptr->next = NULL;

    current->next = ptr;
    current = ptr;
    return ptr;
}

void skrivMeny(void)
{
    printf("\n1: Register name and telephone number\n");
    printf("2: Remove name and telephone number\n");
    printf("3: Search for name\n");
    printf("5: Exit\n");
}

Post* Search(char tempname[30], Post **prev)
{
    Post *ptr = head;
    Post *tmp = NULL;
    int found = 0;
    char structname[sizeof(tempname)];

    printf("\n Searching the list for value [%s] \n",tempname);

    while(ptr != NULL)
    {   
        if (strcmp(ptr->name, tempname) == 0)
        {
            found = 1;
            break;
        }
        else
        {
            tmp = ptr;
            ptr = ptr->next;
        }
    }

    if(found == 1)
    {
        if(prev)
        {
            *prev = tmp;
        }
        return ptr;
    }
    else
    {
        return NULL;
    }
}

void free_entry(Post_table *hash_table, char tempname[30])
{
    Post *del_list;
    Post *temp;
    int ret = 0;

    unsigned int hashkey = Hash(hash_table, tempname);
    del_list = lookup_string(hash_table, tempname);

    ret = Delete(tempname);

    if(ret != 0)
    {
        printf("\n delete [name = %s] failed, no such element found\n",tempname);
    }
    else
    {
        printf("\n delete [name = %s]  passed \n",tempname);
    }
}

int Delete(char tempname[30])
{
    Post *prev = NULL;
    Post *del = NULL;

    printf("\n Deleting value [%s] from list\n",tempname);
    del = Search(tempname,&prev);

    if(del == NULL)
    {
        return -1;
    }
    else
    {
        if(prev != NULL)
        {
            prev->next = del->next;
        }
        if(del == current && del != head)
        {
            current = prev;
        }
        else if(del == head)
        {
            head = del->next;
        }
    }

    free(del);
    del = NULL;
    return 0;
}


int main()
{
    printf("\nHej och välkommen till hashlistan\n\n");
    int menyval = 1;
    char tempname[30];
    int temptel;
    int key;

    Post * ptr;

    Post_table *hash_table;
    int table_size = 10;
    hash_table = create_hash_table(table_size);

while (menyval > 0 && menyval <= 5)
{
    skrivMeny();
    scanf("%d", &menyval);

        if (menyval == 1)
        {
            printf("[Name] [Number] = ");
            scanf("%s %d", &tempname[0], &temptel);//inmatning
            add_string(hash_table, tempname, temptel);
        }

        if (menyval == 2)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            free_entry(hash_table, tempname);
        }

        if (menyval == 3)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            ptr = lookup_string(hash_table, tempname);

            if(ptr == NULL)
            {
                printf("\n Search [name = %s] failed, no such element found\n",tempname);
            }
            else
            {
                printf("\n Search passed [name = %s tel = %d]\n",ptr->name, ptr->tel);
            }
        }
        if (menyval == 5)
        {
            break;
        }

    }
    return 0;
}

感谢所有有助于解决我的问题的帮助或提示!

编辑: 这就是我的代码现在的样子,我将文件分成两个文件; hash.c 和 lista.h 我在 c 文件中包含了头文件。

lista.h:

struct post
{   
    char name[30];          
    int tel;                
    struct post *next;      
};
typedef struct post Post;

struct list
{
    Post *head = NULL;  
    Post *current;
};
typedef struct list List;

Post* CreateList(char tempname[30], int temptel)
{   
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);    
    ptr->tel = temptel;
    ptr->next = NULL;

    printf("\n creating list with headnode as [%s]\n",tempname);

    return ptr;
}

Post* AddList(char tempname[30], int temptel, int emptyElement)
{
    if (emptyElement == 1)
    {
        return (CreateList(tempname, temptel));
    }

    printf("\n Adding node to end of list with value [%s]\n",tempname);
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);
    ptr->tel = temptel;
    ptr->next = NULL;

    return ptr;
}

int Delete(Post_table *hash_table, char tempname[30])
{
    Post *prev = NULL;
    Post *del = NULL;

    printf("\n Deleting value [%s] from list\n",tempname);
    del = Search(tempname,&prev);

    if(del == NULL)
    {
        return -1;
    }
    else
    {
        if(prev != NULL)
        {
            prev->next = del->next;
        }
        if(del == hash_table->table[hashkey].current && del != hash_table->table[hashkey].head)
        {
            hash_table->table[hashkey].current = prev;
        }
        else if(del == hash_table->table[hashkey].head)
        {
            hash_table->table[hashkey].head = del->next;
        }
    }

    free(del);
    del = NULL;
    return 0;
}

hash.c:

struct hash_table
{
    List *table;
    int size;
};

typedef struct hash_table Post_table;

unsigned int Hash(Post_table *hash_table, char tempname[30])
{
    int i;
    int sum;
    int key;
    for(i = 0; i < strlen(tempname); i++)
    {
        sum += (int)tempname[i];
    }

    key = sum % hash_table->size;
    return key;
}

Post_table *create_hash_table(int size)
{
    int i;
    Post_table *new_table;

    if (size < 1)
    {
        return NULL;
    }

    //attempt to allocate memory for the table structure
    if ((new_table = malloc(sizeof(Post_table))) == NULL)
    {
        return NULL;
    }

    //attempt to allocate memory for the table itself
    if ((new_table->table = malloc(sizeof(Post *) * size)) == NULL)
    {
        return NULL;
    }

    //Initialize the elements of the table
    for(i = 0; i < size; i++)
    {
        new_table->table[i] = NULL;
        new_table->size = size;
    }
    return new_table;
}

Post *lookup_string(Post_table *hash_table, char tempname[30])
{
    Post *list;
    unsigned int hashkey = Hash(hash_table, tempname);

    for(list = hash_table->table[hashkey]; list != NULL; list = list->next)
    {
        if (strcmp(tempname, list->name) == 0)
        {
            return list;
        }
    }
    return NULL;
}

int add_string(Post_table *hash_table, char tempname[30], int temptel)
{
    int emptyElement = 0;        
    Post *new_list;
    Post *current_list;
    unsigned int hashkey = Hash(hash_table, tempname);

    /* Attempt to allocate memory for list */
    if ((new_list = malloc(sizeof(Post))) == NULL)
    {
        return 1;
    }

    /* Does item already exist? */
    current_list = lookup_string(hash_table, tempname);
    /* item already exists, don't insert it again. */
    if (current_list != NULL)
    {
        return 2;
    }
    /* Insert into list */
    if (hash_table->table[hashkey] == NULL)
    {
        emptyElement = 1;
    }

    printf("\nHash-key: %d\n", hashkey); 
    hash_table->table[hashkey] = AddList(tempname, temptel);

    if (emptyElement == 1)
    {
            hash_table->table[hashkey].head = hash_table->table[hashkey];
            hash_table->table[hashkey].current = hash_table->table[hashkey];
    }

    if (emptyElement == 0)
    {
            hash_table->table[hashkey].current = hash_table->table[hashkey];
    }

    return 0;
}

void free_entry(Post_table *hash_table, char tempname[30])
{
    Post *del_list;
    Post *temp;
    int ret = 0;

    unsigned int hashkey = Hash(hash_table, tempname);
    del_list = lookup_string(hash_table, tempname);

    ret = Delete(tempname);

    if(ret != 0)
    {
        printf("\n delete [name = %s] failed, no such element found\n",tempname);
    }
    else
    {
        printf("\n delete [name = %s]  passed \n",tempname);
    }
}

void skrivMeny(void)
{
    printf("\n1: Register name and telephone number\n");
    printf("2: Remove name and telephone number\n");
    printf("3: Search for name\n");
    printf("5: Exit\n");
}

Post* Search(char tempname[30], Post **prev)
{
    Post *ptr = head;
    Post *tmp = NULL;
    int found = 0;
    char structname[sizeof(tempname)];

    printf("\n Searching the list for value [%s] \n",tempname);

    while(ptr != NULL)
    {   
        if (strcmp(ptr->name, tempname) == 0)
        {
            found = 1;
            break;
        }
        else
        {
            tmp = ptr;
            ptr = ptr->next;
        }
    }

    if(found == 1)
    {
        if(prev)
        {
            *prev = tmp;
        }
        return ptr;
    }
    else
    {
        return NULL;
    }
}

int main()
{
    printf("\nHej och välkommen till hashlistan\n\n");
    int menyval = 1;
    char tempname[30];
    int temptel;
    int key;

    Post * ptr;

    Post_table *hash_table;
    int table_size = 10;
    hash_table = create_hash_table(table_size);

while (menyval > 0 && menyval <= 5)
{
    skrivMeny();
    scanf("%d", &menyval);

        if (menyval == 1)
        {
            printf("[Name] [Number] = ");
            scanf("%s %d", &tempname[0], &temptel);//inmatning
            add_string(hash_table, tempname, temptel);
        }

        if (menyval == 2)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            free_entry(hash_table, tempname);
        }

        if (menyval == 3)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            ptr = lookup_string(hash_table, tempname);

            if(ptr == NULL)
            {
                printf("\n Search [name = %s] failed, no such element found\n",tempname);
            }
            else
            {
                printf("\n Search passed [name = %s tel = %d]\n",ptr->name, ptr->tel);
            }
        }
        if (menyval == 5)
        {
            break;
        }

    }
    return 0;
}

但正如我所说,这部分似乎有问题:

struct list
{
    Post *head = NULL;  
    Post *current;
};

由于这不正确,它会导致其他几个错误,所以我想先看看这部分有什么问题。

【问题讨论】:

  • 您是否尝试过使用调试器单步执行查找功能,一次一行?您使用的是什么操作系统?什么编译器?
  • 哦,我忘了说这是C语言,操作系统是最新的Ubuntu。它是用gcc编译的,我不记得是哪个版本。但是我现在无法访问我的计算机,并且我所在的这台计算机上没有编译器,这非常有限,所以我也无法安装编译器。
  • 我的眼睛,我的眼睛!这是很多代码。
  • 是的,我注意到了!我在写我的帖子时确实使用了意图,这会使代码更容易阅读,但不知何故,意图并不适用于最终帖子......
  • 实际上,如果您使用 firefox,则意图会正确显示。而且我还更新了我的代码并将其分为一个 c 文件和一个头文件,其中头文件包含在 c 文件中。仍然是相同数量的代码,但可能更容易浏览。

标签: c list search linked-list hashtable


【解决方案1】:

好的,这里对您的代码进行了一些改进:我已经用我的标签“Leo”标记了它们

在 list.c 中:

struct post                 // structure of node
{   
    char name[30];          // stored data
    int tel;                // stored data
    struct post *next;      // reference to next node
};

typedef struct post Post;   // Post = struct post

struct list
{
    Post *head;         
    Post *current;              
};

typedef struct list List;

struct hash_table
{
    List *table;
    int size;
};

typedef struct hash_table Post_table;

Post* CreateList(char tempname[30], int temptel);
Post* AddList(char tempname[30], int temptel, int emptyElement, Post *current);
void skrivMeny(void);
void PrintList(void);
int Delete(Post_table *hash_table, char tempname[30], unsigned int hashkey);
Post* Search(Post_table *hash_table, unsigned int hashkey, char tempname[30], Post **prev);

Post* CreateList(char tempname[30], int temptel)
{   
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);    
    ptr->tel = temptel;
    ptr->next = NULL;

    printf("\n creating list with headnode as [%s]\n",tempname);

    return ptr;
}

// Leo: emptyElement isn't neccessary, we use current==null 
Post* AddList(char tempname[30], int temptel, Post *current)
{
    if( current == null )
    {
        return (CreateList(tempname, temptel));
    }

    printf("\n Adding node to end of list with value [%s]\n",tempname);
    Post *ptr = (Post*)malloc(sizeof(Post));

    strcpy(ptr->name, tempname);
    ptr->tel = temptel;
    ptr->next = NULL;

    // Leo: we must append the new element to current
    current->next = ptr;

    return ptr;
}

在 hash.c 中

unsigned int Hash(Post_table *hash_table, char tempname[30])
{
    int i;
    int sum;
    int key;
    for(i = 0; i < strlen(tempname); i++)
    {
        sum += (int)tempname[i];
    }

    key = sum % hash_table->size;
    return key;
}

Post_table *create_hash_table(int size)
{
    int i;
    Post_table *new_table;

    if (size < 1)
    {
        return NULL;
    }

    //attempt to allocate memory for the table structure
    if ((new_table = malloc(sizeof(Post_table))) == NULL)
    {
        return NULL;
    }

    //attempt to allocate memory for the table itself
    // Leo: replaced malloc() by calloc() so all head and current are initialized with NULL
    if ((new_table->table = calloc(size, sizeof(List *) )) == NULL)
    {
        return NULL;
    }

    //Initialize the elements of the table
    /* Leo: What's that loop for ?
    for(i = 0; i < size; i++)
    {
        new_table->table[i];        // Leo: that line doen't do anything
        new_table->size = size;     // Leo: once is enough, let's have it otside the loop
    }
    */
    new_table->size = size;       // Leo: once is enough, let's have it otside the loop
    return new_table;
}

Post *lookup_string(Post_table *hash_table, char tempname[30])
{
    Post *list;
    unsigned int hashkey = Hash(hash_table, tempname);

    /* Go to the correct list based on the hash value and see if str is
    * in the list.  If it is, return return a pointer to the list element.
    * If it isn't, the item isn't in the table, so return NULL.
    */
    // Leo: we must start with head instead of current
    for(list = hash_table->table[hashkey].head; list != NULL; list = list->next)
    {
        if (strcmp(tempname, list->name) == 0)
        {
            return list;
        }
    }
    return NULL;
}

int add_string(Post_table *hash_table, char tempname[30], int temptel)
{
    //Leo: emptyElement is not used any more (see AddList()
    //int emptyElement = 0;
    //Leo: new_list is never used
    //Post *new_list;
    Post *current_list;
    unsigned int hashkey = Hash(hash_table, tempname);

    /* Attempt to allocate memory for list */
    /* Leo: new_list is never used
    if ((new_list = malloc(sizeof(Post))) == NULL)
    {
        return 1;
    }
    */

    /* Does item already exist? */
    current_list = lookup_string(hash_table, tempname);
    /* item already exists, don't insert it again. */
    if (current_list != NULL)
    {
        return 2;
    }
    /* Insert into list */
    /* Leo: emptyElement isn't used any more 
    if (hash_table->table[hashkey].head == NULL)
    {
        emptyElement = 1;
    }
    */

    printf("\nHash-key: %d\n", hashkey);
    //This line of code under used to store my element in the hash-table but gives now an error 
    //  hash_table->table[hashkey] = AddList(tempname, temptel, emptyElement, hash_table->table[hashkey].current);

    /* Leo: in case of emptyElement == 1 you have called AddList() twice and so created two new list elemens, we replace all of this by the code below
    if (emptyElement == 1)
    {
        hash_table->table[hashkey].head = AddList(tempname, temptel, emptyElement, hash_table->table[hashkey].current);
        hash_table->table[hashkey].current = AddList(tempname, temptel, emptyElement, hash_table->table[hashkey].current);
    }

    if (emptyElement == 0)
    {
        hash_table->table[hashkey].current = AddList(tempname, temptel, emptyElement, hash_table->table[hashkey].current);
    }
    */

    // Leo: Note: if the list for hashKey has not been created yet then both head and current are NULL, otherwise both are != NULL
    hash_table->table[hashkey].current = AddList(tempname, temptel, hash_table->table[hashkey].current);
    // Leo: if the list has been created just now, then both head and current must point to the only list element
    if( hash_table->table[hashkey].head == NULL )
         hash_table->table[hashkey].head = hash_table->table[hashkey].current;

    return 0;
}

void free_entry(Post_table *hash_table, char tempname[30])
{
    Post *del_list;
    Post *temp;
    int ret = 0;

    unsigned int hashkey = Hash(hash_table, tempname);
    del_list = lookup_string(hash_table, tempname);

    ret = Delete(hash_table, tempname, hashkey);

    if(ret != 0)
    {
        printf("\n delete [name = %s] failed, no such element found\n",tempname);
    }
    else
    {
        printf("\n delete [name = %s]  passed \n",tempname);
    }
}

void skrivMeny(void)
{
    printf("\n1: Register name and telephone number\n");
    printf("2: Remove name and telephone number\n");
    printf("3: Search for name\n");
    printf("5: Exit\n");
}

Post* Search(Post_table *hash_table, unsigned int hashkey, char tempname[30], Post **prev)
{
    Post *ptr = hash_table->table[hashkey].head;
    Post *tmp = NULL;
    int found = 0;
    char structname[sizeof(tempname)];

    printf("\n Searching the list for value [%s] \n",tempname);

    while(ptr != NULL)
    {   
        if (strcmp(ptr->name, tempname) == 0)
        {
            found = 1;
            break;
        }
        else
        {
            tmp = ptr;
            ptr = ptr->next;
        }
    }

    if(found == 1)
    {
        if(prev)
        {
            *prev = tmp;
        }
    return ptr;
    }
    else
    {
        return NULL;
    }
}


int main()
{
    printf("\nHej och välkommen till hashlistan\n\n");
    int menyval = 1;
    char tempname[30];
    int temptel;
    int key;

    Post * ptr;

    Post_table *hash_table;
    int table_size = 10;
    hash_table = create_hash_table(table_size);

    while (menyval > 0 && menyval <= 5)
    {
        skrivMeny();
        scanf("%d", &menyval);

        if (menyval == 1)
        {
            printf("[Name] [Number] = ");
            scanf("%s %d", &tempname[0], &temptel);//inmatning
            add_string(hash_table, tempname, temptel);
        }

        if (menyval == 2)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            free_entry(hash_table, tempname);
        }

        if (menyval == 3)
        {
            printf("[Name] = ");
            scanf("%s", &tempname[0]);
            ptr = lookup_string(hash_table, tempname);

            if(ptr == NULL)
            {
                printf("\n Search [name = %s] failed, no such element found\n",tempname);
            }
            else
            {
                printf("\n Search passed [name = %s tel = %d]\n",ptr->name, ptr->tel);
            }
        }

        if (menyval == 5)
        {
            break;
        }

    }
    return 0;
}


int Delete(Post_table *hash_table, char tempname[30], unsigned int hashkey)
{
    Post *prev = NULL;
    Post *del = NULL;

    printf("\n Deleting value [%s] from list\n",tempname);
    del = Search(hash_table, hashkey, tempname, &prev);

    if(del == NULL)
    {
        return -1;
    }

    else
    {
        if(prev != NULL)
        {
            prev->next = del->next;
        }

        if(del == hash_table->table[hashkey].current && del != hash_table->table[hashkey].head)
        {
            hash_table->table[hashkey].current = prev;
        }

        else if(del == hash_table->table[hashkey].head)
        {
            hash_table->table[hashkey].head = del->next;
        }
    }

    free(del);
    del = NULL;
    return 0;
}

我还没有编译它,所以现在可能有一些语法错误,但我希望它清楚整个事情应该如何工作。如果您还有其他问题,请随时提出。

【讨论】:

  • 唯一出现的我不确定的语法错误是:hash.c:42:5: error: too few arguments to function ‘calloc’ 指向这一行 if ((new_table-&gt;table = calloc(sizeof(List *) * size)) == NULL) 我将其替换为 if ((new_table-&gt;table = calloc(0,sizeof(List *) * size)) == NULL) 但现在每当我遇到分段错误时尝试搜索列表并崩溃。 10 次中有 2 次我没有遇到分段错误,但我仍然无法使用搜索功能找到元素。
  • 哎呀,calloc() 应该是 calloc( size, sizeof(List *) )。参数是“元素数量”和“元素大小”(查看man page)。你叫它的方式,它分配了0 * ( sizeof(List *) * size ),因此什么都没有。我已经更正了答案中的错误。
  • 好的,我明白了!现在我让它正常运行,我可以在表中存储东西,它似乎正在创建列表,因为它说将节点添加到列表末尾。但是还是没有找到存储的元素,我去搜索逻辑看看能不能找到问题。
  • 您好!只是想告诉你,我终于让代码正常工作了。它现在可以存储、查找和删除哈希表中的元素。非常感谢您的耐心和努力 Ingo Leonhardt,这对我来说是一个巨大的突破,如果没有您的帮助,我不会成功!再次感谢!
【解决方案2】:

抱歉,如果我弄错了,但据我所知,您的 lookup_string() 函数会遍历哈希表的最后一个元素(最近添加的那个)。 尝试反过来遍历它或使用双向链表。

P.S:你不使用你的搜索功能和一点点定制吗?是这种查找和搜索的冗余吗?

编码愉快!

【讨论】:

  • 嗨!你的意思是我的 lookup_string() 只查看最后一个元素并跳过之前的所有元素?是的,它有点冗余,因为我通过首先实现链接列表然后是哈希表来处理它,但是当我让逻辑工作时,冗余将被修复。谢谢
【解决方案3】:

我认为问题导致混合一个链表和哈希表。该列表未排序,因此哈希表无法指向可以找到具有给定键的所有元素的列表位置。此外,AddList() 返回附加到末尾并存储在hash_table-&gt;table[hashkey] 中的新列表元素。 这就是为什么你只能找到最后一个元素(正如 Mudassir Razvi 已经指出的那样)。 因此,您应该为每个哈希键创建一个列表(我想是最简单的解决方案),或者对每个哈希键的列表进行排序,并仅在使用该键添加第一个元素时分配 hash_table-&gt;table[hashkey] (==> if( hash_table-&gt;table[hashkey] == NULL ))

编辑: 如果你想为每个键创建单独的列表,当然你不能再有全局变量headcurrent,而是每个键一对。所以你可以定义:

struct list {
    Post *head;
    Post *current;
}

并让hash_table-&gt;table 成为struct list 而不是Post 的一个attray。 CreateList() 已经返回 head,因此您可以直接将其分配给 table[key].headtable[key].current。现在您要做的其他事情就是将实际的current 传递给AddList(),然后将table[key].current 设置为AddList() 的返回值。 那是一种路线图,我想你会来的。

【讨论】:

  • 好的,我想我理解了你所说的大部分内容。我应该只在添加第一个元素时分配'hash_table->table [hashkey]',所有其他具有相同哈希键的元素都应该通过前一个元素的“下一个指针”指向?虽然我不明白为什么我需要对列表进行排序。如果每个列表中没有很多元素,我可以让搜索遍历未排序的列表,直到找到正确的元素。我只需要告诉它应该查看哪个列表,我相信这是由 'list = hash_table->table[hashkey];'
  • 目前只有 一个公共 列表用于由全局变量 headcurrent 定义的所有哈希键,每个新元素都附加到其中,并且该列表未排序。因此,您的哈希表可能会告诉您在哪里找到具有给定键的第一个元素,但从那时起,您可能必须搜索到列表的末尾才能找到给定的名称。如果每个键都有一个列表或排序列表,则您最多必须检查与该键一样多的元素。
  • 哦,现在我看到了问题所在。 'head' 是全局的,这就是为什么创建链表只会发生在第一个元素上。我想我应该把'head'和'current'放在 CreateList() 函数中,并按照你所说的进行检查('if(hash_table->table[hashkey] == NULL)')知道何时触发 CreateList() 函数.当“头”和“当前”变为本地时的问题是我认为指针失去了它们的目标值。每个列表都有自己的“头”和“当前”,但随着 CreateList() 函数结束,它们会丢失。
  • 我听从了你的建议,将Post *headPost *current 放在一个结构中,然后我解释了你的句子“并让hash_table-&gt;table 成为struct list 而不是Post 的一个attray”就像将结构 hash_table 中的 Post **table; 更改为 struct list **table 一样。但是编译器在Post *head; 处抱怨错误消息:error: expected ':', ',', ';', '}' or '__attribute__' before '=' token。如果我误解了你的提示,我很抱歉,但我现在真的脱离了我的编程舒适区。
  • 在你的评论中你写了一个';'在Post **table; 中,但不在struct list **table 中。在真正的来源呢?这将解释编译器错误。顺便提一句。您只需要struct list *table;,因为您希望每个键都有一个struct list,而不是struct list *。如果这没有帮助,请发布当前代码。
【解决方案4】:

我决定发布一个关于当前代码的新答案,因为否则我发现其他人会比现在更难以阅读

您当前代码中的语法错误在这里:

struct list 
{
    Post *head = NULL;  
    Post *current;
};

这不是一个变量定义,而只是一个结构的声明。因此你不能在这里做任何赋值(= NULL),因为根本没有变量可以赋值。 相反,您可以在分配数组后在循环中初始化hash_table-&gt;table[i].head,或者只调用calloc() 而不是malloc(),后者使用'\0' 初始化分配的缓冲区。

我猜你的代码中还有更多错误,至少我发现了

if ((new_table->table = malloc(sizeof(Post *) * size)) == NULL)

应该是

if ((new_table->table = malloc(sizeof(list stuct) * size)) == NULL) // or calloc() 

但我现在无法查看所有内容。 希望能给你足够的继续,

【讨论】:

  • 非常感谢!我成功地继续了很多,并解决了其他几个错误。现在我只遇到了由类似错误引起的错误。现在似乎所有问题都与使用hash_table-&gt;table[hashkey] 类型有关,它是List 在用另一种类型赋值的操作中。例如,在“lookup_string”中,我有一个 for 循环,将其值分配给 list,其类型为 struct Post*,在“add_string”中,我将返回值从 AddList 分配给 struct Post* 987654335@ 类型为List
  • 另外,我似乎也无法将其与NULL 进行比较或分配。
  • 不是`table[i]`本身,因为它不是一个指针数组,但table[i].headtable[i].current可以赋值并与NULL比较
  • 好的,但我如何将 AddList 的返回值存储到哈希表槽中? hash_table-&gt;table[hashkey] = AddList(tempname, temptel); 应该将元素返回到哈希表中,但它给出了错误,因为 AddList 返回一个 struct Post* 并且该表是一个 struct list
  • just hash_table-&gt;table[hashkey].current = AddList(tempname, temptel, hash_table-&gt;table[hashkey].current ); 您传递上一个当前列表(可能为 NULL)并接收新的 current(如果 head 已经是 NULL,您还必须将其复制到 hash_table-&gt;table[hashkey].head . 注意headcurrent 都应该是NULL 或者没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 2019-03-24
  • 2017-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
相关资源
最近更新 更多