插入排序优化——超越归并排序的超级算法
插入排序及优化
- 插入排序算法
- 算法讲解
- 数据模拟
- 代码
- 优化思路
- 一、二分查找
- 二、copy函数
- 优化后代码
- 算法的用途
- 题目:数星星(POJ2352 star)
- 输入输出格式
- 输入格式:
- 输出格式
- 输入输出样例
- 输入样例
- 输出样例
- 题目讲解
- 步骤如下
- AC 代码
插入排序算法
在了解如何改进插入排序之前,我们先要了解插入排序的基本算法:
算法讲解
插入排序对于少量元素的排序,是一个有效的算法 。
插入排序是一种简单的排序方法,它是将一个数据插入到已经排好序的有序数组,从而形成一个新的有序数组。
插入排序的工作方式像许多人排序扑克牌:
我们每次从桌子上拿走一张牌并将其插入到手中正确的位置。
为了找到它的正确位置,我们从右到左将它与手中的每张牌进行比较。
因此,手上的牌总是有序。
数据模拟
原本要排序的数为 5 3 4 2 9 1,从小到大排序。
3 5 4 2 9 1 // 将3放到合适的位置(5前面)3 4 5 2 9 1 // 将4放到合适的位置(3、5中间)2 3 4 5 9 1 // 将2放到合适的位置(最前面)2 3 4 5 9 1 // 将9放到合适的位置(最后面)1 2 3 4 5 9 // 将1放到合适的位置(最前面)
排序结束!!!
代码
#include <iostream>
using namespace std;
int n,a[2000]; //定义数据个数n,排序数组a
int main()
{cin >>n; //输入个数for (int i=1;i<=n;i++)cin >>a[i]; //输入数据for (int i=2;i<=n;i++) //第一个数本身只有一个元素,所有有序,因此不用参与排序{int j,k=a[i]; //记录下当前元素for (j=i-1;j>0;j--){if (a[j]>k) //若前面一个数大于当前元素a[j+1]=a[j]; //则将前面一个元素往后移动elsebreak; //否则:说明当前元素已经找到了合适的位置,推出循环}a[j+1]=k; //将当前元素放入数组的合适的位置/* 输出排序的过程for (int j=1;j<=n;j++)cout <<a[j] <<" ";cout <<endl;*/}for (int i=1;i<=n;i++)cout <<a[i] <<" "; //输出排序好的数组return 0;
}
优化思路
我们发现,插入排序的过程浪费在了查找合适的位置上,那么怎么优化呢?
我们知道,插入排序一直在维护 前 i i i个数是有序的,那么如何快速在有序的数列中查找一个小于(或大于)自己的数呢?
一、二分查找
二分!!!!
那么这样我们就讲查找的时间从 O ( n ) O(n) O(n)缩短为 O ( n l o g ( n ) ) O(n~log(n)) O(n log(n))!!
忍不住激动!!
可是找到位置不够,还要进行移动啊。移动的时间复杂度是 O ( n ) O(n) O(n)那么这样非但没有优化,反而还增加了查找的时间。。。
希望瞬间破灭!!
但是我会向它屈服吗???
会 吗?
明显不会!
二、copy函数
我们可以使用一个 S T L STL STL库里面的一个函数:
copy(a,a+n,a+1);
c o p y copy copy函数!!
这个函数可以在 O ( 1 ) O(1) O(1)的时间范围内将数组的某一段移动到,
使用方法:
以上面的操作为例子,这表明:
- 以 a a a数组的第 0 0 0位为开头
- 以 a a a数组的第 n − 1 n-1 n−1位位结尾
- 将它移动到开头位第 1 1 1位的位置
那么,这就好办了,只需要要讲两个结合起来,一个速度与归并排序相当,代码比归并排序简短许多的超级优化插入排序代码诞生了:
优化后代码
#include <bits/stdc++.h>
#define N 2000000
using namespace std;
int n,x,y,f,t[N],k[N];
int main() {scanf("%d",&n);for (int i=1; i<=n; i++) {scanf("%d",&x);f=upper_bound(t+1,t+i,x)-t; //记录二分的位置copy(t+f,t+i,t+f+1); //copyt[f]=x; //存入数组}for (int i=1; i<=n; i++) {printf("%d ",t[i]);}return 0;
}
输入数据:
5
4 9 1021 54 3
输出数据:
3 4 9 54 1021
也是对了好吧~~
算法的用途
这个算法可以快速的在有序数列里面进行操作,也是异常的方便快捷,代码超级简短!!
下面给一道可以用这个算法解决的问题:
题目:数星星(POJ2352 star)
天文学家经常观察星象图。星象图中用平面上的点来表示一颗星星,每一颗星星都有一个笛卡尔坐标。设定星星的等级为其左下角星星的总数。天文学家们想知道星星等级的分布情况。
比如上图, 5 5 5号星星的等级为 3 3 3(其左下角有编号为 1 1 1、 2 2 2、 4 4 4星星共三颗)。 2 2 2号星星和 4 4 4号星星的等级为 1 1 1。在上图中只有一颗星星等级为 0 0 0,两颗星星等级为 1 1 1,一颗星星等级为 2 2 2,一颗星星等级为 3 3 3。
给定一个星象图,请你写一个程序计算各个等级的星星数目。
输入输出格式
输入格式:
输入的第一行包含星星的总数 N ( 1 < = N < = 15000 ) N (1<=N<=15000) N(1<=N<=15000)。接下来 N N N行,描述星星的坐标 ( X , Y ) (X,Y) (X,Y)( X X X和 Y Y Y用空格分开, 0 ≤ X , Y ≤ 32000 0\le X,Y\le 32000 0≤X,Y≤32000)。星象图中的每个点处最多只有一颗星星。所有星星按 Y Y Y坐标升序排列。 Y Y Y坐标相等的星星按 X X X坐标升序排列。
输出格式
输出包含 N N N行,每行一个整数。第一行包含等级 0 0 0的星星数目,第二行包含等级 1 1 1的星星数目,依此类推,最后一行包含等级为 N − 1 N-1 N−1的星星数目。
输入输出样例
输入样例
5
1 1
5 1
7 1
3 3
5 5
输出样例
1
2
1
1
0
题目讲解
由于输入数据有序,所以在第 i i i颗星星左下角的星星一定在 i i i前面!!原理自己想想就知道了~~
所以其实就是求在点 i i i前面的点中,有多少个的 X X X坐标是比 i i i的 X X X坐标要小的,因此直接考虑插入排序做法:
步骤如下
- 输入星星的数量 n n n
- 循环从 1 1 1到 n n n
- 每次输入当前点的 X X X和 Y Y Y
- 用二分查找当前点的 X X X应当放在哪个位置
- 用变了量 f f f记录位置, f − 1 f-1 f−1就是当前星星的等级
- 用 c o p y copy copy将数据,从当前合适的位置开始,到 i − 1 i-1 i−1往后移动一位
- 将当前数据存入排序数组
- 用另一个数组标记这个等级的星星 + + ++ ++
- 循环输出每个级别的星星
AC 代码
#include <bits/stdc++.h>
#define N 20000
using namespace std;
int n,x,y,f,t[N],k[N];
int main() {scanf("%d",&n);for (int i=1; i<=n; i++) {scanf("%d%d",&x,&y);f=upper_bound(t+1,t+i,x)-t;copy(t+f,t+i,t+f+1);t[f]=x;k[f-1]++;}for (int i=0; i<n; i++) {printf("%d\n",k[i]);}return 0;
}
相关文章:

插入排序优化——超越归并排序的超级算法
插入排序及优化 插入排序算法算法讲解数据模拟代码 优化思路一、二分查找二、copy函数 优化后代码算法的用途题目:数星星(POJ2352 star)输入输出格式输入格式:输出格式 输入输出样例输入样例输出样例 题目讲解步骤如下AC 代码 插入…...

面试之快速学习STL-容器适配器
1. 容器适配器 简单的理解容器适配器,其就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用。 注意:默认使用的基础容器不代表一定只能用它,比如queue可以用deque,list。 如果你希望你的qu…...

性能比较 - Spring Boot 应用程序中的线程池与虚拟线程 (Project Loom)
本文比较了 Spring Boot 应用程序中的不同请求处理方法:ThreadPool、WebFlux、协程和虚拟线程 (Project Loom)。 在本文中,我们将简要描述并粗略比较可在 Spring Boot 应用程序中使用的各种请求处理方法的性能。 高效的请求处理在开发高性能后端…...
rust学习-打印结构体中的vec
write! 宏 将格式化后的数据写入到一个缓冲区(buffer),而不是直接打印到标准输出或文件中。 这个缓冲区可以是字符串,也可以是需要写入的文件的缓冲区。 write!(writer, format_string, expr1, expr2, ...);writer 参数是一个实…...

FPGA: RS译码仿真过程
FPGA: RS译码仿真过程 在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程,这篇记录利用译码IP核进行RS解码的仿真过程,带有程序和结果。 1. 开始准备 在进行解码的过程时,同时利用上一篇中的MATLAB仿真程序和编码过程&#x…...
PostgreSQL 查询数据表、视图信息
--获得指定schema范围内的所有表和视图的列表,可指定一个排除表前缀模式with param as (select public,iit as schema_name,db2g% as exclude_pattern),base_info as (--获得所有基表select pg_namespace.nspname as schema_name, a.relname as tbl_name ,TBL as tb…...

手撕vector容器
一、vector容器的介绍 vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素,但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。 总结:vector是一个动态…...

PyMuPDF`库实现PDF旋转功能
本文介绍了一个简单的Python应用程序,用于将PDF文件转换为旋转90度的PDF文件。主要用于csdn网站中导出的博客pdf是横向的,看起来不是很方便,才想到用python编制一个将pdf从横向转为纵向的功能。 功能 该PDF转换工具具有以下功能:…...

微人事 登录问题完善
重启服务端的时候,发现前端页面会操作不了,这样后端session会失效,我们就需要让页面重新跳转到登录页 springsecurity配置类后端配置 前端拦截器进行拦截跳转...
【业务功能篇64】安装docker容器,在docker上安装mysql
docker教程: https://www.runoob.com/docker/docker-tutorial.html卸载docker 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项。 yum remove docker docker-client docker-client-latest docker-co…...
MyBatis的基本概念和核心组件
MyBatis的基本概念 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Pla…...
sql update执行返回0,能否判断数据不存在
答案:不能。 update执行返回0的情况 1、没有找到需要更新的数据,就是这条记录不存在 例如:where后面的条件是id0,那这条记录肯定是不存在的,返回结果是0 2、更新时的数据和要更新的数据完全一致时 例如:更…...

数据分析 | 调用Optuna库实现基于TPE的贝叶斯优化 | 以随机森林回归为例
1. Optuna库的优势 对比bayes_opt和hyperoptOptuna不仅可以衔接到PyTorch等深度学习框架上,还可以与sklearn-optimize结合使用,这也是我最喜欢的地方,Optuna因此特性可以被使用于各种各样的优化场景。 2. 导入必要的库及加载数据 用的是sklea…...

stm32单片机开关输入控制蜂鸣器参考代码(附PROTEUS电路图)
说明:这个buzzer的额定电压需要改为3V,否则不会叫,源代码几乎是完全一样的 //gpio.c文件 /* USER CODE BEGIN Header */ /********************************************************************************* file gpio.c* brief Thi…...

打印X型的图案
int main() {int n0;int i0;int j0;scanf("%d",&n);for(i0;i<n;i){for(j0;j<n;j){if(ij){printf("*");}else if((ij)n-1){printf("*");}elseprintf(" ");}printf("\n");}return 0; }...

不含数字的webshell绕过
异或操作原理 1.首先我们得了解一下异或操作的原理 在php中,异或操作是两个二进制数相同时,异或(相同)为0,不同为1 举个例子 A的ASCII值是65,对应的二进制值是0100 0001 的ASCII值是96,对应的二进制值是 0110 000…...

Mac上传项目源代码到GitHub的修改更新
Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github,不得不说,真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先,在本地终端命令行打开至项目文件下第一步:查看当前的git仓库状态,可以使用git…...

Android6:片段和导航
创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…...

ClickHouse AST is too big 报错问题处理记录
ClickHouse AST is too big 报错问题处理记录 问题描述问题分析解决方案1、修改系统配置2、修改业务逻辑 问题描述 项目中统计报表的查询出现 AST is too big 问题,报错信息如下: 问题分析 报错信息显示 AST is too big。 AST 表示查询语法树中的最大…...

DPDK系列之二十七DIDO
一、DIDO介绍 随着计算机技术发展,特别是应用技术的快速发展。应用场景对计算机的处理速度几乎已经到了疯狂的地步。说句大白话,再快的CPU也嫌慢。没办法,CPU和IO等技术基本目前都处在了瓶颈之处,大幅度提高,短时间内…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...