簡體   English   中英

C - 刪除雙向鏈表中的節點

[英]C - deleting node in doubly linked list

當我嘗試使用deleteinst方法刪除列表中的每個其他元素時,該方法對鏈表沒有任何作用,並且沒有錯誤。 我真的不確定為什么它不起作用我已經看到了在不同程序中使用的相同deleteinst方法。 也許它與指針有關。 如果我運行deleteInst(track.prev,&head); 如果沒有while循環,列表仍保持不變。

如果您有任何想法或需要更多信息,請告訴我。 感謝您的時間。

int main()
{
node *head;
node *track;
head = ReadNodeList(stdin);

track = LastNode(head); //goes to last node.

while(track != NULL){ 
    int i=0;
            //delete every other node
    if(i%2 == 1){
        deleteInst(track, &head);
    }
i++;
track = track->prev;
    }
}

void deleteInst(Instruction *victim, Instruction **head){

  if(*head == NULL || victim == NULL)
    return;

  if(*head == victim)
    *head = victim->next;

  if(victim->next != NULL)
    victim->next->prev = victim->prev;

  if(victim->prev != NULL)
    victim->prev->next = victim->next;     

  free(victim);
  return;
}

一個顯而易見突出的問題:你真的希望這樣做:

 deleteInst(track, &head);
 track = track->prev;

您釋放該節點的那一刻,您將失去訪問其成員的權利。 首先保存,然后在刪除后恢復:

 node *save_prev = track->prev;
 deleteInst(track, &head);
 track = save_prev;

我要檢查的另一件事是列表結構是正確的,類似於(僅在調試期間):

static void checkList (node *curr) {
    int count = 0;

    // PreCon: head->prev must be null.

    if (curr != NULL) {
        if (curr->prev != NULL) {
            puts ("Linked list structure error A!");
            exit (1);
        }
    }

    // Check all nodes.

    while (curr != NULL) {
        // PreCon: curr->prev->next must be curr.

        if (curr->prev != NULL) {
            if (curr->prev->next != curr) {
                puts ("Linked list structure error B!");
                exit (1);
            }
        }

        // PreCon: curr->next->prev must be curr.

        if (curr->next != NULL) {
            if (curr->next->prev != curr) {
                puts ("Linked list structure error C!");
                exit (1);
            }
        }

        // Move to next and keep count.
        curr = curr->next;
        count++;
    }

    // All okay, output success message with size.

    printf ("Linked list structure okay, size = %d\n", count);
}

使用checkList (head)調用它將驗證您的鏈表是否滿足所有有效性前提條件,因為您可能在其他地方有錯誤代碼,例如在ReadNodeList()創建列表時。


除此之外我建議在ReadNodeList()之后單步執行IDE或調試器中的代碼,以查看它實際執行的操作。 並且,如果您沒有IDE /調試器,請使用以下行代碼來源代碼:

printf ("DEBUG %d: track = %p\n", __LINE__, track);

然后檢查調試語句的輸出以分析程序中的流程。


現在,如果你真的要進行調試練習,你可能會驚訝地發現deleteInst似乎永遠不會被調用,因為i似乎總是設置為0

這個小問題的錯誤在於:

while (track != NULL) { 
    int i = 0; // <<<<<<<

    //delete every other node

    if (i%2 == 1) {
        deleteInst (track, &head);
    }
    i++;
    track = track->prev;
}

是的,沒錯,你通過循環每次都將i設置為0 因此i % 2永遠不會等於1 您需要在循環之前初始化i (並且還會刪除訪問釋放內存的未定義行為):

int i = 0;
while (track != NULL) { 
    node *save_prev = track->prev;

    //delete every other node

    if (i%2 == 1)
        deleteInst (track, &head);
    i++;
    track = save_prev;
}

如果在列表初始化期間將尾部放在列表上,則雙鏈表更容易使用。 這消除了大多數令人頭腦麻木的角落情況。

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

typedef struct node
{
    struct node *next;
    struct node *prev;
    int data;
}
    node;

void ShowList( node *head );
void AppendNodeWithData( node *tail, int data );
void RemoveNode( node *item );

int main( void )
{
    int i;
    node *head, *tail, *item, *temp;

    // allocate and initialize the doubly linked list
    head = malloc( sizeof(node) );
    tail = malloc( sizeof(node) );
    if ( !head || !tail )
        exit( 1 );

    head->next = tail;
    head->prev = NULL;
    tail->next = NULL;
    tail->prev = head;

    // add some items to the list
    for ( i = 0; i < 20; i++ )
        AppendNodeWithData( tail, i );

    ShowList( head );

    // remove every other item
    for ( item = tail->prev; item != NULL && item->prev != NULL; item = temp )
    {
        temp = item->prev->prev;
        RemoveNode( item );
    }

    ShowList( head );
}

void ShowList( node *head )
{
    node *item;

    for ( item = head->next; item->next != NULL; item = item->next )
        printf( "  %d", item->data );
    printf( "\n" );
}

void AppendNodeWithData( node *tail, int data )
{
    node *item;

    if ( (item = malloc( sizeof(node) )) == NULL )
        exit( 1 );

    item->data = data;

    item->prev = tail->prev;
    item->next = tail;

    tail->prev->next = item;
    tail->prev = item;
}

void RemoveNode( node *item )
{
    item->next->prev = item->prev;
    item->prev->next = item->next;
    free( item );
}

暫無
暫無

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

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