内部排序->归并排序->2-路归并排序
文字描述
假设初始序列有n个记录,则可看成是n个有序的字序列,每个字序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,…, 如此重复,直到得到一个长度为n的有序序列为止,这种排序方法称为2-路归并排序。
示意图

算法分析
2-路归并排序的时间复杂度为nlogn;
2-路归并排序需要至少同待排序序列同等大小的辅助空间;
与快速排序和堆排序相比,归并排序最大特点就是,它是一种稳定的排序方法。
在一般情况下,2-路归并排序,尤其是递归形式的,很少在内部排序中使用,一般用于外部排序,因为反复的自身函数的调用,容易引起栈溢出。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
* double log2(double x); 以2为底的对数
* double ceil(double x); 取上整
* double floor(double x); 取下整
* double fabs(double x); 取绝对值
*/ #define DEBUG #define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b)) //定义顺序表中结点个数的最大值
#define MAXSIZE 100
//定义无穷大INF的值
#define INF 1000000 //定义结点中的关键字类型为int
typedef int KeyType;
//定义结点中除关键字外的附件信息为int
typedef char InfoType; //待排序的结点的结构体
typedef struct{
//结点中的关键字
KeyType key;
//结点中的除关键字外的附加信息
InfoType otherinfo;
}RedType; //顺序表的结构体
typedef struct{
//顺序表中待排序的结点
RedType r[MAXSIZE+];
//顺序表中待排序的结点个数
int length;
}SqList; //依次打印顺序表中结点的信息
void PrintList(SqList L){
int i = ;
printf("下标值:");
for(i=; i<=L.length; i++){
printf("[%d] ", i);
}
printf("\n关键字:");
for(i=; i<=L.length; i++){
if(EQ(L.r[i].key, INF)){
printf(" %-3c", '-');
}else{
printf(" %-3d", L.r[i].key);
}
}
printf("\n其他值:");
for(i=; i<=L.length; i++){
printf(" %-3c", L.r[i].otherinfo);
}
printf("\n\n");
return ;
} //将有序的SR[i,...,m]和SR[m+1,...,n]归并为有序的TR[i,...,n]
void Merge(RedType SR[], RedType TR[], int i, int m, int n)
{
int j = , k =;
//将SR中记录由小到大地归并到TR
for(j=m+, k=i; i<=m && j<=n; ++k){
if(LQ(SR[i].key, SR[j].key)){
TR[k] = SR[i++];
}else{
TR[k] = SR[j++];
}
}
//将剩余的SR[i,...,m]复制到TR
for(; i<=m; i++){
TR[k++] = SR[i];
}
//将剩余的SR[j,...,n]复制到TR
for(; j<=n; j++){
TR[k++] = SR[j];
}
} //将SR[s,...,t]归并排序为TR1[s,...,t]
void MSort(RedType SR[], RedType TR1[], int s, int t)
{
if(s == t){
TR1[s] = SR[s];
}else{
//将SR[s,...,t]平分为SR[s,...,m]和SR[m+1,...,t]
int m = (s+t)/;
RedType TR2[MAXSIZE+];
//递归地将SR[s,...,m]归并为有序的TR2[s,...,m]
MSort(SR, TR2, s, m);
//递归地将SR[m+1,...,t]归并为有序的TR2[m+1,...,t]
MSort(SR, TR2, m+, t);
//将TR2[s,...,m]和TR2[m+1,...,t]归并到TR1[s,...,t]
Merge(TR2, TR1, s, m, t);
}
} //对顺序表L作2-路归并排序
void MergeSort(SqList *L)
{
MSort(L->r, L->r, , L->length);
#ifdef DEBUG
printf("对该数据作2-路归并排序后:\n");
PrintList(*L);
#endif
} int main(int argc, char *argv[])
{
if(argc < ){
return -;
}
SqList L;
int i = ;
for(i=; i<argc; i++){
if(i>MAXSIZE)
break;
L.r[i].key = atoi(argv[i]);
L.r[i].otherinfo = 'a'+i-;
}
L.length = (i-);
L.r[].key = ;
L.r[].otherinfo = '';
printf("输入数据:\n");
PrintList(L);
//对顺序表L最2-路归并排序
MergeSort(&L);
return ;
}
2-路归并排序
运行

