文字描述

  在折半插入排序的基础上进行改进, 另设一个和待排序序列L相同的数组D, 首先将L[1]赋值给D[0], 数组D中数据是已经排好序的, first指向最小值下标,final指向最大值下标。初始时,first和final值都为0。之后将L的第二个元素开始依次和D[0]比较,大于D[0]的插入到D[0]之后的序列,小于D[0]的插入到D[0]之前的序列;这里可以将数组D想象成一个循环的圆。

示意图

算法分析

  时间复杂度为n*n, 辅助空间为n,是稳定的排序方法。

  二路插入排序和折半插入排序比,只是可以大概率的减少移动的次数,但不能绝对避免,当待排序序列中的第一个数据就是最小值或者最大值时,2-路插入排序将完全失去它的优越性。

代码实现

 #include <stdio.h>
#include <stdlib.h> #define EQ(a, b) ((a) == (b)) //数a和数b相等则为True,否则为False
#define LT(a, b) ((a) < (b)) //数a小于数b则为True
#define LQ(a, b) ((a) <= (b)) //数a小于或等于数b则为True #define MAXSIZE 20 //待排序数的最多个数
typedef int KeyType; //定义待排序数据的关键字类型为int
typedef int InfoType; //定义待排序数据的其他信息类型为int
typedef struct{
KeyType key; //关键字
InfoType otherinfo; //其他数据项
}RedType; //记录类型 typedef struct{
RedType r[MAXSIZE+]; //r[0]闲置或用作哨兵单元
int length; //顺序表长度
}SqList; //顺序表类型 /*
* 顺序打印序列表L中的关键字
*/
void PrintList(SqList L){
int i = ;
printf("len:%d; data:", L.length);
for(i=; i<=L.length; i++){
printf("%d ", L.r[i].key);
}
printf("\n");
return ;
} #define DEBUG /*
* 2-路插入排序算法的实现
*
* @param
* SqList *L : 待排序的顺序表
*/
void TwoInsertSort(SqList *L)
{
//数组D是和L中关键字列表长度相同的辅助数组
RedType D[MAXSIZE] = {};
//将L中第一个数据存入D[0]
D[] = L->r[]; int i = , j = , n = L->length;
//first表示D中最小值下标,final表示D中最大值下标
int first = , final = ;
int k = ;
#ifdef DEBUG
for(j=; j<n; j++){
printf("%d ", D[j].key);
}
printf("\nthe %d lap:fist=%d, final=%d\n\n", i, first, final);
#endif for(i=; i<=L->length; i++){
if(LT(L->r[i].key, D[first].key)){
// 待插入元素比最小的元素小
first = (first-+n)%n;
D[first] = L->r[i];
}else if(LT(D[].key, L->r[i].key)){
// 待插入元素比最大的元素大
final = (final+)%n;
D[final] = L->r[i];
}else{
// 待插入元素处在最小元素和最大元素中间
// 采用直接插入排序的方法,插入到数组D中合适的位置
k = (final+)%n;
while(LT(L->r[i].key, D[(k-+n)%n].key)){
D[(k+n)%n] = D[(k-+n)%n];
k = (k-+n)%n;
}
D[(k+n)%n] = L->r[i];
final = (final+)%n;
}
#ifdef DEBUG
for(j=; j<n; j++){
printf("%d ", D[j].key);
}
printf("\nthe %d lap:fist=%d, final=%d\n\n", i, first, final);
#endif
}
//将排序记录复制到原来的顺序表里
for(j=; j<n; j++){
L->r[+j] = D[first];
first = (first+)%n;
}
} 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.length = (i-); TwoInsertSort(&L);
PrintList(L);
return ;
}

2-路插入排序

运行

[jennifer@localhost Data.Structure]$ ./a.out 12 5 7 4 5 3 45 76
12 0 0 0 0 0 0 0 
the 0 lap:fist=0, final=0

12 0 0 0 0 0 0 5 
the 2 lap:fist=7, final=0

7 12 0 0 0 0 0 5 
the 3 lap:fist=7, final=1

7 12 0 0 0 0 4 5 
the 4 lap:fist=6, final=1

5 7 12 0 0 0 4 5 
the 5 lap:fist=6, final=2

5 7 12 0 0 3 4 5 
the 6 lap:fist=5, final=2

5 7 12 45 0 3 4 5 
the 7 lap:fist=5, final=3

