1. 程式人生 > >單鏈表的就地逆置(頭插法和遞迴法)【轉】

單鏈表的就地逆置(頭插法和遞迴法)【轉】

單鏈表的就地逆置是指輔助空間O(1)的逆置方法,有兩種方法:普通迴圈(頭插法重新建立帶頭節點的新連結串列)和遞迴。下面我們詳細介紹這兩種方法:

方法一:頭插法

演算法思想:逆置連結串列初始為空,表中節點從原連結串列中依次“刪除”,再逐個插入逆置連結串列的表頭(即“頭插”到逆置連結串列中),使它成為逆置連結串列的“新”的第一個結點,如此迴圈,直至原連結串列為空。

  1. void converse(LinkList *head)

  2. {

  3. LinkList *p,*q;

  4. p=head->next;

  5. head->next=NULL;

  6. while(p)

  7. {

  8. /*向後挪動一個位置*/

  9. q=p;

  10. p=p->next;

  11. /*頭插*/

  12. q->next=head->next;

  13. head->next=q;

  14. }

  15. }

頭插法圖解:


 

補充:

對於不含頭結點的單鏈表的頭插法原地逆置

  1. ListNode* converse(ListNode *head)

  2. {

  3. ListNode* dumyOfInsertedList = new ListNode(-1);//一個啞結點,用於建立新的連結串列

  4. if(head == NULL) return NULL;

  5. ListNode* unInsertedHead = head;// 使用unInsertedHead和inInsertHead_next作為待逆置連結串列的首結點和次首結點的便籤

  6. ListNode* unInsertedHead_next = head->next;

  7. while(unInsertedHead)// 頭插直到原連結串列為空

  8. {

  9. unInsertedHead->next = dumyOfInsertedList->next;

  10. dumyOfInsertedList->next = unInsertedHead;

  11. unInsertedHead = unInsertedHead_next;

  12. if(unInsertedHead_next!=NULL)// 注意:最後一個結點時,unInsertedHead_next為NULL沒有next成員變數

  13. {

  14. //cout<<"head:"<< unInsertedHead->val<<"next:"<<unInsertedHead_next->val<<endl;

  15. unInsertedHead_next = unInsertedHead_next->next;

  16. }

  17. }

  18. return dumyOfInsertedList->next;

  19. }

方法二:遞迴

演算法思想:先假定有一個函式,可以將以head為頭結點的單鏈表逆序,並返回新的頭結點。利用這個函式對問題進行求解:將連結串列分為當前表頭結點和其餘部分,遞迴的過程就是,先將表頭結點從連結串列中拆出來,然後對其餘部分進行逆序,最後將當前的表頭結點連結到逆序連結串列的尾部。遞迴的終止條件就是連結串列只剩一個節點時,直接返回這個節點。

  1. /*

  2. dfs深度遍歷這個單鏈表

  3. 在遞迴的時候,不作處理

  4. 在回溯時,標記回溯開始的位置(新的頭結點),將節點和節點的下一節點逆置,將新的頭結點傳遞給上一層遞迴,

  5. 接下來逆置上一個節點和上一節點的下一個節點(逆置已逆置連結串列的尾節點),並傳遞標記的頭結點,直到回溯完成

  6. 我們就得到了逆轉的單鏈表和它的頭結點

  7. dfs(當前狀態)

  8. {

  9.     if(邊界狀態)   //head==NULL說明連結串列為空,不用處理, 從頭到尾我們需要處理的最後一個節點是倒數第二個節點,將它和倒數第一逆置,因此,遍歷到倒是第一個節點就是邊界條件

  10.     {

  11.        記錄       //標記頭結點位置並傳遞(這裡選用返回值,還可以通過全域性變數)給上一層遞迴

  12.     }

  13.     dfs(下一狀態) 

  14.     //回溯部分    //節點和下一節點(逆置這已逆置連結串列的尾結點和),將新的頭結點傳遞給上一層遞迴

  15. }

  16. */

  17. ListNode *reverse(ListNode *head)

  18. {

  19.     if(head==NULL || head->next ==NULL)

  20.         return head;

  21.     /*遞迴*/

  22.     ListNode* headOfReverse = reverse(head->next);

  23.     // cout<<head->next<<" "<<headOfReverse<<endl;

  24.     /*回溯:將當前表頭結點連結到逆序連結串列的尾部*/

  25.     head->next->next = head;

  26.     head->next = NULL;

  27.     return headOfReverse;

  28. }

遞迴法圖解: