簡體   English   中英

鏈表 removeNode C 編程

[英]Linked List removeNode C Programming

我在 ListNode 和 LinkedList 之間有些混淆。 基本上我的問題分為兩部分。 對於第一部分,我應該使用 ListNode。 函數原型如下:

int removeNode(ListNode **ptrHead, int index);

ListNode 部分的所有功能都運行良好。 然后至於第二部分,我應該將上面的函數更改為:

int removeNode(LinkedList *11, int index);

我的第 1 部分代碼運行良好,如下所示:

int removeNode(ListNode **ptrHead, int index) {
ListNode *pre, *cur;
if (index == -1)
    return 1;
else if (findNode(*ptrHead, index) != NULL) {
    pre = findNode(*ptrHead, index - 1);
    cur = pre->next;
    pre->next = cur->next;
    return 0;
}
else
    return 1;
}

ListNode *findNode(ListNode *head, int index) {
    ListNode *cur = head;
    if (head == NULL || index < 0)
        return NULL;
    while (index > 0) {
        cur = cur->next;
        if (cur == NULL) return NULL;
        index--;
    }
    return cur;
}

這是我無法正常工作的第 2 部分的完整代碼:

#include "stdafx.h"
#include <stdlib.h>

typedef struct _listnode {
    int num;
    struct _listnode *next;
}ListNode;

typedef struct _linkedlist {
    ListNode *head;
    int size;
}LinkedList;

void printNode2(ListNode *head);
int removeNode2(LinkedList *ll, int index);

int main()
{
    int value, index;
    ListNode *head = NULL, *newNode = NULL;
    LinkedList *ptr_ll = NULL;

    printf("Enter value, -1 to quit: ");
    scanf("%d", &value);
    while (value != -1) {
        if (head == NULL) {
            head = malloc(sizeof(ListNode));
            newNode = head;
        }
        else {
            newNode->next = malloc(sizeof(ListNode));
            newNode = newNode->next;
        }
        newNode->num = value;
        newNode->next = NULL;
        scanf("%d", &value);
    }

    printNode2(head);

    printf("\nEnter index to remove: ");
    scanf("%d", &index);
    removeNode2(ptr_ll, index);
    printNode2(head);

    return 0;
}

void printNode2(ListNode *head) {
    printf("Current list: ");
    while (head != NULL) {
        printf("%d ", head->num);
        head = head->next;
    }
}

int removeNode2(LinkedList *ll, int index) {
    ListNode *head = ll->head;
    if (head == index)
    {
        if (head->next == NULL)
        {
            printf("There is only one node. The list can't be made empty ");
            return 1;
        }

        /* Copy the data of next node to head */
        head->num = head->next->num;

        // store address of next node
        index = head->next;

        // Remove the link of next node
        head->next = head->next->next;

        return 0;
    }


    // When not first node, follow the normal deletion process

    // find the previous node
    ListNode *prev = head;
    while (prev->next != NULL && prev->next != index)
        prev = prev->next;

    // Check if node really exists in Linked List
    if (prev->next == NULL)
    {
        printf("\n Given node is not present in Linked List");
        return 1;
    }

    // Remove node from Linked List
    prev->next = prev->next->next;

    return 0;
}

當我嘗試運行第 2 部分時,cmd 沒有響應,過了一會兒,它自己關閉了,我不知道哪個部分出了問題。 我在想我是在正確的軌道上還是整個 LinkedList 部分都錯了?

當我嘗試在調試模式下運行時,彈出此錯誤消息:

Exception thrown at 0x01201FD1 in tut.exe: 0xC0000005: Access violation reading location 0x00000000.

If there is a handler for this exception, the program may be safely continued.

提前致謝。

您說當列表僅通過頭指針定義時,您就可以使用鏈表。 在這個設置中,當列表可能被更新時你必須傳遞一個指向頭指針的指針,當你只檢查列表而不修改時只傳遞頭指針,例如:

int removeNode(ListNode **ptrHead, int index);
ListNode *findNode(ListNode *head, int index);

這里,頭指針是客戶端代碼可見的列表句柄。

列表結構的方法為鏈表定義了一個新接口。 雖然頭節點就足夠了,但為了方便追加或節點數量,可能還需要跟蹤尾節點。 該數據可以是鏈表結構中的包。

這意味着節點的處理留給列表,客戶端代碼僅使用鏈表結構,例如:

typedef struct ListNode ListNode;
typedef struct LinkedList LinkedList;

struct ListNode {
    int num;
    ListNode *next;
};

struct LinkedList {
    ListNode *head;
    ListNode *tail;
    int size;
};

void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
void ll_append(LinkedList *ll, int num);
void ll_remove_head(LinkedList *ll);

int main()
{
    LinkedList ll = {NULL};

    ll_append(&ll, 2);
    ll_append(&ll, 5);
    ll_append(&ll, 8);
    ll_print(&ll);

    ll_prepend(&ll, 1);
    ll_prepend(&ll, 0);
    ll_print(&ll);

    ll_remove_head(&ll);
    ll_print(&ll);

    while (ll.head) ll_remove_head(&ll);

    return 0;
}

還有一個區別:在頭節點設置中,頭節點可能為空。 在這里,列表不能為空,它必須存在。 (不過,它的頭部和尾部成員可以為空。)這里的列表是在堆棧上分配的,它的地址&ll必須傳遞給函數。

在鏈表設置中,修改和只讀訪問之間的區別是通過const關鍵字完成的:

void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);

在您的示例中,您采用具有兩個獨立結構的混合方法,一個頭節點和一個列表。 這是行不通的,一個列表由一個結構描述,選擇一個。

鏈表結構方法的優點是所有必需的數據(如頭、尾和大小)總是一起傳遞給函數。 您還可以通過不公開結構成員來向用戶隱藏實現,以便 b 用戶只能處理指向該結構的指針。

最后,這是上述接口的示例實現供您使用:

void ll_print(const LinkedList *ll)
{
    ListNode *node = ll->head;

    while (node != NULL) {
        printf("%d ", node->num);
        node = node->next;
    }

    putchar('\n');
}

void ll_prepend(LinkedList *ll, int num)
{
    ListNode *nnew = malloc(sizeof *nnew);

    nnew->next = ll->head;
    nnew->num = num;

    ll->head = nnew;
    if (ll->tail == NULL) ll->tail = ll->head;
    ll->size++;
}

void ll_append(LinkedList *ll, int num)
{
    ListNode *nnew = malloc(sizeof *nnew);

    nnew->next = NULL;
    nnew->num = num;

    if (ll->tail == NULL) {
        ll->tail = ll->head = nnew;
    } else {
        ll->tail->next = nnew;
        ll->tail = nnew;
    }
    ll->size++;
}

void ll_remove_head(LinkedList *ll)
{
    if (ll->head) {
        ListNode *ndel = ll->head;

        ll->head = ll->head->next;
        ll->size--;

        free(ndel);
    }
}

暫無
暫無

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

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