[英]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.