import java.util.Arrays;
public class paixu____MergeSort {
public static void main(String []args){
int []arr = {8,4,5,7,1,3,6,2};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int []arr){
int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
sort(arr,0,arr.length-1,temp);
}
private static void sort(int[] arr,int left,int right,int []temp){
if(left<right){
int mid = (left+right)/2;
System.out.print("1111 "+Arrays.toString(arr));
System.out.print("left "+left);
System.out.print("mid "+mid);
System.out.println("-------------左边归并排序---------");
sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
System.out.print("2222 "+Arrays.toString(arr));
System.out.print("mid+1 "+(mid+1));
System.out.print("right "+right); System.out.println("-----------右边归并排序---------------");
sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
System.out.print("3333 "+Arrays.toString(arr));
System.out.print("left "+left);
System.out.print("mid "+mid);
System.out.print("right "+right); System.out.println("--------将两个有序子数组合---------------");
merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
System.out.print("4444 "+Arrays.toString(arr)); System.out.println("---------------------------");
}
}
private static void merge(int[] arr,int left,int mid,int right,int[] temp){
System.out.print("left "+left);
System.out.print("mid "+mid);
System.out.print("right "+right);
System.out.println("+++++++++++++++++++++");
int i = left;//左序列指针
int j = mid+1;//右序列指针
int t = 0;//临时数组指针
while (i<=mid && j<=right){
if(arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[t++] = arr[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[t++] = arr[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
arr[left++] = temp[t++];
}
}
}
1111 [8, 4, 5, 7, 1, 3, 6, 2]left 0mid 3-------------左边归并排序---------
1111 [8, 4, 5, 7, 1, 3, 6, 2]left 0mid 1-------------左边归并排序---------
1111 [8, 4, 5, 7, 1, 3, 6, 2]left 0mid 0-------------左边归并排序---------
2222 [8, 4, 5, 7, 1, 3, 6, 2]mid+1 1right 1-----------右边归并排序---------------
3333 [8, 4, 5, 7, 1, 3, 6, 2]left 0mid 0right 1--------将两个有序子数组合---------------
left 0mid 0right 1+++++++++++++++++++++
4444 [4, 8, 5, 7, 1, 3, 6, 2]---------------------------
2222 [4, 8, 5, 7, 1, 3, 6, 2]mid+1 2right 3-----------右边归并排序---------------
1111 [4, 8, 5, 7, 1, 3, 6, 2]left 2mid 2-------------左边归并排序---------
2222 [4, 8, 5, 7, 1, 3, 6, 2]mid+1 3right 3-----------右边归并排序---------------
3333 [4, 8, 5, 7, 1, 3, 6, 2]left 2mid 2right 3--------将两个有序子数组合---------------
left 2mid 2right 3+++++++++++++++++++++
4444 [4, 8, 5, 7, 1, 3, 6, 2]---------------------------
3333 [4, 8, 5, 7, 1, 3, 6, 2]left 0mid 1right 3--------将两个有序子数组合---------------
left 0mid 1right 3+++++++++++++++++++++
4444 [4, 5, 7, 8, 1, 3, 6, 2]---------------------------
2222 [4, 5, 7, 8, 1, 3, 6, 2]mid+1 4right 7-----------右边归并排序---------------
1111 [4, 5, 7, 8, 1, 3, 6, 2]left 4mid 5-------------左边归并排序---------
1111 [4, 5, 7, 8, 1, 3, 6, 2]left 4mid 4-------------左边归并排序---------
2222 [4, 5, 7, 8, 1, 3, 6, 2]mid+1 5right 5-----------右边归并排序---------------
3333 [4, 5, 7, 8, 1, 3, 6, 2]left 4mid 4right 5--------将两个有序子数组合---------------
left 4mid 4right 5+++++++++++++++++++++
4444 [4, 5, 7, 8, 1, 3, 6, 2]---------------------------
2222 [4, 5, 7, 8, 1, 3, 6, 2]mid+1 6right 7-----------右边归并排序---------------
1111 [4, 5, 7, 8, 1, 3, 6, 2]left 6mid 6-------------左边归并排序---------
2222 [4, 5, 7, 8, 1, 3, 6, 2]mid+1 7right 7-----------右边归并排序---------------
3333 [4, 5, 7, 8, 1, 3, 6, 2]left 6mid 6right 7--------将两个有序子数组合---------------
left 6mid 6right 7+++++++++++++++++++++
4444 [4, 5, 7, 8, 1, 3, 2, 6]---------------------------
3333 [4, 5, 7, 8, 1, 3, 2, 6]left 4mid 5right 7--------将两个有序子数组合---------------
left 4mid 5right 7+++++++++++++++++++++
4444 [4, 5, 7, 8, 1, 2, 3, 6]---------------------------
3333 [4, 5, 7, 8, 1, 2, 3, 6]left 0mid 3right 7--------将两个有序子数组合---------------
left 0mid 3right 7+++++++++++++++++++++
4444 [1, 2, 3, 4, 5, 6, 7, 8]---------------------------
[1, 2, 3, 4, 5, 6, 7, 8]
Process finished with exit code 0
另一个参考代码:
链表的归并排序
方法一:自顶向下归并排序
对链表自顶向下归并排序的过程如下。
找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以使用快慢指针的做法,快指针每次移动 22 步,慢指针每次移动 11 步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
对两个子链表分别排序。
将两个排序后的子链表合并,得到完整的排序后的链表。可以使用「21. 合并两个有序链表」的做法,将两个有序的子链表进行合并。
上述过程可以通过递归实现。递归的终止条件是链表的节点个数小于或等于 11,即当链表为空或者链表只包含 11 个节点时,不需要对链表进行拆分和排序。
class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}
public ListNode sortList(ListNode head, ListNode tail) {
if (head == null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
ListNode slow = head, fast = head;
while (fast != tail) {
slow = slow.next;
fast = fast.next;
if (fast != tail) {
fast = fast.next;
}
}
ListNode mid = slow;
ListNode list1 = sortList(head, mid);
ListNode list2 = sortList(mid, tail);
ListNode sorted = merge(list1, list2);
return sorted;
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
while (temp1 != null && temp2 != null) {
if (temp1.val <= temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
} else if (temp2 != null) {
temp.next = temp2;
}
return dummyHead.next;
}
}
// 作者:LeetCode-Solution
// 链接:https://leetcode-cn.com/problems/sort-list/solution/pai-xu-lian-biao-by-leetcode-solution/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法二:自底向上归并排序
flag