5 7 12 45 76 3 4 5 
the 8 lap:fist=5, final=4

len:8; data:3 4 5 5 7 12 45 76 
[jennifer@localhost Data.Structure]$

内部排序->插入排序->其它插入排序->2-路插入排序的更多相关文章

  1. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  2. 内部排序->插入排序->其它插入排序->表插入排序

    文字描述 和之前的插入排序比,表插入排序可以保证排序过程中不移动记录:因此表插入排序所用的存储结构和之前的顺序存储不同,表插入排序采用静态链表类型作为待排记录序列的存储结构,设数组中下标0的分量为表头 ...

  3. [4] 算法之路 - 插入排序之Shell间隔与Sedgewick间隔

    题目 插入排序法由未排序的后半部前端取出一个值.插入已排序前半部的适当位置.概念简单但速度不快. 排序要加快的基本原则之中的一个: 是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度 ...

  4. [Swift]八大排序算法(五):插入排序

    排序分为内部排序和外部排序. 内部排序:是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 外部排序:指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存 ...

  5. 选择排序法、冒泡排序法、插入排序法、系统提供的底层sort方法排序之毫秒级比较

    我的代码: package PlaneGame;/** * 选择排序法.冒泡排序法.插入排序法.系统提供的底层sort方法排序之毫秒级比较 * @author Administrator */impo ...

  6. 排序算法(1)--Insert Sorting--插入排序[1]--straight insertion sort--直接插入排序

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.基本思想 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成 ...

  7. 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  8. 七种机器内部排序的原理与C语言实现,并计算它们的比较次数与移动次数。

    内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 排序是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列.排序分为 ...

  9. C++ 内部排序(一)

    先讲两个概念,所谓内部排序,指待排序的节点均存储在内存中.所谓排序的稳定性,指排序后,值相等的两个元素原来相对的位置是否发生变化了.举个例子. 待排序列:3(1),1,5,3(2)  稳定排序:1,3 ...

随机推荐

  1. linux每日命令(6):rm命令

    rm是常用的命令,该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除.对于链接文件,只是删除了链接,原有文件均保持不变. rm是一个危险的命令,使用的 ...

  2. goldengate–使用filter+@GETENV在线重新初始化指定的table

    goldengate–使用filter+@GETENV在线重新初始化指定的table 转载:http://www.easyora.net/blog/using_filter_getenv_functi ...

  3. HttpPost请求将json作为请求体传入的简单处理方法

    https://www.cnblogs.com/mambahyw/p/7875142.html **************************************************** ...

  4. Excel中substitute替换函数的使用方法

    问题现象:在Excel中,对几千条数据按照时间顺序排序,但总是有部分数据不参与排序,单纯用单元格调整不起任何作用. 解决办法: 数据排列问题最重要的是数据格式的一致性.解决这个问题,建议按如下步骤: ...

  5. Java知多少(29)覆盖和重载

    在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类 ...

  6. 【转帖】39个让你受益的HTML5教程

    39个让你受益的HTML5教程                    闲话少说,本文作者为大家收集了网上学习HTML5的资源,期望它们可以帮助大家更好地学习HTML5. 好人啊! 不过,作者原来说的4 ...

  7. spring与quartz定时器

    参考: http://www.iteye.com/topic/399980 http://www.cnblogs.com/xrab/p/5850186.html

  8. 01简单工厂模式SimpleFactory

    一.什么是简单工厂模式 简单工厂模式属于类的创建型模式,又叫做静态 工厂方法模式.通过专门定义一个类来负责创建 其他类的实例,被创建的实例通常都具有共同的 父类. 二.模式中包含的角色及其职责 1.工 ...

  9. Mercurial (hg) Hook : PHP Syntax Check , hg 代码检测 钩子

    用百度搜了一遍hg的hook教程,发现真的是太少了.公司目前正要用到这个,正好本人负责,So. 百度是个坑,少有的几篇文章,再加上善于发现的眼睛,发现TortoiseHg的UI操作都会在控制台显示动作 ...

  10. Linux下跑程序,防止命令终端(断网,断电)

    有时候我们在服务器上跑程序,会发现当我们离开窗口时,正在执行的程序中断了,这让人非常郁闷.下面介绍防止程序中断的方法: 新建一个名为yourname的Screen窗口: screen -S yourn ...