二路归并排序的基本思想

设数组a中存放了n个数据元素,初始时把它们看成是n个长度为1的有序子数组,然后从第一个有序子数组开始,把相邻的有序子数组两两合并,得到[n/2]个长度为2的新的有序子数组(当n为奇数时,最后一个新的有序子数组的长度为1)。对这些新的有序子数组再进行两两归并。如此重复,直到得到一个长度为n的有序数组为止。

一次二路归并排序算法的目标是把若干个长度为k的相邻有序子数组从前、向后进行两两归并,得到个数减半的长度为2k的相邻有序子数组。算法设计中要考虑的一个问题是:若元素个数为2k的整数倍,则两两归并正好完成n个数据元素的一次二路归并;若元素个数不为2k的整数倍,则当归并到最后一组时,剩余的元素个数会不足2k个,这时的处理方法是:
① 若剩余的元素个数大于k而小于2k,则把前k个元素作为一个子数组,把剩余的元素作为最后一个子数组。
② 若剩余的元素个数小于k时,也即剩余的元素个数只够一组时,则不用再进行两两归并排序。

一次二路归并

void Merge(DataType a[], int n, DataType swap[], int k){//一次二路归并排序后的有序子序列存于数组swap中,k为有序子数组的长度int m = 0, u1, u2, l2, i, j;int l1 = 0;//第一个有序子数组的下界为0;while(l1+k <=n-1){l2 = l1+k;//计算第二个有序数组的下界 u1 = l2-1;//计算第一个有序数组的上界u2 = (l2+k-1 <=n-1) ? l2+k-1:n-1;//计算第二个有序数组上界for(i=l1,j=l2;i<u1&&j<=u2;m++){//两个有序子数组合并if(a[i].key<=a[j].key){swap[m] = a[i];i++;}else{swap[m] = a[j];j++;}} while(i<=u1){//子数组2已经归并完,将子数组1中剩余的元素存放到数组swap中 swap[m] = a[i];m++;i++; }while(j<=u2){//子数组1已经归并完,将子数组2中剩余的元素存放到数组swap中 swap[m] = a[j];m++;j++; }l1 = u2+1;} for(i=l1;i<n;i++,m++){//将原始数组中只够一组的数据元素顺序存放到数组swap中 swap[m] = a[i];}
}

二路归并排序

void MergeSort(DataType a[], int n){int i, k=1;//归并长度从1开始DataType *swap;swap = (DataType *)malloc(sizeof(DataType)*n);//申请动态数组空间while(k<n){Merge(a,n,swap,k);//调用归并函数for(i=0;i<n;i++){a[i] = swap[i];//将元素从临时数组swap放回数组a中 } k = 2*k;//归并长度加倍 } free(swap);//释放动态数组空间 }

测试代码

#include <stdio.h>
#include <stdlib.h>typedef int KeyType; typedef struct{KeyType key;
}DataType;void Merge(DataType a[], int n, DataType swap[], int k){//一次二路归并排序后的有序子序列存于数组swap中,k为有序子数组的长度int m = 0, u1, u2, l2, i, j;int l1 = 0;//第一个有序子数组的下界为0;while(l1+k <=n-1){l2 = l1+k;//计算第二个有序数组的下界 u1 = l2-1;//计算第一个有序数组的上界u2 = (l2+k <=n-1) ? l2+k-1:n-1;//计算第二个有序数组上界for(i=l1,j=l2;i<u1&&j<=u2;m++){//两个有序子数组合并if(a[i].key<=a[j].key){swap[m] = a[i];i++;}else{swap[m] = a[j];j++;}} while(i<=u1){//子数组2已经归并完,将子数组1中剩余的元素存放到数组swap中 swap[m] = a[i];m++;i++; }while(j<=u2){//子数组1已经归并完,将子数组2中剩余的元素存放到数组swap中 swap[m] = a[j];m++;j++; }l1 = u2+1;} for(i=l1;i<n;i++,m++){//将原始数组中只够一组的数据元素顺序存放到数组swap中 swap[m] = a[i];}
}void MergeSort(DataType a[], int n){int i, k=1;//归并长度从1开始DataType *swap;swap = (DataType *)malloc(sizeof(DataType)*n);//申请动态数组空间while(k<n){Merge(a,n,swap,k);//调用归并函数for(i=0;i<n;i++){a[i] = swap[i];//将元素从临时数组swap放回数组a中 } k = 2*k;//归并长度加倍 } free(swap);//释放动态数组空间 } void main(void){int i=0;DataType array[9]={72,73,71,23,94,16,5,68,64};DataType array2[9]; printf("原数组顺序:");for(i=0;i<9;i++){printf("%d ",array[i]);}printf("\n\n");MergeSort(array,9);printf("二路归并排序之后结果:");for(i=0;i<9;i++){printf("%d ",array[i]);} getch(0);
}


上图所示是二路归并排序算法各次归并排序过程的一个示例。

复杂度分析

对n个元素进行一次二路归并排序时,归并的次数约为lbn,任何一次的二路归并排序元素的比较次数都约为n-1,所以,二路归并排序算法的时间复杂度为O(nlbn)。

