前言

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


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. KingbaseES lag 和 lead 函数

    1.简介 lag与lead函数是跟偏移量相关的两个分析函数,通过这两个函数可以在一次查询中取出同一字段的前N行的数据(lag)和后N行的数据(lead)作为独立的列,从而更方便地进行进行数据过滤. 2 ...

  2. Dapr 的 gRPC组件 (又叫可插拔组件) 的提案

    Dapr 在1.9 版本中的提案,计划在 Dapr Runtime 中组件采用 外部 gRPC 组件: https://github.com/dapr/dapr/issues/3787 ,针对这个 g ...

  3. SSM保姆级从创建项目到使用,包括事务和设置回滚

    1. 简介 Spring 和 Mybaits整合 2. 创建项目 负责将代理类记性扫描,扫描的是Mapper接口所在的包,这个是mybatis提供的,所以会去找SqlSessionFactory 2. ...

  4. 全网最全Redis学习

    一.Redis简介 Redis是以Key-Value形式进行存储的NoSQL数据库,C语言进行编写的.平时操作的数据都在内存中,效率特高,读的效率110000/s,写81000/s,所以多把Redis ...

  5. Elasticsearch:用户安全设置

    Elastic Stack的组件是不安全的,因为它没有内置的固有安全性. 这意味着任何人都可以访问它. 在生产环境中运行Elastic Stack时,这会带来安全风险. 为了防止生产中未经授权的访问, ...

  6. Solutions:应用程序性能监控/管理(APM)实践---python/flask

    本文部分内容转载自:https://blog.csdn.net/UbuntuTouch/article/details/102844900 官方文档:https://www.elastic.co/gu ...

  7. 使用logstash拉取MySQL数据存储到es中的再次操作

    使用情况说明: 已经使用logstash拉取MySQL数据存储到es中,es中也创建了相应的索引,也存储了数据.假若把这个索引给删除了,再次进行同步操作的话要咋做,从最开始的数据进行同步,而不是新增的 ...

  8. 存储卷PersistentVolume

    概述 与管理计算资源相比,管理存储资源是一个完全不同的问题.为了更好的管理存储,Kubernetes 引入了 PersistentVolume 和 PersistentVolumeClaim 两个概念 ...

  9. 安装 loki 轻量级日志监控系统

    文章转载自:https://www.cnblogs.com/flypig666/archive/2004/01/13/14151801.html 从本文中学习到的是docker-compose相关命令 ...

  10. 仿B站小火箭发射上升

    效果图:   CSS代码块: <style type="text/css"> .goTop { background-image: url(img/rocket_top ...