数据结构:单链表就地逆置(递归方法)解析
先上代码:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 struct ListNode { 6 int value; 7 ListNode *next; 8 ListNode(int x) :value(x), next(NULL) {} 9 }; 10 11 //单链表的转置 12 // 1)递归方法 13 ListNode* reverseByRecursion(ListNode *head) 14 { 15 if (head == NULL || head->next == NULL) 16 return head; 17 ListNode *newhead = reverseByRecursion(head->next); 18 19 head->next->next = head; 20 head->next = NULL; 21 return newhead; 22 } 23 24 int main() { 25 ListNode a(3); 26 ListNode b(1); 27 ListNode c(5); 28 ListNode d(6); 29 ListNode e(2); 30 a.next = &b; 31 b.next = &c; 32 c.next = &d; 33 d.next = &e; 34 ListNode *head = &a; 35 ListNode* newhead = reverseByRecursion(head); 36 while (newhead != NULL) { 37 printf("%d\n", newhead->value); 38 newhead = newhead->next; 39 } 40 system("pause"); 41 }
强烈建议用visual studio,特别是在用到递归的时候,程序什么时候返回,返回到哪里,指针指向的内容会比较难以弄清,但是单步调试就解决了这个问题。
首先定义一个链表:
1 struct ListNode{ 2 int value; 3 ListNode *next; 4 ListNode(int x):value(x),next(NULL){} 5 };
然后把它们给串联起来形成一个链表:
1 ListNode a(3); 2 ListNode b(1); 3 ListNode c(5); 4 ListNode d(6); 5 ListNode e(2); 6 a.next = &b; 7 b.next = &c; 8 c.next = &d; 9 d.next = &e;
接着就是进行递归调用,从最后一个节点开始,每每两个节点进行就地逆置,这里要搞明白什么是浅拷贝,
浅拷贝的意思就是只复制引用(指针),而未复制真正的值。
所以newhead的处理流程是这样的,
2->6 2->6->5 2->6->5->1 2->6->5->1->3
每次两两就地逆置的时候,会关联前面的上下文。
下面几行的代码不清楚的地方就用单步调试去运行,会有收获的。搞清楚每个节点都相对应的内存空间,我们要做的事只是重新对这些节点进行排序。
1 ListNode *newhead = reverseByRecursion(head->next); 2 3 head->next->next = head; 4 head->next = NULL; 5 return newhead;
以上。