归并排序的一种比较快的排序,尤其在链表中,在所有排序中是时间复杂度为nlog(n)级别的有三种,分别为快速排序,堆排序和归并排序,但是快速排序在单链表中没有优势(适合于双向链表),同样堆排序在建堆和调整堆得过程对于单链表也是比较麻烦,这里我们选取了归并排序。
归并排序的概念和原理我就不介绍了,网上的相关资料比较多。在这里,我只想记录一个思路,归并的排序分为三步走:1 分割,2 递归,3 合并。
首先链表的定义如下:
public class ListNode {
int val;
ListNode next;
ListNode(int x)
{
val = x;
next = null;
}
}
使用快慢指针,等分单向链表,并调用merge函数对链表排序,具体如下:
public ListNode mergeSort(ListNode head) {
ListNode first = head;
ListNode second = head;
if (null == first || null == second) {
return first;
}
// 使用快慢指针将链表等分为两个链表
while (second.next != null && second.next.next != null) {
first = first.next;
second = second.next.next;
}
//断开
if (first.next != null) {
second = first.next;
first.next = null;
first = head;
}
// 只剩一个节点时,返回
if (first == second) {
return first;
}
//递归调用mergeSort方法
return merge(mergeSort(first), mergeSort(second));
}
按递增顺序,将两个有序单向链表,归并成一个有序单向链表,如下:
public ListNode merge(ListNode first, ListNode second) {
ListNode tmp;
if (first == null)
return second;
if (second == null)
return first;
if (first.val < second.val) {
tmp = first;
first = first.next;
} else {
tmp = second;
second = second.next;
}
tmp.next = merge(first, second); //这个是关键
return tmp;
}