序言
这篇大家谈一种根据合并实际操作进行排列的优化算法。
归并排序优化算法构思
要将一个数组排序,能够 先将二维数组分成2个二维数组各自排列,随后再将結果归并在一起,反复递归这一全过程,直至二维数组总体井然有序,这就是归并排序的优化算法构思。
归并排序的优势是它可以确保随意长短为N的数组排序需要的時间与 NlogN 正相关,这一优势是初中级排列没法做到的。
缺陷是由于合并实际操作必须引进附加的二维数组,附加的室内空间与N正相关
原地不动合并完成
在完成归并排序以前,大家必须先进行2个井然有序二维数组的合并实际操作,将要2个井然有序的数组合并成一个井然有序的二维数组;
- public class MergeSort implements SortTemplate {
- private Comparable[] aux;
- @Override
- public void sort(Comparable[] array) {
- //待完成
- }
- private void merge(Comparable[] a, int lo, int mid, int hi) {
- for (int i = lo; i <= hi; i ) {
- aux[i] = a[i];
- }
- int i = lo, j = mid 1;
- for (int k = lo; k <= hi; k ) {
- if (i > mid) {
- a[k] = aux[j ];
- } else if (j > hi) {
- a[k] = aux[i ];
- } else if (less(aux[i], aux[j])) {
- a[k] = aux[i ];
- } else {
- a[k] = aux[j ];
- }
- }
- }
- }
自顶向下的归并排序
根据分而治之的观念,大的数组排序,先递归拆分为小的二维数组,确保小的二维数组井然有序再合并,直至全部二维数组井然有序,这一实际操作便是自顶向下的归并排序
- public class MergeSort implements SortTemplate {
- private Comparable[] aux;
- @Override
- public void sort(Comparable[] array) {
- aux = new Comparable[array.length];
- doSort(array, 0, array.length - 1);
- }
- private void doSort(Comparable[] array, int lo, int hi) {
- if (lo >= hi) {
- return;
- }
- int mid = (hi - lo) / 2 lo;
- doSort(array, lo, mid);
- doSort(array, mid 1, hi);
- merge(array, lo, mid, hi);
- }
- private void merge(Comparable[] a, int lo, int mid, int hi) {
- //省去
- }
- }
之上编码是规范的递归归并排序实际操作,可是历经细心思索以后,该优化算法也有能够 提升的地区
「检测二维数组是不是早已井然有序」;如果a[mid]<=a[mid 1],那麼大家就可以绕过merge方式 ,降低merge实际操作;修补以后的doSort方式
- private void doSort(Comparable[] array, int lo, int hi) {
- if (lo >= hi) {
- return;
- }
- int mid = (hi - lo) / 2 lo;
- doSort(array, lo, mid);
- doSort(array, mid 1, hi);
- if (array[mid].compareTo(array[mid 1]) >= 0) {
- merge(array, lo, mid, hi);
- }
- }
「针对小规模纳税人的二维数组能够 是用插入排序」;针对小规模纳税人的二维数组应用归并排序会提升递归调用栈,因此我们可以考虑到应用插入排序来解决子二维数组的排列
- private void doSort(Comparable[] array, int lo, int hi) {
- if (lo >= hi) {
- return;
- }
- if (hi - lo < 5) { //检测,低于5就应用插入排序
- insertionSort(array, lo, hi);
- return;
- }
- int mid = (hi - lo) / 2 lo;
- doSort(array, lo, mid);
- doSort(array, mid 1, hi);
- if (less(array[mid 1], array[mid])) {
- merge(array, lo, mid, hi);
- }
- }
- //插入排序
- private void insertionSort(Comparable[] array, int lo, int hi) {
- for (int i = lo; i <= hi; i ) {
- for (int j = i; j > lo && less(array[j], array[j - 1]); j--) {
- exch(array, j, j - 1);
- }
- }
- }
「节约拷贝原素到輔助二维数组的時间」;要完成该实际操作较不便,必须在每一层递归的情况下互换键入数据信息和輸出二维数组的人物角色;改动以后的详细编码以下:
- public class MergeSort implements SortTemplate {
- private Comparable[] aux;
- @Override
- public void sort(Comparable[] array) {
- aux = array.clone();
- doSort(aux, array, 0, array.length - 1);
- }
- private void doSort(Comparable[] src, Comparable[] dest, int lo, int hi) {
- if (lo >= hi) {
- return;
- }
- if (hi - lo < 5) { //检测,低于5就应用插入排序
- insertionSort(dest, lo, hi);
- return;
- }
- int mid = (hi - lo) / 2 lo;
- doSort(dest, src, lo, mid);
- doSort(dest, src, mid 1, hi);
- if (less(src[mid 1], src[mid])) {
- merge(src, dest, lo, mid, hi);
- }
- }
- //插入排序
- private void insertionSort(Comparable[] array, int lo, int hi) {
- for (int i = lo; i <= hi; i ) {
- for (int j = i; j > lo && less(array[j], array[j - 1]); j--) {
- exch(array, j, j - 1);
- }
- }
- }
- private void merge(Comparable[] src, Comparable[] dest, int lo, int mid, int hi) {
- int i = lo, j = mid 1;
- for (int k = lo; k <= hi; k ) {
- if (i > mid) {
- dest[k] = src[j ];
- } else if (j > hi) {
- dest[k] = src[i ];
- } else if (less(src[i], src[j])) {
- dest[k] = src[i ];
- } else {
- dest[k] = src[j ];
- }
- }
- }
- }
每一层递归实际操作都是会让子二维数组井然有序,可是子二维数组可能是aux[lo..hi]也是有可能是a[lo..hi];因为第一次启用doSort传到的是src=aux,dest=array,因此递归最终的結果一定是键入到array中,确保了array总体排列进行
自底向上的归并排序
完成合并优化算法也有另一种构思,便是先合并什么小的二维数组,随后再成对合并获得子二维数组,直至全部二维数组井然有序
- public class MergeSort implements SortTemplate {
- private Comparable[] aux;
- @Override
- public void sort(Comparable[] array) {
- int length = array.length;
- aux = new Comparable[length];
- for (int sz = 1; sz < length; sz = sz) {
- for (int i = 0; i < length - sz; i = 2 * sz) {
- merge(array, i, i sz - 1, Math.min(i 2 * sz - 1, length - 1));
- }
- }
- }
- private void merge(Comparable[] a, int lo, int mid, int hi) {
- for (int i = lo; i <= hi; i ) {
- aux[i] = a[i];
- }
- int i = lo, j = mid 1;
- for (int k = lo; k <= hi; k ) {
- if (i > mid) {
- a[k] = aux[j ];
- } else if (j > hi) {
- a[k] = aux[i ];
- } else if (less(aux[i], aux[j])) {
- a[k] = aux[i ];
- } else {
- a[k] = aux[j ];
- }
- }
- }
- }