排序算法——归并排序(二路归并)
时间:2019-02-16
本文章向大家介绍排序算法——归并排序(二路归并),主要包括排序算法——归并排序(二路归并)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
二路归并的基本思想:将含有n个记录的原始序列看做n个长度1的子序列。从第一个子序列开始,将相邻的两个子序列合并,得到长度为2或1(最后只剩下1个子序列的情况)的子序列。如此重复成对归并,直到序列的长度等于原始序列的长度时为止。
基本过程:两个有序序列的合并。
排序过程如下图:
C++代码:
//一次二路归并过程
//对序列a[0]...a[length-1]进行一次二路归并排序,每个子序列的长度为size
void Merge(int a[], int swap[], int size, int length) {
int i, j;
int begin1, end1, begin2, end2;//分别表示两个子序列的首尾下标
int sp;//表示已经归并的元素个数
begin1 = 0;//第一个子序列的起始下标
sp = 0;
while (begin1 + size <= length - 1) { //测试是否存在两个可以合并的子序列
begin2 = begin1 + size; //第二个子序列的起始下标
end1 = begin2 - 1; //第一个子序列的结束下标
if (begin2 + size > length) {
end2 = length - 1; //第二个子序列的结束下标(第二个子序列长度不足size)
}
else {
end2 = begin2 + size - 1;
}
//下面合并两个子序列
for (i = begin1, j = begin2; i <= end1&&j <= end2;) { //注意是小于等于
if (a[i] <= a[j]) {
swap[sp++] = a[i++];
}
else {
swap[sp++] = a[j++];
}
}
//其中某一个子序列已经全部归并
while (i <= end1) {//第一个子序列还有剩余
swap[sp++] = a[i++];
}
while (j <= end2) {//第二个子序列还有剩余
swap[sp++] = a[j++];
}
begin1 = end2 + 1;//改变子序列开头以开启下一对序列的合并
}
//将原始序列中无法配对的子序列(最后落单的序列)放入结果序列中
for (i = begin1; i < length;) {
swap[sp++] = a[i++];
}
}
int * MergeSort(int a[], int length) {
int *result = new int[length];//存储归并结果
int size = 1;//记录子序列的大小
while (size < length) {//合并到子序列长度等于原始序列长度时为止
Merge(a,result,size,length); //归并的结果存于result
size = size * 2;
Merge(result, a, size, length);//归并的结果存于a
size = size * 2;
}
return a;
}
n个记录进行二次归并时,归并的次数为log_2n,每次归并过程中,记录的比较次数不超过n次。所以二次归并的时间复杂度为Ο(nlog_2n),空间复杂度为Ο(n)。二路归并排序是稳定的排序,这是它相对于快速排序的最大优点。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android 在子线程中更新UI的几种方法示例
- WebView设置WebViewClient的方法
- Android星级评分条的实现代码
- Android模仿美团顶部的滑动菜单实例代码
- android实现按钮获取焦点延迟加载
- Devtools 老师傅养成[1] - Chrome Devtools介绍
- Android4.4开发之电池低电量告警提示原理与实现方法分析
- 浅谈android性能优化之启动过程(冷启动和热启动)
- Android拖动条的实现代码
- Devtools 老师傅养成[3] - Console 面板
- Android开发中数据库升级且表添加新列的方法
- Android冷启动实现app秒开的实现代码
- Devtools 老师傅养成[4] - Sources 面板
- android中使用Html渲染的方式实现必填项前面的*号示例
- android视频播放简单实现示例(VideoView&MediaPlayer)