赞
踩
排序原理:
对最后合并细化分析,核心代码Merge
import java.util.Arrays;
public class MergeSort {
private static int[] arr;
public static void sort(int[] a){
arr = new int[a.length];
sort(a,0,a.length-1);
}
private static void sort(int[] a,int lo, int hi){
if(lo>=hi) return;
int mid = lo + (hi - lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
//合并两个数组
merge(a,lo,mid,hi);
}
private static void merge(int[] a, int lo,int mid ,int hi ){
//指向辅助数组的指针。
int i = lo;
//定义第一个数组的指针,初始指向第一个元素;
int p1 = lo;
//定义第二个数组的指针,初始指向第一个元素
int p2 = mid+1;
//比较两个数组指针指向的元素的大小,哪个小,就放入arr数组
while(p1<=mid&&p2<=hi){
if(a[p1]<a[p2]){
arr[i++]=a[p1++];
}else{
arr[i++]=a[p2++];
}
}
//如果数组二遍历完,数组一没完
while(p1<=mid){
arr[i++] = a[p1++];
}
//如果数组一遍历完,数组二没完
while(p2<=hi){
arr[i++] = a[p2++];
}
//拷贝数组
for (int i1 = lo; i1 <= hi; i1++) {
a[i1] = arr[i1];
}
}
public static void main(String[] args) {
int[] a = {8, 4, 5, 7, 1, 3, 6, 2};
sort(a);
System.out.println(Arrays.toString(a));
}
}
O(nlogn)
归并排序是分治思想的最典型的例子,上面的算法中,对a[lo…hi]进行排序,先将它分为a[lo…mid]和a[mid+1…hi]
两部分,分别通过递归调用将他们单独排序,最后将有序的子数组归并为最终的排序结果。该递归的出口在于如果
一个数组不能再被分为两个子数组,那么就会执行merge进行归并,在归并的时候判断元素的大小进行排序。
用树状图来描述归并,如果一个数组有8个元素,那么它将每次除以2找最小的子数组,共拆log8次,值为3,所以树共有3层,那么自顶向下第k层有2^k个子数组,每个数组的长度为2^(3-k),归并最多需要2^(3-k)次比较。因此每层的比较次数为 2^k * 2^(3-k)=2^3,那么3层总共为 3*2^3。
假设元素的个数为n,那么使用归并排序拆分的次数为log2(n),所以共log2(n)层,那么使用log2(n)替换上面32^3中 的3这个层数,最终得出的归并排序的时间复杂度为:log2(n) 2^(log2(n))=log2(n)*n,根据大O推导法则,忽略底数,最终归并排序的时间复杂度为O(nlogn).
归并排序需要申请额外的数组空间,导致空间复杂度提升,是典型的以空间换时间的操作。
稳定的
归并排序在归并的过程中,只有arr[i]<arr[i+1]的时候才会交换位置,如果两个元素相等则不会交换位置,所以它
并不会破坏稳定性,归并排序是稳定的。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。