http://blog.csdn.net/lycnjupt/article/details/47103433
https://blog.csdn.net/v_xchen_v/article/details/53067448
单链表的就地逆置是指辅助空间O(1)的逆置方法,有两种方法:普通循环(头插法重新建立带头节点的新链表)和递归。下面我们详细介绍这两种方法:
方法一:头插法
算法思想:逆置链表初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。
- void converse(LinkList *head)
- {
- LinkList *p,*q;
- p=head->next;
- head->next=NULL;
- while(p)
- {
- /*向后挪动一个位置*/
- q=p;
- p=p->next;
- /*头插*/
- q->next=head->next;
- head->next=q;
- }
- }
头插法图解:
补充:
对于不含头结点的单链表的头插法原地逆置
- ListNode* converse(ListNode *head)
- {
- ListNode* dumyOfInsertedList = new ListNode(-1);//一个哑结点,用于创建新的链表
- if(head == NULL) return NULL;
- ListNode* unInsertedHead = head;// 使用unInsertedHead和inInsertHead_next作为待逆置链表的首结点和次首结点的便签
- ListNode* unInsertedHead_next = head->next;
- while(unInsertedHead)// 头插直到原链表为空
- {
- unInsertedHead->next = dumyOfInsertedList->next;
- dumyOfInsertedList->next = unInsertedHead;
- unInsertedHead = unInsertedHead_next;
- if(unInsertedHead_next!=NULL)// 注意:最后一个结点时,unInsertedHead_next为NULL没有next成员变量
- {
- //cout<<"head:"<< unInsertedHead->val<<"next:"<<unInsertedHead_next->val<<endl;
- unInsertedHead_next = unInsertedHead_next->next;
- }
- }
- return dumyOfInsertedList->next;
- }
方法二:递归
算法思想:先假定有一个函数,可以将以head为头结点的单链表逆序,并返回新的头结点。利用这个函数对问题进行求解:将链表分为当前表头结点和其余部分,递归的过程就是,先将表头结点从链表中拆出来,然后对其余部分进行逆序,最后将当前的表头结点链接到逆序链表的尾部。递归的终止条件就是链表只剩一个节点时,直接返回这个节点。
- LinkList* converse(LinkList *head)
- {
- LinkList *newHead;
- if(head==NULL||head->next==NULL)
- return head;
- /*递归*/
- newHead=converse(head->next);
- /*回溯:将当前表头结点链接到逆序链表的尾部*/
- head->next->next=head;
- head->next=null;
- return newHead;
- }
递归法图解: