[英]Deleting two adjacent nodes in singly linked list
我是學生(還是新秀),我有問題。 我必須刪除單鏈列表中總和等於k的一對節點。 例如,如果鏈接列表為13-> 4-> 5-> 4-> 3且k = 9 ,則我的函數應將列表轉換為13-> 3 (4 + 5 = 9,5 + 4 = 9 )。 這是我未完成的代碼:
typedef struct _node
{
int value;
struct _node* next;
}Node;
void remove(Node **list, int k)
{
if(*list == NULL || (*list)->next == NULL)
return;
Node *prev = *list;
Node *tmp = (*list)->next;
while(tmp != NULL)
{
if(prev->value + tmp->value == k)
{
free(prev);
prev = tmp->next;
free(tmp);
tmp = tmp->next->next;
}
}
}
我有一個主意,但我不知道如何在while循環中設置條件。 有人知道如何重寫嗎?
現在,您在第一個匹配項處斷開了鏈接:在您的示例中,刪除4之后,13的next
仍然指向該鏈接,因此一個懸空指針也指向該鏈接。 但這不會發生,因為您永遠不會從13移動到任何地方,因為您僅在刪除元素時才向前迭代(這對13-> 4不會發生)。
您應該考慮的第三件事是,您實際上應該標記要刪除的元素,否則您將無法刪除示例中的后四個元素。
首先->您不在列表中前進,因此將導致無限循環。
第二->如果tmp
的下一個節點為NULL
則tmp=tmp->next->next
將給您分段錯誤。
第三->當釋放內存時,您也在斷開鏈表,因此在基礎代碼中聲明了pointToPrev
指針,該指針將指向prev
指針后面的節點,但是如果釋放內存,它將將指向tmp
net節點保存列表。
最好將while循環更改為此:
` int indicator=0;
Node *pointToPrev = *list;
if(prev->value + tmp->value == k)
{
*list=temp->next;
free(tmp);
free(prev);
indicator=2;
}
while((tmp != NULL)&&(indicator!=2))
{
if(prev->value + tmp->value == k)
{
free(prev);
pointToPrev->next = tmp->next;
free(tmp)
break; //AS YOU DON'T NEED TO COMPLETE THE ENTIRE WHILE LOOP AS SUM HAS BEEN ALREADY FOUND
}
else //THIS WILL SAVE YOU FROM THE INFINITE LOOP
{
tmp = tmp->next;
prev = prev->next;
if(indicator==0)
{
pointToPrev = *list;
indicator=1;
}
else
pointToPrev=pointToPrev->next;
}
}
由於存在兩個重疊條件來控制是否應刪除給定節點,因此此問題變得很復雜:如果其值與前一個節點的值之和是目標值,或者其值與下一個節點的值之和是目標值。 而且,除了當它是最后一個節點之外,您始終將下一個節點與下一個節點進行比較,因此您必須紀念它所攜帶的值,否則必須避免將其刪除。
可以通過從第二個節點開始的普通鏈表遍歷來解決此問題(或者如果少於兩個節點,則無需執行任何操作)。 每次迭代
循環終止后,請根據需要刪除最后一個節點。 您需要在每次迭代之間攜帶足夠的狀態,以適當地執行刪除操作,並記住上一次迭代中求和評估的結果,但是總的來說,這並不比按值刪除單個節點困難得多。
這種方法非常簡單,因為它將每次評估中必須考慮的案例數限制為兩個,它永遠不需要在列表中比下一個節點更向前看,並且在刪除一個節點時,該節點始終具有與當前節點的關系相同。 該代碼應保留為應做的練習。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.