[英]Reverse a linked list using recursion
void reve(struct Node *head)
和display(struct Node *head)
方法采用一个参数 - 链表的头部。 我想打印整个链表,但我的显示 function 只打印4
。
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *link;
};
void display(struct Node *head) {
if (head == NULL) {
return;
}
cout << head->data << "\t";
display(head->link);
//head = head->link;
}
struct Node *reve(struct Node *head) {
struct Node *p = head;
if (p->link == NULL) {
head = p;
return head;
}
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
struct Node *insert(struct Node *head, int new_data) {
Node *new_node = new Node();
new_node->data = new_data;
new_node->link = head;
head = new_node;
return head;
}
int main() {
Node *head = NULL;
head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
cout << "The linked list is: ";
//display(head);
head = reve(head);
display(head);
return 0;
}
如果p->link
不是NULL
,则 function reve
不会返回值。
由于head
有超过 1 个元素,所以head = reve(head);
具有未定义的行为。
与递归相比,在简单循环中反转链表更容易实现:
struct Node *reve(struct Node *p) {
if (p != NULL) {
struct Node *prev = NULL;
while (p->link) {
struct Node *next = p->link;
p->link = prev;
prev = p;
p = next;
}
}
return p;
}
如果您的任务需要递归,您可以提取第一个节点,反转列表的其余部分,并将 append 作为第一个节点。 请注意,这不是尾递归,因此任何足够长的列表都可能导致堆栈溢出。
struct Node *reve(struct Node *head) {
if (head != NULL && head->link != NULL) {
struct Node *first = head;
struct Node *second = head->link;
head = reve(second);
first->link = NULL; // unlink the first node
second->link = first; // append the first node
}
return head;
}
如果你想要递归方式:
Node* reverse(Node* head)
{
if (head == NULL || head->next == NULL)
return head;
/* reverse the rest list and put
the first element at the end */
Node* rest = reverse(head->next);
head->next->next = head;
head->next = NULL;
/* fix the head pointer */
return rest;
}
/* Function to print linked list */
void print()
{
struct Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
在 C++ 中,当已声明的结构或 class 用作类型说明符时,您无需使用关键字struct
或class
。
function reve
具有未定义的行为。
首先head
可以等于nullptr
。 在这种情况下,此语句
if (p->link == NULL) {
调用未定义的行为。
其次, function 在p->link
不等于nullptr
的情况下不返回任何内容。
//...
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
这是一个演示程序,展示了如何实现这些功能。 当结构用作类型说明符时,我使用了包含关键字struct
的 C 方法。
#include <iostream>
struct Node
{
int data;
struct Node *link;
};
struct Node * insert( struct Node *head, int data )
{
return head = new Node{ data, head };
}
struct Node * reverse( struct Node *head )
{
if ( head && head->link )
{
struct Node *tail = head;
head = reverse( head->link );
tail->link->link = tail;
tail->link = nullptr;
}
return head;
}
std::ostream & display( struct Node *head, std::ostream &os = std::cout )
{
if ( head )
{
os << head->data;
if ( head->link )
{
os << '\t';
display( head->link, os );
}
}
return os;
}
int main()
{
struct Node *head = nullptr;
const int N = 10;
for ( int i = 0; i < N; i++ )
{
head = insert( head, i );
}
display( head ) << '\n';
head = reverse( head );
display( head ) << '\n';
return 0;
}
程序 output 是
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
display
很好。
我注意到的第一件事是您正在尝试修改复制的值。 例如第 16 行。此代码无效。
请注意,您在插入时有一个错误:您返回head
而不是new_node
。
对于超过 1 个项目的列表,您的版本失败。 reve()
应该返回原始列表的最后一个节点,而您没有这样做,因此 lastNode 不会指向反向列表的最后一个节点。 所以我的建议是你把它放在一边。
所以, reve
:
struct Node* reve(struct Node* head) {
if (head->link == NULL) {
return head;
}
struct Node* lastNode = reve(head->link);
lastNode->link = head;
head->link = NULL;
return head;
}
和main
:
int main() {
Node* head = NULL;
Node* last_node = head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
head = reve(head);
cout << "The linked list is: ";
// Now, last_node is the new head
display(last_node);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.