内部排序->归并排序->2-路归并排序的更多相关文章
- 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)
解题思路: 排序方法:多路归并排序 每次将n个list的头元素取出来,进行排序(堆排序),最小元素从堆中取出后,将其所在list的下一个元素 放入堆中,调整堆序列. 函数实现原型: void list ...
- 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较
2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...
- 9, java数据结构和算法: 直接插入排序, 希尔排序, 简单选择排序, 堆排序, 冒泡排序,快速排序, 归并排序, 基数排序的分析和代码实现
内部排序: 就是使用内存空间来排序 外部排序: 就是数据量很大,需要借助外部存储(文件)来排序. 直接上代码: package com.lvcai; public class Sort { publi ...
- C++:探究纯虚析构函数以及实现数组的高速排序与链表的归并排序
C++:探究纯虚析构函数以及实现数组的高速排序与链表的归并排序 标签: 数据结构 数组 链表 高速排序 归并排序 抽象类 虚继承 by 小威威 1.介绍 本篇博文将通过课后作业的(15 C++ Hom ...
- 选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用
1.问题来源 在刷题是遇到字符串相关问题中使用 strcmp()函数. 在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底. #include & ...
- 连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort)
连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort) 1,起泡排序(bubble sort),大致有三种算法 基本版,全扫描. 提前终止版,如果发现前区里没有发生交换 ...
- Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。
Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得 ...
- 七种机器内部排序的原理与C语言实现,并计算它们的比较次数与移动次数。
内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 排序是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列.排序分为 ...
- 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...
随机推荐
- batch,iteration,epoch 什么意思
深度学习中经常看到epoch. iteration和batchsize,下面按自己的理解说说这三个的区别: (1)batchsize:批大小.在深度学习中,一般采用SGD训练,即每次训练在训练集中取b ...
- Django基础学习之Cookie 和 Sessions 应用
在Django里面,使用Cookie和Session看起来好像是一样的,使用的方式都是request.COOKIES[XXX]和request.session[XXX],其中XXX是您想要取得的东西的 ...
- c++ linux socket编程 c++网络编程
声明:大部分代码来自这篇博客http://www.cnblogs.com/diligenceday/p/6241021.html, 感谢博主 思路: 思路很重要呦~~~ socket详细信息,思路:h ...
- Java如何获取URL的部分?
在Java编程中,如何获取URL的一部分? 以下示例显示了如何通过net.URL类的url.getProtocol()和url.getFile()方法等获取URL的部分. package com.yi ...
- hibernate 查询全部数据的三种方法
1.Query对象 使用Query对象需要写hql语句,使用hql语句操作的是实体类和属性. 用于查询全部的hql语句:from 实体类名称 例:String hql = "from U ...
- 避免在构造函数中调用虚方法(Do not call overridable methods in constructors)
CLR中说道,不要在构造函数中调用虚方法,原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现.但在这个时候,尚未完成对继承层次结构中所有字段的初始化.所以,调用虚方法会导致不可预测的 ...
- c# 中config.exe 引发的一些问题
public static void CreateConfig(){ //c#可以添加内置的app.config,我们通过ConfigrationManager类可以 //可以很轻松的操作相关节点,操 ...
- 【CF717G】Underfail 费用流
[CF717G]Underfail 题意:赌城拉斯维起司的赌场最近推出了一种新式赌法.它的玩法是由庄家(Joker)设局,赌徒只需要交付一定数额的赌资即可入局.具体地,Joker将给出一个长度为 $n ...
- Jenkins插件管理
1.配置jenkins需要的maven.jdk路径 [root@db01 secrets]# echo $JAVA_HOME /application/jdk [root@db01 secrets]# ...
- select2 javascript控件 如何设置指定的值
$("#id").select2("data") 这样的方法无效 要使用$("#selectNull").val("") ...