連結串列的歸併排序,無需輔助外存
阿新 • • 發佈:2019-01-14
rt, 最近的面試題,面的時候敲的血崩,特此寫下部落格以作留念
如有錯誤,歡迎指正
class Node{
int val;
Node next;
}
import java.util.Random; class Node { public int val; public Node next; public Node(int val) { this.val = val; this.next = null; } } public class Test { public static void main(String[] args) { Random random = new Random(47); Node head = new Node(10); Node p = head; for(int i = 0; i < 9; ++i) { p.next = new Node(random.nextInt(20)); p = p.next; } System.out.print("歸併前:"); for (Node i = head; i != null; i = i.next) System.out.print(i.val + " "); System.out.println(); head = MergeSort(head, 10); System.out.print("歸併後:"); for (Node i = head; i != null; i = i.next) System.out.print(i.val + " "); System.out.println(); } //傳入連結串列頭和連結串列長度,返回新連結串列頭,對以head開始的長度為len的連結串列排序 private static Node MergeSort(Node head, int len) { if (len > 1) { int m = len / 2; head = MergeSort(head, m); Node p = head; for (int i = 0; i < m - 1; ++i) p = p.next; p.next = MergeSort(p.next, len - m); head = merge(head, len, m); } return head; } //對以head開始的長度為len的連結串列合併, [1, m]和[m+1, len]的兩條連結串列 private static Node merge(Node head, int len, int m) { Node p1 = head; Node p1Pre = null; Node p2 = head.next; Node p2Pre = head; for (int i = 0; i < m - 1; ++i) { p2 = p2.next; p2Pre = p2Pre.next; } int l = 1; int r = m + 1; while (l <= m && r <= len) { //將連結串列歸併到p1鏈上 if (p1.val <= p2.val) { p1Pre = p1; p1 = p1.next; ++l; } else { //將p2指向的節點移到p1的前面 p2Pre.next = p2.next; p2.next = p1; if (p1Pre == null) { head = p2; p1Pre = head; } else { p1Pre.next = p2; p1Pre = p2; } p2 = p2Pre.next; ++r; } } return head; } }
雖然連結串列的歸併無需輔存,但連結串列的查詢增加了時間複雜度,而且寫的時候容易出錯,連結串列的歸併也並不好用