二路归并排序时使用了n个临时内存单元存放数据元素,所以,二路归并排序算法的空间复杂度为O(n)。

由于二路归并排序算法是相邻有序子表两两归并,对于关键字相同的数据元素,能够保证原来在前边的元素排序后仍在前边,因此,二路归并排序算法是一种稳定的排序算法。

前边讨论过的几个时间复杂度为O(nlbn)的排序算法都是不稳定的排序算法,而二路归并排序算法不仅时间复杂度是O(nlbn),而且还是一种稳定的排序算法。这是二路归并排序算法的最大特点。

数据结构----二路归并排序相关推荐

  1. 数据结构——二路归并排序和基数排序

    二路归并排序 算法原理 假设该数组为q,左边界为 l,右边界为 r,并设置临时数组tmp. 采用分治思想: 第一步:确定分界点: mid = l + r >>1. 第二步:递归划分左右两段 ...

  2. 数据结构——二路归并排序

    归并排序就是将两个或两个以上的有序表合并成一个有序表的过程,其中将两个有序表合并成一个有序表的过程称为"2-路归并". 排序过程 将目标序列一分为二,再讲子序列再次一分为二,直到子 ...

  3. 数据结构源码笔记(C语言):二路归并排序

    //实现二路归并排序算法#include<stdio.h> #include<malloc.h> #define MAXE 20 //线性表中最多元素个数typedef int ...

  4. C++实现二路归并排序算法

    排序算法分为五大类,一共是有九种,如下: 插入类:直接插入排序.折半插入排序.希尔排序 交换类:冒泡排序.快速排序 选择类:简单选择排序.堆排序 归并类:二路归并排序 基数类:多关键字排序 九种算法的 ...

  5. 二路归并排序原理及JAVA实现

    归并类排序 基本思想:首先将原始无序序列划分为两个子序列,然后分别对每个子序列递归地进行排序,最后再将有序子序列合并. 归并排序基于分治策略思想.前面提到的基于分治的快速排序重在"分&quo ...

  6. 二路归并排序及时间复杂度分析

    序言 二路归并排序是一种效率极高的递归排序,将数组A化为有序数组时间复杂度为O(nlogn). 思想 二路归并排序分为拆分数组以及合并两个操作. 切分(自上而下)时间复杂度2*T(n/2) 每次从数组 ...

  7. 二路归并排序简介及其并行化

    1.归并排序简介 1.1算法思想 归并排序属于比较类非线性时间排序,比较类排序中性能最佳,应用较为广泛. 归并排序是分治法(Divide and Conquer)的一个典型的应用.将已有序的子序列合并 ...

  8. 二路归并排序Python实现-III

    二路归并排序Python实现-III 归并排序 是一种 效率比较高并且稳定的算法.时间复杂度 O(NLog(N)),空间复杂度 O(N). 归并排序(Merge Sort)是建立在归并操作上的一种有效 ...

  9. Sort List(二路归并排序)

    题目链接:https://leetcode.com/problems/sort-list/description/ 题目要求:对链表进行排序,时间复杂度O(n),常数的空间复杂度 两种解法,本质上都是 ...

  10. 二路归并排序 Implemented With C++

    文章目录 Definition Implementation Performance Definition 对于一个长度为 n n n 的表,我们可以把这张表看成是由 n n n 个长度为 1 1 1 ...

最新文章

  1. MQTT客户端工具MQTTfx
  2. Linux进程和计划任务管理
  3. ASP.NET+SQL创建存储过程
  4. 文件服务器存储,文件服务器存储
  5. 日期时间格式之间的相互转换
  6. django-路由-通过正则表达式来捕获路径-对应视图函数
  7. 即使到了 2020 年,编程语言之争仍未休!
  8. 关于在平台中设置系统全局变量的使用和场景
  9. pandas中replace的用法
  10. Mootools 1.4 官方网站的API使用说明存在错误
  11. vue获取豆瓣图片资源,数据接口正常,图片无法显示,按右键能正常显示
  12. XML语言的基本语法-Java Web
  13. python程序员工资高吗?
  14. 《那些年啊,那些事——一个程序员的奋斗史》——77
  15. 正则表达式 压缩 HTML 字符串
  16. ios设备备份,更新路径(mac os)
  17. Java-多人聊天小程序
  18. 项目开发流程(简述)
  19. ai怎样导出所选部分,AI 怎么导出部分文件
  20. GPU显存 - 深度学习中 GPU 和显存分析

热门文章

  1. IDEA中快速创建jsp页面模板
  2. winsdk仿win7扫雷
  3. 基于springboot的薪资管理系统设计
  4. 校对双层PDF中的隐藏文本
  5. 2021考研数学二汤家凤接力题典1800【题目册】
  6. 使用ffmpeg解析mp4文件得到音频和视频数据
  7. 华为的人才体系:任正非这样管理19万员工
  8. 王鉴老师--沪师经纪-刘建
  9. SGD(随机梯度下降算法)的缺点
  10. 类似京东商城筛选模块