一、分治法的思想
把复杂的问题分解,再分解,成为很小的问题,解决这些小问题之后合并,再合并。这就是分治法的思想。
通常分治法是递归的。
二、归并排序
归并排序就是利用分治法,把无序的数列拆分成多个子数列,子数列再拆分成多个子数列,直至只子数列只有2个数,然后排序,合并,再排序,在合并。。。直到只剩一个有序的数列。
归并排序算法的核心就是:两个各自有序的数列合并成一个完全有序的数列。这个过程可以说很简单,就是从两个数列开头选出最小的数,放入第三个数列中,然后较小的数的指标后移,继续重复操作。直到其中一个数列全部被放入队列中,此时另一个队列剩下的全部数放入第三个数列。
归并排序的时间复杂度是O(nlgn)
如图所示:
三、Java代码实现
public class MergeSort {
public static void main(String[] args) {
int a[] = {5,3,2,8,7,6,10,20,30,11,22,33,44,100,60,200};
mergeSort(a, 0, a.length - 1);
for (int i : a) {
System.out.println(i);
}
}
//递归拆分数列
public static void mergeSort(int[] a, int low, int high) {
int middle = (low + high) / 2;
if (low < high) {
mergeSort(a, low, middle);
mergeSort(a, middle + 1, high);
merge (a, low, middle, high);
}
}
//合并两段有序数列
public static void merge(int[] a, int low, int middle, int high) {
int n1 = middle - low + 1;
int n2 = high - middle;
int[] l = new int[n1];
int[] r = new int[n2];
for (int i = low, j = 0; i <= middle; i++, j++) {
l[j] =a[i];
}
for (int i = middle + 1, j= 0; i <= high; i++, j++) {
r[j] = a[i];
}
int i = 0;
int j = 0;
int k = low;
while(i < n1 || j < n2) {
if (i < n1 && j < n2) {
if (l[i] < r[j]) {
a[k++] = l[i];
i++;
}else {
a[k++] = r[j];
j++;
}
} else if (i < n1) {
a[k++] = l[i];
i++;
} else if (j < n2) {
a[k++] = r[j];
j++;
}
}
}
}
四、思考归并排序的优化。
归并排序的时间复杂度是nlgn ,插入排序的时间复杂度是n^2。
归并排序在n较小的时候是不如插入排序的。所以我们可以使用归并排序划分,到一定数的时候使用插入排序进行底层的排序,这样优化起来就非常合理了。
来源:oschina
链接:https://my.oschina.net/u/2250599/blog/514438