动画演示:
原理:
分治法,先整个数组排序递归到分成小块排序,递归到只有一个元素即本身有序返回,到两个元素进行合并成有序,再到四个元素合并到有序......以此类推到整个数组元素有序
思路:
- 把数组不断划分成子序列,划成长度只有2或者1的子序列。
- 然后利用临时数组,对子序列进行排序,合并,再把临时数组的值复制回原数组。
- 反复操作1~2步骤,直到排序完成。
代码:
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[]{2, 6, 3, 4, 9, 8};
sort(arr,0,arr.length-1);
print(arr);
}
private static void sort(int[] arr, int left, int right) {
//递归终止条件(只有一个元素,默认有序)
if(left >= right)
return;
int mid = left + (right - left)/2;
//向左递归
sort(arr,left,mid);
//向右递归
sort(arr,mid+1,right);
//左右数组都已有序,进行合并
merge(arr,left,mid+1,right);
}
/**
* 合并两个数组
* @param arr
* @param leftPtr 左边数组开始位置
* @param rightPtr 右边数组开始位置
* @param rightBound 右边数组边界 左边数组边界 -> rightPtr-1
*/
private static void merge(int[] arr, int leftPtr, int rightPtr, int rightBound) {
int[] temp = new int[rightBound - leftPtr + 1];
int i = leftPtr;
int j = rightPtr;
int k = 0;
//两个数组没有越界,比较大小放入临时数组
while(i <= rightPtr -1 && j <= rightBound){
if(arr[i] < arr[j]){
temp[k++] = arr[i++];
}else{
temp[k++] = arr[j++];
}
}
//上一个while退出,说明有一个数组元素已经全部放入临时数组了
while(i <= rightPtr -1){
temp[k++] = arr[i++];
}
while(j <= rightBound){
temp[k++] = arr[j++];
}
//临时数组已经全部有序,放回到原来的数组中
for(int index = 0;index<temp.length;index++){
arr[index + leftPtr] = temp[index];
}
}
private static void print(int []arr)
{
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
}
}
算法复杂度:O(nlogn)
算法空间复杂度:O(n)
算法稳定性:稳定