归并排序及优化

归并排序

归并排序及优化
首先把数组分成一半,想办法把左右两边数组排序,之后呢再将它们归并起来,这就是归并排序的基本思想。

这样的话如果有N个元素,就会分成log(n)层,如果整个归并过程我们可以以O(n)时间复杂度解决的话,那么我们就设计成了一个 Nlog(n)级别的排序算法。

归并排序及优化
归并排序及优化
归并排序及优化
归并排序及优化
这个归并的过程需要O(n)的辅助空间,把两个已经排好序的数组合并成一个排序数组,整体呢需要三个索引在数组中追踪,其中蓝色的箭头表示最终在归并的过程中我们需要跟踪的位置,而俩个红色的箭头表示当前已经排好序的数组,分别指向当前要考虑的元素。

首先我们要看1和2谁先放在最终数组中,显然1比2小所以我们首先把1放在最终数组中,这样蓝色箭头就可以考虑下一元素应该放谁,与此同时,下面红色箭头1所在数组也可以考虑下一元素了,此时1这个元素就最终有序了,然后我们就可以考虑2和4谁放入最终数组,显然是2,以此类推。

归并排序及优化
归并排序及优化
归并排序及优化
归并排序及优化

对于这些索引位置定义

归并排序及优化

优化

  • 对于arr[mid]

mergeSort

// 对arr[l...r]范围的数组进行插入排序
template
void insertionSort(T arr[], int l, int r) {
   for (int i = l + 1; i  l && arr[j - 1] > e; j--) {
           arr[j] = arr[j - 1];
       }
       arr[j] = e;
   }
}

// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
template
void __merge(T arr[], const int l, const int mid, const int r) {
   T aux[r - l + 1];
   for (int i = l; i  mid) {  // 如果左半部分元素已经全部处理完毕
           arr[k] = aux[j - l];
           ++j;
       } else if (j > r) {  // 如果右半部分元素已经全部处理完毕
           arr[k] = aux[i - l];
           ++i;
       } else if (aux[i - l] < aux[j - l]) {  // 左半部分所指元素 < 右半部分所指元素
           arr[k] = aux[i - l];
           ++i;
       } else {  // 左半部分所指元素 >= 右半部分所指元素
           arr[k] = aux[j - l];
           ++j;
       }
   }
}

// 递归使用归并排序,对arr[l...r]的范围进行排序
template
void __mergeSort(T arr[], const int l, const int r) {
   /*if (l >= r) {
       return;
   }*/
   // 优化2: 对于小规模数组近乎有序的概率比较大, 使用插入排序有优势
   if (r - l  arr[mid + 1]) {
       __merge(arr, l, mid, r);
   }
}

//归并排序
template
void mergeSort(T arr[], const int n) {
   __mergeSort(arr, 0, n - 1);
}

自底向上归并排序

使用自底向上的归并排序算法 Merge Sort BU 也是一个O(nlogn)复杂度的算法,虽然只使用两重for循环,但是,Merge Sort BU也可以在1秒之内轻松处理100万数量级的数据,需要注意的是:不要轻易根据循环层数来判断算法的复杂度,Merge Sort BU就是一个反例。

比较Merge Sort和Merge Sort Bottom Up两种排序算法的性能效率,整体而言, 两种算法的效率是差不多的。但是如果进行仔细测试,从统计意义上来讲自顶向下的归并排序会略胜一筹。不过Merge Sort Bottom Up 有一个非常重要的作用,这个代码中没有使用数组的索引获取元素特性,就因如此可以非常好的在nlog(n)的时间对链表这样的数据结构进行排序。

template
void mergeSortBU(T arr[], const int n) {
    // Merge Sort Bottom Up 优化
    // 对于小数组, 使用插入排序优化
    for (int i = 0; i < n; i += 16) {
        insertionSort(arr, i, std::min(i + 15, n - 1));
    }
    for (int sz = 16; sz < n; sz += sz) {
        for (int i = 0; i < n - sz; i += sz + sz) {
            // 对于arr[mid]  arr[i + sz]) {
                __merge(arr, i, i + sz - 1, std::min(i + sz + sz - 1, n - 1));
            }
        }
    }
}

概述

归并排序及优化
归并排序及优化

Original: https://www.cnblogs.com/chengmf/p/16493760.html
Author: 放飞梦想C
Title: 归并排序及优化

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/588190/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球