前言

本文章是建立在 插入排序 的基础上写的,如果还有不懂 插入排序 的童鞋先停下脚步,可以先看看这里~ 直接/折半插入排序


2路插入排序解释

插入排序 中,当待插入元素需要插入的位置位于当前有序序列的首位时,我们需要进行更多的元素后移操作。过多的交换操作消耗了很多时间,因此可以着眼于减少交换次数这个方面,提高 插入排序 的效率。这就是为什么出现了 2路插入排序

2路插入排序 是对 插入排序 的进一步改进,它是通过在首尾两路同时进行插入操作,来减少插入过程中移动的次数。

那么具体如何实现呢?

我们用一个临时数组 tmp 来存储当前已排序序列,每次插入元素后有序序列的长度都会 +1。因为要进行首尾两路的插入操作,我们需要将临时数组 tmp 作为一个循环数组来处理,同时定义 frontrear 来标记当前有序序列中的头尾。这是 2路插入排序 的核心。


2路插入排序动态演示

我们需要一个循环数组 tmp,因此有了下图

我们以 [5, 3, 8, 2, 7, 4, 1, 6] 为例进行动态演示

第一次插入

第二次插入

第三次插入

第四次插入

第五次插入

第六次插入

第七次插入

第八次插入


2路插入排序核心代码

void TwoInsertSort(int a[], int n){
int *tmp = new int[n]; //临时数组
int front = 0, rear = 0; //记录当前tmp数组中最大值和最小值的位置
tmp[0] = a[0]; //初始化tmp for(int i = 1; i < n; i++){
int key = a[i];
//如果当前插入的元素比最小的元素更小
if(key < tmp[front]){
front = (front - 1 + n) % n;
tmp[front] = key;
}
//如果当前插入元素比最大元素更大
else if(key > tmp[rear]){
rear = (rear + 1 + n) % n;
tmp[rear] = key;
}
//如果在当前最小和最大之间
else{
int k = (rear + n) % n;
//将比当前插入值key大的进行后移
while(tmp[(k + n) % n] > key){
tmp[(k + 1 + n) % n] = tmp[(k + n) % n];
k = (k - 1 + n) % n;
} tmp[(k + 1 + n) % n] = key; //当前插入值放到合适位置
rear = (rear + 1 + n) % n; //更新最大值位置(有序序列长度+1)
}
} //复制临时数组到原数组中
for(int k = 0; k < n; k++)
a[k] = tmp[(front + k) % n];
delete[] tmp;
}

完整程序源代码

#include<iostream>
#include<ctime>
using namespace std; //临时数组作为循环数组操作
void TwoInsertSort(int a[], int n){
int *tmp = new int[n]; //临时数组
int front = 0, rear = 0; //记录当前tmp数组中最大值和最小值的位置
tmp[0] = a[0]; //初始化tmp for(int i = 1; i < n; i++){
int key = a[i];
//如果当前插入的元素比最小的元素更小
if(key < tmp[front]){
front = (front - 1 + n) % n;
tmp[front] = key;
}
//如果当前插入元素比最大元素更大
else if(key > tmp[rear]){
rear = (rear + 1 + n) % n;
tmp[rear] = key;
}
//如果在当前最小和最大之间
else{
int k = (rear + n) % n;
//将比当前插入值key大的进行后移
while(tmp[(k + n) % n] > key){
tmp[(k + 1 + n) % n] = tmp[(k + n) % n];
k = (k - 1 + n) % n;
} tmp[(k + 1 + n) % n] = key; //当前插入值放到合适位置
rear = (rear + 1 + n) % n; //更新最大值位置(有序序列长度+1)
}
} //复制临时数组到原数组中
for(int k = 0; k < n; k++)
a[k] = tmp[(front + k) % n];
delete[] tmp;
} void show(int *a, int n){
for(int i = 0; i < n; i++)
cout<<*(a + i)<<" ";
cout<<endl;
} main(){
int a[50];
srand((int)time(0));
int k = 0;
while(k < 50)
a[k++] = rand() % 100 + 1; //数字范围[1,100] show(a, 50); TwoInsertSort(a, 50); cout<<endl<<endl;
show(a, 50);
}

程序运行结果图

