简体   繁体   English

C - 如何修改函数内部的指针数组

[英]C - how to modify an array of pointers inside of a function

I'm trying to implement a hash table in C, and almost have it. 我正在尝试在C中实现哈希表,几乎拥有它。 I'm implementing collision resolution via chaining using a linked list in each array slot, and I'd like to be able to chain inside a function call. 我正在通过链接使用每个数组槽中的链表来实现冲突解决,我希望能够在函数调用内部进行链接。

Now, the problem is that in order for the modifications to be permanent I believe that I need an additional level of indirection. 现在,问题是为了使修改成为永久性的,我相信我需要一个额外的间接层。 This is a problem in that when I try to traverse the list the previous element is overwritten by the next (see my comment inside the insert() function). 这是一个问题,当我尝试遍历列表时,前一个元素被下一个元素覆盖(请参阅我在insert()函数中的注释)。 I've tried to pass this array with an additional level of indirection specified a few different ways but I get compiler warnings and seg faults. 我试图传递这个数组与额外的间接级别指定几种不同的方式,但我得到编译器警告和seg错误。

This may seem simple to some of you, but it's had me scratching my head for quite some time now, and this scenario (passing array of pointers for modification) is treated nowhere in my text and I can't seem to find this exact question asked (although it may be in a form I don't recognize). 这对你们中的一些人来说可能看起来很简单,但是现在我已经抓住了很长一段时间了,这个场景(通过修改指针数组)在我的文本中没有得到处理,我似乎无法找到这个确切的问题问(虽然它可能是我不认识的形式)。 I'm not necessarily looking for a 'quick fix' to my code, but I want to understand what is the best practice to accomplish what I'm looking to do. 我不一定在寻找代码的“快速修复”,但我想了解完成我想要做的事情的最佳实践。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
//#include "list.c"
struct node{
    int key;
    struct node* next;
};

void createTable(struct node *table[], int numEls, int numSlots);
int hash(int key, int numSlots);
void insert(struct node *table[], int key, int slot, int numSlots);
void display(struct node *table[], int numEls);

int main(void){
    srand(time(NULL));
    int numEls, numSlots;
    printf("Please enter the desired number of slots in the hash table: ");
    scanf("%d", &numSlots);
    struct node *table[numSlots];
    printf("\nPlease enter the desired number of elements: ");
    scanf("%d", &numEls);
    printf("\nYour load factor will be %f", (float)numEls/numSlots);
    createTable(table, numEls, numSlots);
}

void createTable(struct node *table[], int numEls, int numSlots){
    for(int i = 0; i < numSlots; i++)
        table[i] = NULL;
    for(int j = 0; j < numEls; j++){
        for(int k = 0; k < 99999999; k++){}//give the rand function time 
        int el = rand()%100;
        insert(table, el, hash(rand()%100, numSlots), numSlots);
    }
    display(table, numSlots);
}

int hash(int key, int numSlots){
    return((int)(pow(key, 2.819)) % numSlots);
}

void insert(struct node *table[], int key_, int slot, int numSlots){
    printf("\nInserting %d into slot %d", key_, slot);
    fflush(stdout);
    struct node* new = malloc(sizeof(struct node));
    (new)->key = key_;
    (new)->next = NULL;
    struct node** temp = &(table[slot]);
    if((*temp) == NULL){
        printf(" (*temp) == NULL");
        (*temp) = new;
    }
    else{
        printf(" %d", (*temp)->key);
        while((*temp)->next != NULL){
            printf(" %d", (*temp)->next->key);
                (*temp) = (*temp)->next;  //head is overwritten with head->next 
        }
        (*temp)->next = new;
        printf(" %d", (*temp)->next->key);
    }
}

void display(struct node *table[], int numSlots){
    for(int i = 0; i < numSlots; i++){
        printf("\nSlot %d:", i);
        struct node* temp = table[i];
        while(temp != NULL){
            printf(" %d", temp->key);
            temp = temp->next;
        }
    }
}

In the line with the comment, you are overwriting the pointer to the head (inside the outermost array) with the next element in the linked list, which was probably not your intent. 在注释行中,您将使用链接列表中的下一个元素覆盖指向头部(最外层数组内)的指针 ,这可能不是您的意图。

The correction is to walk down the list of pointers until you found the last pointer, without modifying the main data structure during the walk. 更正是沿着指针列表向下走,直到找到最后一个指针,而不在步行期间修改主数据结构。

Here is a corrected version of insert() . 这是insert()的更正版本。

void insert(struct node *table[], int key_, int slot, int numSlots){
    printf("\nInserting %d into slot %d", key_, slot);
    fflush(stdout);
    struct node* new = malloc(sizeof(struct node));
    new->key = key_;
    new->next = NULL;

    // Here we make a copy of the pointer to the head node in the linked list.
    // This way, we never overwrite the original copy which lives in the array itself.
    struct node* head = table[slot];
    if(head == NULL){
        printf(" head == NULL");
        table[slot] = new;
    }
    else{
        while(head->next != NULL) {
            head = head->next;  //head is overwritten with head->next 
        }
        head->next = new;
    }
}

This isn't an answer but is too big for a comment... can you explain what this code is meant to be doing? 这不是一个答案,但对于评论来说太大了......你能解释一下这段代码应该做什么吗?

while((*temp)->next != NULL)
{
    printf(" %d", (*temp)->next->key);
    (*temp) = (*temp)->next;  //head is overwritten with head->next 
}
(*temp)->next = new;

I would expect that you want to append the new node at the end of the linked list of existing nodes in this slot. 我希望您希望将新节点附加到此插槽中现有节点的链接列表的末尾。 But this code actually updates the head to point to the last node in the list , just like your comment says (leaking memory - the earlier nodes in the list are now unreachable). 但是这段代码实际上更新了头部以指向列表中的最后一个节点,就像你的评论所说的那样(泄漏内存 - 列表中的早期节点现在无法访问)。 Then it makes the last node (which is now the only node in the list) point to new . 然后它使最后一个节点(现在是列表中唯一的节点)指向new节点。

So your "list" only ever has length 1 or 2, and it leaks memory each time you try to put a third entry in. 因此,您的“列表”只有长度1或2,并且每次尝试输入第三个条目时它会泄漏内存。

It seems to me that there is nothing wrong with your passing of table (which is a list of heads of linked lists) but the problem is that the code that maintains the list for which those are heads, is not right. 在我看来,你传递table (这是链表的头部列表)没有任何问题,但问题是维护列表的代码是不正确的。

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

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