鍊錶二路歸併排序

2021-10-12 10:20:55 字數 1586 閱讀 5680

給你鍊錶的頭結點head,請將其按公升序排列並返回排序後的鍊錶

例如:4->2->1->3

排序  1->2->3->4

要求時間複雜度o(nlongn)  空間複雜度 o(1)

節點結構

public class listnode 

listnode(int val)

listnode(int val, listnode next)

}

歸併排序的含義   將兩個或者兩個以上的有序表組合成乙個新的有序表

該題使用的是二路歸併,即   兩個有序表組合成乙個新的有序表,如果還是不理解歸併排序,檢視我的另一篇部落格排序圖接

現在解決問題的思路有了,但面對的有這麼兩個問題:

1. 如何從鍊錶中獲取兩個有序鍊錶

2. 如何將兩個有序鍊錶整合成乙個新的有序鍊錶

對於問題1,解決方案:

每次查詢鍊錶的中間節點,將鍊錶從中間斷開,即  mid 的前乙個節點的next置為null,此時整個鍊錶分為前半段後半段

前半段與後半段    分別繼續查詢中間節點,繼續分為     更小的前半段 與 更小後半段 (遞迴思想)

分到最後,會出現  前半段就是乙個節點,後半段也就是乙個節點        此時可以看作兩個都是有序的鍊錶,即此時從鍊錶中獲取到了兩個有序鍊錶

對於問題2,解決方案:

首先要是兩個頭節點有乙個為null,直接返回另乙個

兩個頭節點都不為空,val小的為新鍊錶的頭節點,定義工作指標p,遍歷root1  root2,p永遠指向小的,最後要是root1先為null,p.next就等於root2,反之p.next=root1

下面附上比較完整的**

public listnode sortlistii(listnode head)

listnode mid = slow.next;

slow.next = null;

listnode left = sortlistii(head);

listnode right = sortlistii(mid);

return concat(left,right);

}//二路歸併排序 快慢指標

public listnode concat(listnode root1,listnode root2)else

//工作節點

listnode p = root;

while (root1!=null && root2!=null)else

p = p.next;

}//連線上 最後剩下的有序鍊錶

p.next = root1==null ? root2 : root1;

//返回頭節點

return root;

}//二路合一

歸併排序(二路歸併)

歸併排序是一種遞迴思想的體現,通過多次合併較小的幾個 二路歸併為兩個 有序陣列形成新的有序表。思路 將陣列分為n nn個一元組,兩兩合併得到二元組,以此類推共合併log 2n log 2n log2 n 次後,陣列變得有序。時間複雜度為o n logn o nlogn o nlog n 編譯環境de...

二路歸併排序

不是困難的演算法,不過也是練習了下遞迴。include include include using namespace std const int maxn 100 5 int a maxn int b maxn void mergesort int a,int b,int begin,int en...

二路歸併排序

二路歸併排序是將兩個有序表合併成乙個有序表的排序方法。其基本思想為 序列中有 n個記錄,可以看作為 n個有序子串行,每個序列長度為 1。首先將每相鄰的兩個記錄合併,得到 n 2 個較大的有序子串行,每個序列長度為 2。再將上述子串行兩兩合併,得到 n 2 2 個有序子串行,直至得到乙個長度為 n的有...