插入排序优化——超越归并排序的超级算法

插入排序及优化

  • 插入排序算法
    • 算法讲解
    • 数据模拟
    • 代码
  • 优化思路
    • 一、二分查找
    • 二、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 n1位位结尾
  • 将它移动到开头位第 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 0X,Y32000)。星象图中的每个点处最多只有一颗星星。所有星星按 Y Y Y坐标升序排列。 Y Y Y坐标相等的星星按 X X X坐标升序排列。

输出格式

输出包含 N N N行,每行一个整数。第一行包含等级 0 0 0的星星数目,第二行包含等级 1 1 1的星星数目,依此类推,最后一行包含等级为 N − 1 N-1 N1的星星数目。

输入输出样例

输入样例

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 f1就是当前星星的等级
  • c o p y copy copy将数据,从当前合适的位置开始,到 i − 1 i-1 i1往后移动一位
  • 将当前数据存入排序数组
  • 用另一个数组标记这个等级的星星 + + ++ ++
  • 循环输出每个级别的星星

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/43020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HIVE SQL实现分组字符串拼接concat

在Mysql中可以通过group_concat()函数实现分组字符串拼接&#xff0c;在HIVE SQL中可以使用concat_ws()collect_set()/collect_list()函数实现相同的效果。 实例&#xff1a; abc2014B92015A82014A102015B72014B6 1.concat_wscollect_list 非去重拼接 select a ,concat_ws(-…

Linux系统中基于NGINX的代理缓存配置指南

作为一名专业的爬虫程序员&#xff0c;你一定知道代理缓存在加速网站响应速度方面的重要性。而使用NGINX作为代理缓存服务器&#xff0c;能够极大地提高性能和效率。本文将为你分享Linux系统中基于NGINX的代理缓存配置指南&#xff0c;提供实用的解决方案&#xff0c;助你解决在…

C语言刷题训练DAY.8

1.计算单位阶跃函数 解题思路&#xff1a; 这个非常简单&#xff0c;只需要if else语句即可完成 解题代码&#xff1a; #include <stdio.h>int main() {int t 0;while(scanf("%d",&t)!EOF){if (t > 0)printf("1\n");else if (t < 0)pr…

大模型基础02:GPT家族与提示学习

大模型基础&#xff1a;GPT 家族与提示学习 从 GPT-1 到 GPT-3.5 GPT(Generative Pre-trained Transformer)是 Google 于2018年提出的一种基于 Transformer 的预训练语言模型。它标志着自然语言处理领域从 RNN 时代进入 Transformer 时代。GPT 的发展历史和技术特点如下: GP…

【校招VIP】java语言类和对象之map、set集合

考点介绍&#xff1a; map、set集合相关内容是校招面试的高频考点之一。 map和set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索效率与其具体的实例化子类有关系。 『java语言类和对象之map、set集合』相关题目及解析内容可点击文章末尾链接查看&#xff01; …

深入了解Maven(一)

目录 一.Maven介绍与功能 二.依赖管理 1.依赖的配置 2.依赖的传递性 3.排除依赖 4.依赖的作用范围 5.依赖的生命周期 一.Maven介绍与功能 maven是一个项目管理和构建工具&#xff0c;是基于对象模型POM实现。 Maven的作用&#xff1a; 便捷的依赖管理&#xff1a;使用…

springboot 使用zookeeper实现分布式队列

一.添加ZooKeeper依赖&#xff1a;在pom.xml文件中添加ZooKeeper客户端的依赖项。例如&#xff0c;可以使用Apache Curator作为ZooKeeper客户端库&#xff1a; <dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</…

【java安全】Log4j反序列化漏洞

文章目录 【java安全】Log4j反序列化漏洞关于Apache Log4j漏洞成因CVE-2017-5645漏洞版本复现环境漏洞复现漏洞分析 CVE-2019-17571漏洞版本漏洞复现漏洞分析 参考 【java安全】Log4j反序列化漏洞 关于Apache Log4j Log4j是Apache的开源项目&#xff0c;可以实现对System.out…

英语——构词法

