以前一直没有考虑过对单链表的排序,直到遇到Leetcode
一、快速排序
单链表的快速排序需要用到快速排序的单向扫描法,总体思路是用一快一慢两个指针,快指针用来寻找小于key的结点,慢指针用来指向当前找到的较小结点应该存储的位置。
public static int partition(int[] nums,int start,int end){
int fast=start+1;
int slow=start;
int key=nums[start];
while(fast<=end){
if(nums[fast]<key){
slow++;
Swap.swap(nums,slow,fast);
}
fast++;
}
Swap.swap(nums,start,slow);
return slow;
}
排序的时候,交换的不是结点的指针,而是交换链表结点的值,有点取巧。
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
quickSort(head,null);
return head;
}
public void quickSort(ListNode begin,ListNode end){
if(begin==end||begin.next==end) return;
ListNode mid=partition(begin,end);
quickSort(begin,mid);
quickSort(mid.next,end);
}
public ListNode partition(ListNode begin,ListNode end){
if(begin==end||begin.next==end) return begin;
int key=begin.val;
ListNode start=begin,next=begin.next;
while(next!=end){
if(next.val<key){
start=start.next;
swapVal(next,start);
}
next=next.next;
}
swapVal(begin,start);
return start;
}
public void swapVal(ListNode p1,ListNode p2){
int t=p1.val;
p1.val=p2.val;
p2.val=t;
}
二、归并排序
单链表归并排序的思路是找到单链表的中间结点,并将链表从中间结点处断开得到两条单链表分别进行归并排序。注意这里需要将中间结点的前一个结点断开,并且中间结点是结点数除2的上界。如2个结点的链表中间结点是第2个,3个结点的链表中间结点是第二个,4个结点的链表中间点结是第3个。
public static ListNode merge(ListNode head1,ListNode head2){
if(head1==null) return head2;
if(head2==null) return head1;
ListNode start1=head1,start2=head2;
ListNode head;
if(start1.data.compareTo(start2.data)<0){
head=start1;
start1=start1.next;
}else{
head=start2;
start2=start2.next;
}
head.next=merge(start1,start2);
return head;
}
public static ListNode getMid(ListNode head){
if(head==null||head.next==null) return head;
ListNode fast=head.next.next;
ListNode slow=head.next;
ListNode pre=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next;
if(fast.next!=null) fast=fast.next;
}
pre.next=null;
return slow;
}
public static ListNode mergeSort(ListNode head){
if(head==null||head.next==null) return head;
ListNode head1=head;
ListNode head2=getMid(head);
head1=mergeSort(head1);
head2=mergeSort(head2);
return merge(head1,head2);
}