一、什么是自底向上的归并排序?算法
说到底,无论是前面说的自顶向下的归并排序仍是如今讲的自底向上的归并排序,其实质都是归并。编程
来看看一个演示过程:数组
这个就是待排序的数组序列性能
先将数组序列以2个元素为一组分红4组,每一个组内部分红2个子序列进行向上合并测试
这是合并以后的效果优化
而后以4个元素为一组分红2组,每一个组内部分红2个子序列进行向上合并spa
这是合并以后的效果code
而后以8个元素为一组分红1个组,每一个组内部分红2个子序列进行向上合并blog
最终整个序列编程有序的了排序
其实从这里看就能够知道,这个就好像是前面说的自顶向下排序过程当中的后面一个过程。
二、时间复杂度
同自顶向下的归并排序相同,时间复杂度也是O(nlogn)级别。
三、算法的实现(基于C++)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
1 /***************************** 自底向上的归并排序算法实现 ***********************************/ 2 template<typename T> 3 void mergeSortBU (T arr[], int count) 4 { 5 for (int size = 1; size <= count; size += size) { // 外层循环把整个序列分红多个子序列,size表示一个子序列的元素个数,每一次循环以翻倍的形式增长 6 for (int i = 0; i + size < count; i += size + size) { // 内层循环遍历全部子序列,以两个子序列为一组向上归并 7 __merge<T>(arr, i, i + size - 1, MIN(i + size + size - 1, count - 1)); // 对两部分数据进行归并操做 8 } 9 } 10 } 11 /*******************************************************************************************/
四、性能测试(与通过优化过的自顶向下归并排序算法相比较)
测试数据量50000:
测试数据量100000:
五、算法优化
其实跟自顶向下归并排序的优化算法是同样的
1 /***************************** 自底向上的归并排序算法实现 ***********************************/ 2 template<typename T> 3 void mergeSortBU (T arr[], int count) 4 { 5 for (int size = 1; size <= count; size += size) { // 外层循环把整个序列分红多个子序列,size表示一个子序列的元素个数,每一次循环以翻倍的形式增长 6 for (int i = 0; i + size < count; i += size + size) { // 内层循环遍历全部子序列,以两个子序列为一组向上归并 7 if (MIN(i + size + size - 1, count - 1) - i < 40) { // 优化措施2 8 __insertSortMG<T>(arr, i, MIN(i + size + size - 1, count - 1)); 9 continue; 10 } 11 12 if (arr[i + size - 1] > arr[i + size]) { // 优化措施1 13 __merge<T>(arr, i, i + size - 1, MIN(i + size + size - 1, count - 1)); // 对两部分数据进行归并操做 14 } 15 } 16 } 17 } 18 /*******************************************************************************************/
优化事后的性能测试:
测试数据量50000:
测试数据量100000:
总结: 从上面的数据能够看出来,通过优化以后,自底向上归并排序的性能获得了一个很大的提高,
可是仍是比自顶向下归并排序慢,这个实际上是有缘由的,在这里不作分析。
还有一个值得一提的就是未通过优化的算法的代码可知,代码中没有使用数组的特性(使用索引找
到对应的元素),因此咱们能够用自底向上归并排序对一个链表进行排序。