簡體   English   中英

C中的鏈接列表–方法

[英]Linked list in C – methods

假設我們有雙重鏈接的節點列表

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

typedef struct Node {
    int value;
    struct Node* next;
    struct Node* prev;
} Node;

typedef struct LinkedList {
    Node *first;
    Node *last;
} LinkedList;

void initList(LinkedList* l) {
    l->first = NULL;
    l->last = NULL;
}

我必須編寫代碼方法,該方法將具有給定值的新節點插入列表的末尾,並返回指向該新節點的指針。 我的嘗試如下:

Node *insert(LinkedList *list, int value) {

    Node node;
    node.value = value;
    node.prev = list->last;
    node.next = NULL;

    if (list->last != NULL){
        (list->last)->next = &node;
    }else{
        list->first = &node;
        list->last = &node;
    }

    return &node;
}

看來,在空列表中插入是可行的,但對於非空列表則無效。

(有一些實現測試,可以告訴我插入是否成功。我可以發布它們的代碼,但是並不重要)。

那么,請問錯誤在哪里?

日志中有一個警告(第51行是帶有“ return&node”的警告)

C:\...\main.c|51|warning: function returns address of local variable [-Wreturn-local-addr]|

那是個嚴重的問題嗎? 以及如何將其刪除?


感謝您的回答,但我認為非空列表仍然存在問題,因為根據測試,此操作失敗:

void test_insert_nonempty(){
    printf("Test 2: ");

    LinkedList l;
    initList(&l);

    Node n;
    n.value = 1;
    n.next = NULL;
    l.first = &n;
    l.last = &n;

    insert(&l, 2);

    if (l.last == NULL) {
        printf("FAIL\n");
        return;
    }
    if ((l.last->value == 2) && (l.last->prev != NULL)) {
        printf("OK\n");
        free(l.last);
    }else{
        printf("FAIL\n");
    }
}

Node node; 是函數insert的局部變量。 一旦您的函數終止並且不再定義,它就會被“銷毀”。 將指針返回到函數的局部變量是未定義的行為。 您必須分配動態內存。 動態分配內存將保留,直到您free它:

Node *insert(LinkedList *list, int value) {

    Node *node = malloc( sizeof( Node ) ); // allocate dynamic memory for one node
    if ( node == NULL )
        return NULL; // faild to allocate dynamic memory

    node->value = value;
    node->prev = list->last;
    node->next = NULL;

    if ( list->first == NULL )
        list->first = node;      // new node is haed of list if list is empty
    else // if ( list->last != NULL ) // if list->first != NULL then list->last != NULL
        list->last->next = node; // successor of last node is new node
    list->last = node;           // tail of list is new node

    return node;
}

請注意,為避免內存泄漏,銷毀列表時必須free列表的每個節點。

您要返回的非靜態局部變量的地址在從函數返回時將消失,從函數返回后取消引用該地址將調用未定義的行為

您必須分配一些緩沖區並返回其地址。

Node *insert(LinkedList *list, int value) {

    Node *node = malloc(sizeof(Node));
    if (node == NULL) return NULL;
    node->value = value;
    node->prev = list->last;
    node->next = NULL;

    if (list->last != NULL){
        (list->last)->next = node;
    }else{
        list->first = node;
        list->last = node;
    }

    return node;
}

您必須動態分配新節點。

否則函數中的變量node

Node *insert(LinkedList *list, int value) {

    Node node;
    //...

是該函數的局部變量,退出該函數后將不活動。 結果,用於訪問該變量的任何指針都將無效。

該功能可以看起來像

Node * insert( LinkedList *list, int value ) 
{
    Node *node = malloc( sizeof( Node ) );

    if ( node != NULL )
    {
        node->value = value;
        node->prev = list->last;
        node->next = NULL;

        if ( list->last != NULL )
        {
            list->last->next = node;
        }
        else
        {
           list->first = node;
        }

        list->last = node;
    }

    return node;
}

暫無
暫無

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

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