[英]reversing linked list
我正在嘗試使用遞歸反轉鏈接列表並為其編寫以下代碼。 列表的開頭是列表的開始。
node *reverse_list_recursive(node *list)
{
node *parent = list;
node *current = list->next;
if(current == NULL)
return parent;
else
{
current = reverse_list_recursive(current);
current->next = parent;
printf("\n %d %d \n",current->value,parent->value);
return parent;
}
}
我可以看到所有鏈接都被顛倒了。 然而,當我嘗試顯示時,我得到了無限的數字打印。 當我嘗試反轉列表中最初的第一個數字的鏈接時,我懷疑出現錯誤。
我做錯了什么?
假設我有一個鏈表:
---------- ---------- ---------- ----------
| 1 | |--->| 2 | |--->| 3 | |--->| 4 | |--->NULL
---------- ---------- ---------- ----------
您的代碼將其轉換為:
---------------------- ----------------------
| | | |
v | v |
---------- ---------- ---------- ----------
| 1 | |--->| 2 | | | 3 | | | 4 | |
---------- ---------- ---------- ----------
^ |
| |
----------------------
請注意,第一個元素仍然指向 2。
如果在前兩個之后添加一行parent->next = NULL
,您將得到:
---------------------- ----------------------
| | | |
v | v |
---------- ---------- ---------- ----------
NULL<---| 1 | | | 2 | | | 3 | | | 4 | |
---------- ---------- ---------- ----------
^ |
| |
----------------------
這實際上是正確的結構。
完整代碼為:(每次遞歸調用只需打印當前值)
node *reverse_list_recursive(node *list)
{
node *parent = list;
node *current = list->next;
if(current == NULL)
return parent;
else
{
current = reverse_list_recursive(current);
parent->next = NULL;
current->next = parent;
printf("\n %d \n",current->value);
return parent;
}
}
您需要將新尾部(即舊頭部)的下一個指針設置為 NULL
編輯:這是一個遞歸版本
node *reverse_list_recursive(node *list)
{
node *parent = list;
node *child = list->next;
node *new_head;
if (child == NULL)
return parent ; /* new head */
new_head = reverse_list_recursive(child)
child->next = parent; /* Old parent is the new child of the old child when reversed */
parent->next = NULL; /* might be tail, will be overwritten after we return if we're not at the top level */
return new_head;
}
當您到達列表的末尾時,您將返回最后一個節點。 然后將最后一個節點的下一個值分配給它自己,因此會造成不一致。 如果當前為 NULL,則返回 NULL,如果返回為 NULL,則簡單地忽略其余代碼。
您忘記更新鏈表上第一項的next
成員。 添加parent->next = NULL;
在遞歸調用之前。
我在這里看不到遞歸的好處,迭代也能正常工作。 自從我寫 C 以來已經很久了(並且沒有簡單的方法來測試以下語法錯誤......或者畏縮核心轉儲,但你明白了)。
node *reversed_list(node *list) {
node *fwd=list;//Purely for readability
node *last=null;
node *next=null;
node *rev=null;
do {
//Cache next
next=fwd->next;
//Set current
rev=fwd;
//Reset next to point back
rev->next=last;
//Update last
last=fwd;
//Forward ptr;
fwd=next;
} while (fwd!=null);
return rev;
}
很確定你的*list
在你調用它之后沒用,因為它現在指向列表的最后一個元素->next=null
,可以只更新它而不是返回指針。
更新(用於遞歸解決方案)
正如其他人所說,你的新尾部搞砸了(指向最后一個元素,但應該指向空)......並且你沒有返回正確的頭部,而是返回第二個元素。 考慮列表a->b->null
與您的算法:
p=a, c=b; c= p=b c=null return b; //b->null c=b c->next=a //b->a return a; //a->b, b->a, a returned //But what you wanted is a->null, b->a, and b returned
以下更新的代碼將修復:
node *reverse_list_recursive(node *list)
{
node *parent = list;
node *current = list->next;
if(current == NULL)
return parent;
else
{
current = reverse_list_recursive(current);
current->next = parent;
parent->next=null; //Fix tail
printf("\n %d %d \n",current->value,parent->value);
return current; //Fix head
}
}
使用列表a->b->null
:
p=a, c=b; c= p=b c=null return b; //b->null c=b c->next=a //b->a p->next=null //a->null return b; // b->a->null
current = reverse_list_recursive(current);
您將新的列表頭存儲在 current 中,因此current->next = parent;
是錯誤的。 New current
是新的鏈表頭,但是你需要訪問新的鏈表尾,即 OLD current
:
node* newhead = reverse_list_recursive(current);
current->next = parent;
printf("\n %d %d \n",current->value,parent->value);
return newhead;
我可以看到的一些問題:
這是用於反轉鏈表的遞歸代碼。
list * reverse(list * head)
{
if( head == NULL || head -> link == NULL )
return head;
list *node = reverse( head- > link );
head -> link -> link = head;
head -> link = NULL;
return node;
}
不同的代碼如下:
'
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
struct Node {
int data;
struct Node* next;
};
typedef struct Node node;
node* dogrusıralama(node* r)
{
for (int i = 0; i < 6; i++)
{
printf("%d", r->data);
r = r->next;
printf("\n");
}
}
node *terssıralama(node* r)
{
node* iter;
iter = r;
node* temp;
temp = r;
node* temp2;
temp2 = r;
int a = 4;
for (int k = 0; k < 5; k++)
{
temp2 = temp2->next;
}
for (int j = 0; j < 5; j++)
{
int i = a;
for (; i > 0; i--)
{
temp = temp->next;
}
a--;
iter = temp;
iter->next->next = iter ;
temp = r;
}
temp->next = NULL;
return temp2;
}
int main() {
node* dugum;
node* dugum2;
node* dugum3;
node* dugum4;
dugum = (node*)malloc(sizeof(node*));
dugum2 = dugum;
for (int i = 0; i < 5; i++)
{
dugum2->next = NULL;
dugum2->next = (node*)malloc(sizeof(node*));
dugum2->data = i;
dugum2 = dugum2->next;
}
dugum4 = dugum;
dogrusıralama(dugum);
dugum3 = terssıralama(dugum);
for (int i = 0; i < 6; i++)
{
printf("\n");
printf("%d", dugum3->data);
dugum3 = dugum3->next;
}
} '
上面的 Severl 版本不能像 OP 那樣工作,所以這里是我的遞歸版本測試良好:
node * reverseRecursive(node *p,node **head)
{
if(p->next == NULL)
{
*head = p;
return p;
}
node *before;
before = reverseRecursive(p->next,head);
before->next = p;
p->next = NULL;
return p;
}
//call from main
node*head;
//adding value
//assuming now head is now 1->2->3->4->NULL
node* newHead;
reverseRecursive(head,&newHead);
//now now newHead is now 4->3->2->1->NULL
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.