簡體   English   中英

C - 如何修改函數內部的指針數組

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

我正在嘗試在C中實現哈希表,幾乎擁有它。 我正在通過鏈接使用每個數組槽中的鏈表來實現沖突解決,我希望能夠在函數調用內部進行鏈接。

現在,問題是為了使修改成為永久性的,我相信我需要一個額外的間接層。 這是一個問題,當我嘗試遍歷列表時,前一個元素被下一個元素覆蓋(請參閱我在insert()函數中的注釋)。 我試圖傳遞這個數組與額外的間接級別指定幾種不同的方式,但我得到編譯器警告和seg錯誤。

這對你們中的一些人來說可能看起來很簡單,但是現在我已經抓住了很長一段時間了,這個場景(通過修改指針數組)在我的文本中沒有得到處理,我似乎無法找到這個確切的問題問(雖然它可能是我不認識的形式)。 我不一定在尋找代碼的“快速修復”,但我想了解完成我想要做的事情的最佳實踐。

#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;
        }
    }
}

在注釋行中,您將使用鏈接列表中的下一個元素覆蓋指向頭部(最外層數組內)的指針 ,這可能不是您的意圖。

更正是沿着指針列表向下走,直到找到最后一個指針,而不在步行期間修改主數據結構。

這是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;
    }
}

這不是一個答案,但對於評論來說太大了......你能解釋一下這段代碼應該做什么嗎?

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

我希望您希望將新節點附加到此插槽中現有節點的鏈接列表的末尾。 但是這段代碼實際上更新了頭部以指向列表中的最后一個節點,就像你的評論所說的那樣(泄漏內存 - 列表中的早期節點現在無法訪問)。 然后它使最后一個節點(現在是列表中唯一的節點)指向new節點。

因此,您的“列表”只有長度1或2,並且每次嘗試輸入第三個條目時它會泄漏內存。

在我看來,你傳遞table (這是鏈表的頭部列表)沒有任何問題,但問題是維護列表的代碼是不正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM