归并排序–八大排序算法
和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
将两个排序好的子序列合并成一个最终的排序序列。
代码
java
package sort;
import java.util.Arrays;
public class MergerSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[] = {8,4,5,7,1,3,6,2};
int temp[] = new int[arr.length];
System.out.println(Arrays.toString(arr));
System.out.println("排序后:");
mergerSort(arr, 0, arr.length - 1, temp);
System.out.println(Arrays.toString(arr));
}
/**
* 分+ 治 方法
* @param arr
* @param left
* @param right
* @param temp
*/
public static void mergerSort(int arr[], int left,int right,int temp[] ) {
if(left < right) {
int mid = (left + right )/2;
//向左递归分解
mergerSort(arr, left, mid, temp);
//向右递归分解
mergerSort(arr, mid + 1, right, temp);
merger(arr, left, right, mid, temp);
}
}
/**
* 合并的方法
* @param arr
* @param left 有序序列的初始索引
* @param right 中间索引
* @param mid 右边索引
* @param temp 递归共享的数组
*/
public static void merger(int arr[],int left,int right,int mid,int temp[] ){
int i = left;
int j = mid +1;
int t = 0;
//比较俩个有序序列,将小的数放到temp数组
while(i <= mid && j <= right) {
if(arr[i] <= arr[j]) {
temp[t] = arr[i];
i++;
t++;
}else {
temp[t] = arr[j];
j++;
t++;
}
}
//如果有剩余,将剩余的放到temp数组里
while(i <= mid) {
temp[t] = arr[i];
t++;
i++;
}
while(j <= right) {
temp[t] = arr[j];
j++;
t++;
}
//将temp数组拷贝到arr数组
t = 0;
while(left <= right) {
arr[left] = temp[t];
t++;
left++;
}
}
}
c
/**
* 归并排序
*
* @param array
* @return
*/
public static int[] MergeSort(int[] array) {
if (array.length < 2) return array;
int mid = array.length / 2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(MergeSort(left), MergeSort(right));
}
/**
* 归并排序——将两段排序好的数组结合成一个排序数组
*
* @param left
* @param right
* @return
*/
public static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
for (int index = 0, i = 0, j = 0; index < result.length; index++) {
if (i >= left.length)
result[index] = right[j++];
else if (j >= right.length)
result[index] = left[i++];
else if (left[i] > right[j])
result[index] = right[j++];
else
result[index] = left[i++];
}
return result;
}