当前位置: 首页 > news >正文

高级排序算法之归并排序

算法分析

归并排序算法的时间复杂度能达到nlog(n)。

归并排序算法的基本思想:归并排序算法是把数据逐次分割成每块,对每块进行排序后,然后再进行合并成为一个排好序的数据。

第一步:数据平均分割

第二步:再次对数据进行平均分割,直到数据无法再分割,也就是每份数据只有一个了,然后再对每份数据进行合并,依次向上进行合并每份有序的数据。

根据以上算法的基本思想,相信大家也想到了,归并排序使用递归实现起来相对更加简单。以上所说的归并排序为自顶向下的归并排序算法,还有一种自底向上的归并排序算法实现下边再说。

自顶向下归并排序

以下是自顶向下的归并排序算法的实现示例:

template<typename T>
void __merge(T arr[], int l, int mid, int r)
{
    //int aux[r - l + 1];  //数据量达到千万时,申请数组程序崩溃
    int *aux = new int[r-l+1];

    for(int i = l; i <= r; i++)
        aux[i - l] = arr[i];

    int i = l, j = mid +1;
    for(int k= l; k <= r; k++)
    {
        if(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++;
        }
    }	
    delete []aux;
}

template<typename T>
void __mergeSort(T arr[], int l, int r)
{
    if(r - l <= 15)     //优化点2:对小数据量使用插入排序
    {
        insertionSort(arr, l, r);
        return ;
    } 

    int mid = (l + r)/2;

    __mergeSort(arr, l, mid);
    __mergeSort(arr, mid + 1, r);
    
    if(arr[mid] > arr[mid+1])     //优化点1:对于arr[mid] <= arr[mid+1]的情况不需要进行merge
        __merge(arr, l, mid, r);
}

//此为自顶向下的归并排序算法
template<typename T>
void mergeSort(T arr[], int n)
{
    __mergeSort(arr, 0, n - 1);
}

  

自底向上归并排序

自底向上的归并排序算法与自顶向下的归并排序正好相反,先指定一个步长,把数据按步长分割,每份数据使用插入排序算法(插入排序对小数据量性能好,插入排序参考博文)

示例代码:

template<typename T>
void insertionSort(T arr[], int l, int r)
{
	for(int i = l+1; i <= r; i++)
	{
		T tmp = arr[i];
		int j;
		for(j = i; j > l && arr[j - 1] > tmp; j --)
			arr[j] = arr[j - 1];

		arr[j] = tmp;
	}
}

 

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

总结

归并排序算法的时间复杂度为nlog(n),相对与时间复杂度为O(n^2)的选择排序、插入排序、冒泡排序等基础排序算法更好,但在小数据量或者几乎有序的数据中,时间复杂度为O(n^2)的插入排序与nlog(n)的归并排序相差无几。

 

转载于:https://www.cnblogs.com/baihl/p/10665960.html

相关文章:

  • C#winform程序安装时自动卸载新版本覆盖旧版本
  • 第二次实验报告
  • 数据库原理 知识点总结
  • Express初识
  • MyBatis Dynamic SQL 1.1.1 发布,生成动态 SQL 的框架
  • 21个值得收藏的Javascript技巧
  • 43. Multiply Strings字符串相乘
  • displayport-2
  • 他山之石——运维平台哪家强?
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • String Boot中@Controller和@RestController的区别?
  • 加入lib
  • form 表单中input 使用disable属性
  • Android 设置按钮为透明
  • 订餐小程序新获利使商家摆脱第三方平台束缚
  • Angular Elements 及其运作原理
  • exports和module.exports
  • JavaScript函数式编程(一)
  • Java多线程(4):使用线程池执行定时任务
  • Map集合、散列表、红黑树介绍
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • PHP 的 SAPI 是个什么东西
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • 包装类对象
  • 前端路由实现-history
  • 前端之Sass/Scss实战笔记
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 译有关态射的一切
  • 译自由幺半群
  • Semaphore
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • # include “ “ 和 # include < >两者的区别
  • #ifdef 的技巧用法
  • #Ubuntu(修改root信息)
  • #WEB前端(HTML属性)
  • (145)光线追踪距离场柔和阴影
  • (175)FPGA门控时钟技术
  • (3)llvm ir转换过程
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (三)mysql_MYSQL(三)
  • (十一)c52学习之旅-动态数码管
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (原)本想说脏话,奈何已放下
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)甲方乙方——赵民谈找工作
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转载)深入super,看Python如何解决钻石继承难题
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .gitattributes 文件
  • .net framework4与其client profile版本的区别
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项