[排序算法] 2路插入排序 (C++)的更多相关文章

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

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

  2. Java常见排序算法之折半插入排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  3. Java常见排序算法之直接插入排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  4. 排序算法之直接插入排序Java实现

    排序算法之直接插入排序 舞蹈演示排序: 冒泡排序: http://t.cn/hrf58M 希尔排序:http://t.cn/hrosvb  选择排序:http://t.cn/hros6e  插入排序: ...

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

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

  6. 结构-行为-样式-Js排序算法之 直接插入排序

    最新因工作原因需要接触到算法,之前学习C++的时候有接触过算法,Javascript中实现算法其实也是大同小异.下面我讲下第一个实现的排序算法--直接插入排序.基本实现思路:假定一个数组中前n(n&g ...

  7. 排序算法之折半插入排序的思想以及Java实现

    1 基本思想 折半插入排序(binary insertion sort)的基本原理与直接插入排序相同,不同之处在于,确定当前记录在前面有序子数组中的位置时,直接插入排序是采用顺序查找的方法,而折半插入 ...

  8. 基本的排序算法C++实现(插入排序,选择排序,冒泡排序,归并排序,快速排序,最大堆排序,希尔排序)

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/8529525.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  9. 我的Java开发学习之旅------>Java经典排序算法之二分插入排序

    一.折半插入排序(二分插入排序) 将直接插入排序中寻找A[i]的插入位置的方法改为采用折半比较,即可得到折半插入排序算法.在处理A[i]时,A[0]--A[i-1]已经按关键码值排好序.所谓折半比较, ...

  10. 八大排序算法之直接插入排序(InsertionSort)

    常见的排序算法 今天复习[直接插入排序] 核心思想:有序数组中 找位置 -- 给无序数组第一个 找位置 ` public class InsertionSort { // 核心思想:有序数组中 找位置 ...

随机推荐

  1. Servlet小结

    1.sevlet的生命周期 用户在发送第一次请求的时候Servlet对象被实例化(AServlet的构造方法被执行了.并且执行的是无参数构造方法.) AServlet对象被创建出来之后,Tomcat服 ...

  2. 《Java基础——线程类》

    Java基础--线程类       一.线程的创建之Thread类: 规则: 通过声明一个新类作为子类继承 Thread 类,并复写 run() 方法,就可以启动新线程并执行自己定义的 run()方法 ...

  3. JS 模块化 - 03 AMD 规范与 Require JS

    1 AMD 规范介绍 AMD 规范,全称 Asynchronous Module Definition,异步模块定义,模块之间的依赖可以被异步加载. AMD 规范由 Common JS 规范演进而来, ...

  4. 使用 Loki 微服务模式部署生产集群

    转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247500523&idx=1&sn=0994af2b50 ...

  5. ProxySQL(4):多层配置系统

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9280793.html ProxySQL中的库 使用ProxySQL的Admin管理接口连上ProxySQL, ...

  6. Deployment故障排除图解

    PDF文件下载地址:https://files.cnblogs.com/files/sanduzxcvbnm/troubleshooting-kubernetes.pdf

  7. NSIS隐藏桌面

    下午在网上闲逛发现了一段代码, 刷新桌面用的,当时觉得可以利用nsis现有命令再结合API来实现,翻了些资料,终于搞定,同时结合查找到的桌面句柄,写了一个隐藏桌面的小玩意娱乐下. 完整脚本: !inc ...

  8. 一文读懂Apache Geode缓存中间件

    目录 一.对缓存中间件的诉求 1.1 我们为什么需要缓存中间件 1.2 缓存的分类 1.1.1 弱势缓存 1.1.2 强势缓存 二.什么是Apache Geode 2.1 Apache Geode的架 ...

  9. aws-cli命令-S3相关的操作及管理

    在工作中,我们可能经常会将本地数据上传S3进行备份,或者将S3数据下载到本地 本文主要讲解下,工作中可能经常会用到的与S3相关的操作 1.将本地目录的数据同步到指定的S3位置,及s3资源管理 # 同步 ...

  10. P7113 [NOIP2020] 排水系统 (拓扑排序)

    (不想打高精,也不想学习其他大佬的神仙写法,打了90分的错解). 本题容易想到用拓扑排序处理,涉及分数的加法,用long long会超时,不过通分时先除后乘卡一下也可以拿90分. 结构体真是个复杂的东 ...