前言

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


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 V8R6C5B041 sys_backup.sh单实例备份案例

    ​ 数据库版本: test=# select version(); version ---------------------------------------------------------- ...

  2. python 作用域与命名空间

    作用域 作用域分为: 全局作用域 局部作用域 在函数内部的作用域叫做局部作用域,局部作用域中的变量叫做局部变量 非函数内部的作用域叫做全局作用域,全局作用域中的变量叫做全局变量 局部作用域可以使用全局 ...

  3. Elasticsearch:如何把Elasticsearch中的数据导出为CSV格式的文件

    本教程向您展示如何将数据从Elasticsearch导出到CSV文件. 想象一下,您想要在Excel中打开一些Elasticsearch中的数据,并根据这些数据创建数据透视表. 这只是一个用例,其中将 ...

  4. 一文搞定 Spring事务

    Spring 事务 上文 使用SpringJDBC 1.JDBC事务控制 ​ 不管你现在使用的是那一种ORM开发框架,只要你的核心是JDBC,那么所有的事务处理都是围绕着JDBC开展的,而JDBC之中 ...

  5. 集合框架——LinkedList集合源码分析

    目录 示例代码 底层代码 第1步(初始化集合) 第2步(往集合中添加一个元素) 第3步(往集合中添加第二个元素) 第4步(往集合中添加第三个元素) LinkedList添加元素流程示意图 第5步(删除 ...

  6. 追求性能极致:Redis6.0的多线程模型

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  7. P2216 [HAOI2007]理想的正方形 方法记录

    [HAOI2007]理想的正方形 题目描述 有一个 \(a \times b\) 的整数组成的矩阵,现请你从中找出一个 \(n \times n\) 的正方形区域,使得该区域所有数中的最大值和最小值的 ...

  8. 【Java8新特性】- Optional应用

    Java8新特性 - Optional应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...

  9. java常用注解校验参数

    validation中内置的constraints 注解 描述 @AssertFalse 所注解的元素必须是Boolean类型,且值为false @AssertTrue 所注解的元素必须是Boolea ...

  10. Kafka之概述

    Kafka之概述 一.消息队列内部实现原理 (1)点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除) 点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消 ...