單鏈表的就地逆置是指輔助空間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;
- }
遞歸法圖解:
參考:http://blog.csdn.net/lycnjupt/article/details/47103433