归并排序算法分为自顶向下和自底向上实现的,自顶向下实现归并排序就是用二分法将一个完整的数组逐级划分,然后逐级归并,一般采用递归算法实现,正如之前给出的归并排序算法;而自底向上的归并排序就是将数组中的每个元素看成是一个个有序子序列,然后两两归并,形成新的有序序列,接着再两两归并,直到得到一个完整的有序序列为止,如下图所示:

自底向上的归并排序算法只需要用循环迭代就可以实现,具体C++实现代码如下:

SortTestHelper.h文件(辅助函数):

#include <iostream>
#include <cstdlib>
#include <ctime>  //clock()、CLOCKS_PER_SEC
#include <cassert>  //包含函数assert()using namespace std;namespace SortTestHelper
{//辅助函数 - 随机产生一个数组int* generateRandomArray(int n, int RangeL, int RangeR)  //返回数组首地址{//判断RangeL是否<=RangeRassert(RangeL <= RangeR);  //参数为表达式,表达式为真时返回true,否则打印错误信息int *arr = new int[n];srand(time(0));for(int i = 0; i < n ; i++){arr[i] = rand() % (RangeR - RangeL + 1) + RangeL;  //使得产生的随机数在RangeL和RangeR之间}return arr;}//辅助函数 - 产生一个近乎有序的随机数组int* generateNearlyOrderedArray(int n, int swapTime){int *arr = new int[n];for(int i = 0; i < n; i++){arr[i] = i;  //先生成一个完全有序的数组}//然后交换几组元素,使之变成无序但近乎有序的数组srand(time(0));for(int j = 0; j < swapTime; j++){//随机生成一个x位置和y位置int posx = rand() % n;int posy = rand() % n;//交换x和y处的元素swap(arr[posx], arr[posy]);}return arr;}//辅助数组 - 产生一个完全有序数组int* generateTotallyOrderedArray(int n){int *arr = new int[n];for(int i = 0; i < n; i++){arr[i] = i;}return arr;}//辅助函数 - 打印数组template<typename T>void printArray(T arr[], int n){for(int i = 0; i < n; i++){cout << arr[i] << " ";}cout << endl;}//辅助函数 - 判断数组是否有序(升序)template<typename T>bool isSorted(T arr[], int n){for(int i = 0; i < n - 1; i++){if(arr[i] > arr[i + 1]){return false;}}return true;}//辅助函数 - 测试算法的时间template<typename T>void testSort(string sortname, void(*sort)(T[], int), T arr[], int n)  //arr[]和n是函数指针需要的参数{clock_t starttime = clock();sort(arr, n);  //调用函数sort()clock_t endtime = clock();//判断排序是否成功assert(isSorted(arr, n));  //若是数组无序,则assert会自动调用abort()退出程序,不会执行下面的语句cout << sortname << " needs " << double(endtime - starttime) / CLOCKS_PER_SEC << "s." << endl;}//辅助函数 - 拷贝数组int* copyIntArray(int a[], int n){int *arr = new int[n];//使用C++函数copy()copy(a, a + n, arr);return arr;}
}

main.cpp文件:

#include<iostream>
#include "SortTestHelper.h"
//自底向上的归并排序算法
template<typename T>
void mergeSortBU(T arr[], int n)
{for(int sz = 1; sz <= n; sz += sz){for(int i = 0; i < n; i += sz + sz){//将arr[i...i+sz-1]和arr[i+sz...i+sz+sz-1]进行归并if(i + sz + sz - 1 < n)  //则i+sz-1和i+sz+sz-1都没有越界{__merge(arr, i, i + sz - 1, i + sz + sz -1);}else if(i + sz - 1 < n){__merge(arr, i, i + sz - 1, n - 1);}else{break;}}}
}int main()
{int n = 500000;int *arr = SortTestHelper::generateRandomArray(n, 0, n);SortTestHelper::testSort("mergeSortBU", mergeSortBU, arr, n);delete[] arr;return 0;
}

在main.cpp文件中,自底向上的递归算法中,在调用__merge(arr, i, i+sz-1, i+2*sz-1) 将arr[i...i+sz-1]和arr[i+sz...i+2*sz-1]进行归并时,需要考虑数组下标出界的问题,有2个下标需要考虑出界:i+sz-1和i+2*sz-1,可以加上述归并算法简化如下:

//自底向上的归并排序算法
template<typename T>
void mergeSortBU(T arr[], int n)
{for(int sz = 1; sz <= n; sz += sz){for(int i = 0; i + sz < n; i += sz + sz){__merge(arr, i, i + sz - 1, min(i + 2 * sz - 1, n - 1));}}
}

即当mid = i + sz - 1未出界时,调用__merge()函数进行归并,若mid出界,则跳出内层循环,进入下一趟归并。

可以测试自顶向下的归并算法和自底向上的归并算法的时间性能,发现两者相差不大,但是从自底向上的归并排序代码中可以看出,无需使用数组下标访问数组中的元素,这保证了自底向上的归并排序算法可以很好的使用时间复杂度为O(nlogn)对链表进行排序(因为数组可以通过中括号和下标随机访问数组元素,时间复杂度为O(1),这不会影响整个排序的时间复杂度,但是单链表不能通过这种方式随机访问单个元素,其访问元素的时间复杂度为O(n),由于自底向上的归并算法中没有涉及到访问单个元素,因此对于链表也能很好的实现时间复杂度为O(nlogn)的归并排序)。

自底向上的归并排序算法相关推荐

  1. java归并算法实例_Java编程中实现归并排序算法的实例教程

    算法概述/思路归并排序是基于一种被称为"分治"(divide and conquer)的策略.其基本思路是这样的: 1.对于两个有序的数组,要将其合并为一个有序数组,我们可以很容易 ...

  2. 第十五周 项目三 归并排序算法的改进

    /* * Copyright (c)2017,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名称:项目3.cpp * 作 者:孙仁圆 * 完成日期:2017年12 ...

  3. 自顶向下与自底向上的归并排序

    自顶向下的归并排序 在本节中我们所讨论的算法都基于归并排序这个简单的操作,即将两个有序的数组归并排序成一个有序数组.很快人们就根据这个操作发明了一种简单的归并算法.要将一个数组排序,可以先将它分成两半 ...

  4. 2路归并排序算法(C语言)

    转载自:http://blog.csdn.net/caryaliu/article/details/7475700 将两个按值有序序列合并成一个按值有序序列,则称之为二路归并排序,下面有自底向上和自顶 ...

  5. 【java排序】 归并排序算法、堆排序算法

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  6. JavaScript实现MergeSort归并排序算法(附完整源码)

    JavaScript实现MergeSort归并排序算法(附完整源码) Comparator.js完整源代码 Sort.js完整源代码 MergeSort.js完整源代码 Comparator.js完整 ...

  7. C语言merge sort归并排序算法(附完整源码)

    C语言merge sort归并排序算法 merge sort归并排序算法的完整源码(定义,实现) merge sort归并排序算法的完整源码(定义,实现) #ifndef MERGE_SORT_H # ...

  8. python 归并排序算法_python基本算法之实现归并排序(Merge sort)

    0.前言 评判一个算法的好坏的标准: 时间复杂度 空间复杂度 1.归并排序算法是什么? 冒泡排序(Bubble Sort)是一种建立在归并操作上面的一种有效的排序算法,由John von neuman ...

  9. 排序算法:归并排序算法实现及分析

    归并排序算法介绍 归并排序(Merging Sort)就是利用归并的思想实现排序的放.它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个 ...

  10. 算法竞赛——归并排序算法

    算法竞赛--归并排序算法 分治法 划分问题:把序列分成元素个数尽量相等的两半 递归求解:把两半元素分别排序 合并问题:把两个有序表合并成一个 借鉴RuJia的精妙的合并过程 void merges2( ...

最新文章

  1. C#中Dispose和Close的区别
  2. CV之Hog+HamMingDistance:基于Hog提取和汉明距离对比的应用—图像相似度对比之for循环将多个成对图片依次对比并输出相似度
  3. Java 接口 新特性(Java8)
  4. MATLAB安装第三方工具箱
  5. 计算机控制系统笔记,笔记型计算机的电源控制系统
  6. WVI职业价值观测量表
  7. 服务器获取真实客户端 IP [ X-Forwarded-For ]
  8. 【从零开始学架构-李运华】04|复杂度来源:高性能
  9. 数字图像处理100问—27 双三次插值( Bicubic Interpolation )
  10. 网络邻居没有查看工作组计算机,解决Windows 10 系统看不到网上邻居工作组里的其他计算机-win7网上邻居...
  11. 浅谈ACL在校园网中的应用
  12. 互联网络彻底瘫痪的可能性研究
  13. 聚焦云+人工智能,纳德拉宣布微软重大重组
  14. 新蓝海之门,或将由数据信托来打开!
  15. OpenFOAM动态加密网格的负载平衡
  16. 阿里在线免费图标库的使用
  17. 香港中文大学推荐的书单~
  18. xp系统什么梗_电脑分区4K对齐,对系统的影响
  19. 教你如何快速分清云平台与云管平台的区别?
  20. echarts数据可视化项目经验积累

热门文章

  1. Python压缩解压–gzip
  2. ug建模和草图切换_从草图到XD,为什么我要切换
  3. C++ STL库(6)
  4. Java中的方法重载(overload)
  5. NCI和CNC应用中M代码的概念和功能
  6. ubuntu16.04查看opencv版本
  7. 计算机毕业设计PHP图书馆图书借阅管理系统
  8. arcgis软件环境安装
  9. 怎么把pdf用abobe转换成html,Adobe Acrobat:把网页转换为PDF
  10. python 贴吧小爬虫案例