按照语言一定的规律创造新词的方法就叫作构词法。英语中常见的构词法包括六种:合成法、派生法、转化法、混合法、截短法和首尾字母结合法。其中后三种将在第四节“缩写和简写”中进行讲解。 第一节 合成法 英语构词法中把两个单词连在一起合成一个新词,前一个词修饰或限定后…

前端性能优化——包体积压缩插件,打包速度提升插件,提升浏览器响应的速率模式

前端代码优化 –其他的优化可以具体在网上搜索 压缩项目打包后的体积大小、提升打包速度&#xff0c;是前端性能优化中非常重要的环节&#xff0c;结合工作中的实践总结&#xff0c;梳理出一些 常规且有效 的性能优化建议 ue 项目可以通过添加–report命令&#xff1a; "…

innodb索引与算法

B树主键插入 B树在innodb的插入有三种模式page_last_insert, page_dirction, page_N_direction 而在bustub里面的B树就是page_N_direction,如果是自增主键的话&#xff0c;就是上面这样的插入法 FIC优化 (DDL) 选择性统计 覆盖索引 MMR ICP优化 自适应hash 全文索引 MySQL…

Rust之编写自动化测试

1、测试函数的构成&#xff1a; 在最简单的情形下,Rust中的测试就是一个标注有test属性的函数。属性 (attribute)是一种用于修饰Rust代码的元数据。只需要将#[test]添加到关键字fn的上一行便可以将函数转变为测试函数。当测试编写完成后,我们可以使用cargo test命令来运行测试…

Flink-----Standalone会话模式作业提交流程

1.Flink的Slot特点: 均分隔离内存,不隔离CPU可以共享:同一个job中,不同算子的子任务才可以共享同一个slot,同时在运行的前提是,属于同一个slot共享组,默认都是“default”2.Slot的数量 与 并行度 的关系 slot 是一种静态的概念,表示最大的并发上线并行度是个动态的概念…

List和ObservableCollection和ListBinding在MVVM模式下的对比

List和ObservableCollection和ListBinding在MVVM模式下的对比 List 当对List进行增删操作后&#xff0c;并不会对View进行通知。 //Employee public class Employee : INotifyPropertyChanged {public event PropertyChangedEventHandler? PropertyChanged;public string N…

Vue-13.创建完整的Vue项目(vue+vue-cli+js)

前言 之前写了命令创建Vue项目&#xff0c;但是事实上我们可以直接用编译器直接创建项目&#xff0c;这里我使用webstorm&#xff08;因为我是前后端兼修的所以我习惯使用Idea家族的编译器&#xff09; 只写前端的推荐用VsCode前后端都写的推荐用webstorm 新建项目 项目初始…

确保Django项目的稳定运行和持续改进

确保Django项目的稳定运行和持续改进 引言 Django是一个强大的Python Web框架&#xff0c;用于构建高效、可靠的Web应用程序。然而&#xff0c;部署一个Django项目并不意味着工作已经完成。在项目上线之后&#xff0c;确保项目的稳定运行并不断进行改进是非常重要的。本博客将…

vscode 安装勾选项解释

1、通过code 打开“操作添加到windows资源管理器文件上下文菜单 &#xff1a;把这个两个勾选上&#xff0c;可以对文件使用鼠标右键&#xff0c;选择VSCode 打开。 2、将code注册为受支持的文件类型的编辑器&#xff1a;不建议勾选&#xff0c;这样会默认使用VSCode打开支持的相…

《Linux从练气到飞升》No.15 Linux 环境变量

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

微信小程序通用字体代码

下面是一个简单的微信小程序通用字体代码示例&#xff1a; // 在app.wxss中设置全局字体样式 import ./styles/fonts.wxss;// 在fonts.wxss中定义字体样式 font-face {font-family: CustomFont;src: url(font.ttf) format(truetype); }// 在page.wxss中使用自定义字体样式 .cus…

SASS 学习笔记 II

SASS 学习笔记 II 上篇笔记&#xff0c;SASS 学习笔记 中包含&#xff1a; 配置 变量 嵌套 这里加一个扩展&#xff0c;嵌套中有一个 & 的用法&#xff0c;使用 & 可以指代当前 block 中的 selector&#xff0c;后面可以追加其他的选择器。如当前的 scope 是 form&a…