数据结构与算法02-排序算法

介绍

排序算法是计算机科学中被广泛研究的一个课题。历时多年,它发展出了数十种算法,这些
算法都着眼于一个问题:如何将一个无序的数字数组整理成升序?先来学习一些“简单排序”,它们很好懂,但效率不如其他排序算法。主打一个循序渐进👏

冒泡排序🐳

假设要对[4, 2, 7, 1, 3]进行排序。它现在是无序的,我们的目标是产生一个包含相同元素、升序的数组。
第 1 步:首先,比较 4 和 2。如图可见它们的顺序是错的
在这里插入图片描述
第 2 步:交换它们的位置
第 3 步:比较 4 和 7:
在这里插入图片描述
依次类推,每一次轮回过后,未排序的值中最大的那个都会“冒”到正确的位置上。

用python实现

def bubble_sort(list):unsorted_until_index = len(list) - 1sorted = Falsewhile not sorted:sorted = Truefor i in range(unsorted_until_index):if list[i] > list[i+1]:sorted = Falselist[i], list[i+1] = list[i+1], list[i]unsorted_until_index = unsorted_until_index - 1list = [65, 55, 45, 35, 25, 15, 10]
bubble_sort(list)
print(list)

输出:
[10, 15, 25, 35, 45, 55, 65]

效率

冒泡排序的执行步骤可分为两种。

  • 比较:比较两个数看哪个更大。
  • 交换:交换两个数的位置以使它们按顺序排列
    如果数组不只是随机打乱,而是完全反序,在这种最坏的情况下,每次比较过后都得进行一
    次交换。
    现在把两种步骤放在一起来看。一个含有 10 个元素的数组,需要:
    9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 = 45 次比较,以及 45 次交换,共 90 步。
    效率太低了😓。元素量呈倍数增长,步数却呈指数增长,如下表所示:
    在这里插入图片描述
    因此描述冒泡排序效率的大 O 记法,是 O(N 2)。
    规范一些来说:用 O(N 2)算法处理 N 个元素,大约需要 N 2步。
    O(N 2)算法是比较低效的,随着数据量变多,其步数也剧增,如下图所示:
    在这里插入图片描述
  • 嵌套循环
function hasDuplicateValue(array) {var steps = 0;for (var i = 0; i < array.length; i++) {for (var j = 0; j < array.length; j++) {steps++;if (i !== j && array[i] == array[j]) {return true;}}}console.log(steps);return false;}hasDuplicateValue([1,2,3])

嵌套循环算法的效率就是 O(N^2)。一旦看到嵌套循环,你就应该马上想到 O(N2)

改进

以下时间复杂度:其大 O 记法是 O(N)

function hasDup(array){var steps = 0;var existsNumbers = [];for (let i = 0; i < array.length; i++) {steps++;if(existsNumbers[array[i]]===undefined){existsNumbers[array[i]] = 1;}else{return true;}}console.log(steps);return false;}

执行 hasDuplicateValue([1,2,3])的话,你会看到输出为 3,跟元素个数一致。

选择排序👈

冒泡排序算法,其效率是 O(N 2)。现在我们再来探索另一种排序算法,选择排序:

步骤

(1) 从左至右检查数组的每个格子,找出值最小的那个。在此过程中,我们会用一个变量来记住检查过的数字的最小值(事实上记住的是索引,但为了看起来方便,下图就直接写出数值)。
如果一个格子中的数字比记录的最小值还要小,就把变量改成该格子的索引。
在这里插入图片描述
(2) 知道哪个格子的值最小之后,将该格与本次检查的起点交换。第 1 次检查的起点是索引 0,第2此起点时索引1
在这里插入图片描述
(3) 重复第(1) (2)步,直至数组排好序

效率

选择排序的步骤可分为两类:比较和交换,也就是在每轮检查中把未排序的值跟该轮已遇到的最小值做比较,以及将最小值与该轮起点的值交换以使其位置正确。
但每轮的交换最多只有 1 次。如果该轮的最小值已在正确位置,就无须交换,否则要做 1 次交换。相比之下,冒泡排序在最坏情况(完全逆序)时,每次比较过后都要进行 1 次交换。
在这里插入图片描述
选择排序的大 O 记法为 O(N2),跟冒泡排序一样!🙋

因为:大 O 记法不包含一般数字,除非是指数。
例如:当数据量少于某个值时,O(N2)是比 O(100N)要快的,但过了这个值之后,O(100N)便反超 O(N 2),并一直保持优势!
在这里插入图片描述

这就是大 O 记法忽略常数的原因。大 O 记法只表明,对于不同分类,存在一临界点,在这
一点之后,一类算法会快于另一类,并永远保持下去。至于这个点在哪里,大 O 并不关心。

插入排序✍

我们已经学过两种排序算法:冒泡排序和选择排序。虽然它们的效率都是 O(N 2),但其实选择排序比冒泡排序快一倍。现在来学第三种排序算法——插入排序。

在最坏的情况里,插入排序的时间复杂度跟冒泡排序、选择排序一样,都是 O(N2)

效率

插入排序包含 4 种步骤:移除、比较、平移和插入。要分析插入算法的效率,就得把每种步骤都统计一遍。
在数组完全逆序的最坏情况下,我们每一轮都要将 temp_value 左侧的所有值与temp_value 比较。因为那些值全都大于 temp_value,所以每一轮都要等到空隙移到最左端才能结束。
在第一轮,temp_value 为索引 1 的值,由于 temp_value 左侧只有一个值,所以最多进行一次比较。到了第二轮,最多进行两次比较,以此类推。到最后一轮时,就要拿 temp_value 以外的所有值与其进行比较。换言之,如果数组有 N 个元素,则最后一轮中最多进行 N - 1 次比较。
在这里插入图片描述

总结

懂得区分最好、平均、最坏情况,是为当前场景选择最优算法以及给现有算法调优以适应环
境变化的关键。记住,虽然为最坏情况做好准备十分重要,但大部分时间我们面对的是平均情况。

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

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

相关文章

闽盾杯 2021 DNS协议分析

今年CISCN的Tough DNS 的前戏就是DNS协议分析 直接可以查找到flag的base64形式Zmxh 发现就是请求的dnslog 携带的数据 过滤器就是 dns tshark -r dns.pcapng -T json -Y "dns" >1.json 字段选择 dns.qry.name tshark -r dns.pcapng -T json -Y "dns"…

内网渗透-隧道搭建ssp隧道代理工具

内网渗透-隧道搭建&ssp隧道代理工具 目录 内网渗透-隧道搭建&ssp隧道代理工具spp隧道代理工具spp工作原理图cs上线主机spp代理通信服务端配置客户端配置CS配置设置CS生成木马的监听器配置CS监听上线的监听器生成木马 spp隧道搭建服务端配置客户端配置CS配置 内网穿透&a…

根据模板和git commit自动生成日·周·月·季报

GitHub - qiaotaizi/dailyreport: 日报生成器 GitHub - yurencloud/daily: 程序员专用的日报、周报、月报、季报自动生成器&#xff01; config.json: { "Author": "gitname", "Exclude": ["update:", "add:", "…

实际测试stm32中断优先级

HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority); void HAL_NVIC_EnableIRQ(IRQn_Type IRQn); void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);第一个函数 HAL_NVIC_SetPriority 是用来设置单个优先级的抢占优先级和响应优先级的值。第二个…

恒压频比开环控制系统Matlab/Simulink仿真分析(SPWM控制方式)

介绍恒压频比的开环控制方法驱动永磁同步电机的转动&#xff0c;首先分析恒压频比的控制原理&#xff0c;然后在Matlab/Simulink中进行永磁同步电机恒压频比开环控制系统的仿真分析&#xff0c;最后将Simulink中的恒压频比控制算法生成代码加载到实际工程中进行工程实现。 一、…

丝绸之路网络安全论坛成功举办,开源网安受邀分享软件供应链安全落地经验

5月23日&#xff0c;2024第八届丝绸之路网络安全论坛在陕西宾馆会议中心成功举办&#xff0c;本次论坛由陕西省信息网络安全协会主办&#xff0c;以“汇聚万千智慧 夯实安全堤坝”为主题&#xff0c;邀请业内专家学者、企业代表、行业代表共计400余人参加。开源网安常务副总王颉…

【PostgreSQL17新特性之-冗余IS [NOT] NULL限定符的处理优化】

在执行一个带有IS NOT NULL或者NOT NULL的SQL的时候&#xff0c;通常会对表的每一行&#xff0c;都会进行检查以确保列为空/不为空&#xff0c;这是符合常理的。 但是如果本身这个列上有非空&#xff08;NOT NULL&#xff09;约束&#xff0c;再次检查就会浪费资源。甚至有时候…

Leetcode3165. 不包含相邻元素的子序列的最大和(Go中的线段树分治包含多类数据使用maintain进行维护)

题目截图 题目分析 不能取相邻的&#xff0c;就是打家劫舍 然后更改某一个值就是单点更新 更新后&#xff0c;需要更新区间的值 需要注意的是&#xff0c;使用分治时需要考虑到一头一尾的问题&#xff0c;所以有4种情况&#xff08;选or不选在两个位置&#xff09; 这四种情况…

编程入门(七)【虚拟机VMware安装Linux系统Ubuntu】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;Ubuntu知多少&#x1f680;安装的前期准备&am…

SQL—DQL之执行顺序(基础)

一、引言 1、编写顺序 2、执行顺序 介绍&#xff1a; DQL语句&#xff08;数据查询语句&#xff09; 1、首先先执行的是 FROM &#xff0c;通过 FROM 来决定我要查询的是哪一张表的数据。 2、紧接着通过 WHERE 来指定查询的条件。 3、第三步就是通过 GROUP BY 以及 HAVING 来…

中国BI步入增长大周期,腾讯云ChatBI加速AI+BI融合

过去十年&#xff0c;大数据技术的快速发展&#xff0c;让数据消费前进一大步&#xff0c;数据价值得到一定程度的挖掘与释放&#xff0c;真正开启了“用数”的大时代。但数据分析繁杂的技术栈、复杂的处理过程以及程式化的交互方式&#xff0c;让“数据消费”的门槛始终降不下…

现在的时代,您必会的“调教”AI技巧

人工智能大行其道&#xff0c;如何借势&#xff1f;始于问询。要得要得预期&#xff0c;精于“提问技巧”&#xff01; (笔记模板由python脚本于2024年05月30日 18:37:27创建&#xff0c;本篇笔记适合有独立编程基础的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#…

基于 Apache Doris 的实时/离线一体化架构,赋能中国联通 5G 全连接工厂解决方案

作者&#xff1a;田向阳&#xff0c;联通西部创新研究院 大数据专家 共创&#xff1a;SelectDB 技术团队 导读&#xff1a; 数据是 5G 全连接工厂的核心要素&#xff0c;为支持全方位的数据收集、存储、分析等工作的高效进行&#xff0c;联通 5G 全连接工厂从典型的 Lambda 架…

Presto 从提交SQL到获取结果 源码详解(3)

物理执行计划 回到SqlQueryExecution.startExecution() &#xff0c;执行计划划分以后&#xff0c; // 初始化连接&#xff0c;获取Connect 元数据&#xff0c;添加会话&#xff0c;初始ConnectId metadata.beginQuery(getSession(), plan.getConnectors()); // 构建物理执行…

AngularJS基础语法(2009版本)

jquery和AngularJS 数据绑定和获取对比&#xff1a; jquery&#xff0c;要操作DOM&#xff1a; angularJS&#xff0c;无需操作DOM就可以进行动态数据变化&#xff1a; 要使用Angularjs就需要在html页面先引入&#xff1a; ng-app&#xff1a; html页面中&#xff0c;需要给…

redis(17):什么是布隆过滤器?如何实现布隆过滤器?

1 布隆过滤器介绍 布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。它基于位数组和多个哈希函数的原理,可以高效地进行元素的查询,而且占用的空间相对较小,如下图所示: 根据 key 值计算出它的存储位置,然后将此位置标…

API测试工具领域,Postman的10个最佳替换

Postman 赢得了流行且有效的 API 工具的声誉。然而&#xff0c;对于那些寻求更符合特定需求和偏好的替代方案的人来说&#xff0c;存在一些值得注意的选择。这些 Postman 替代方案提供了独特的特性和功能&#xff0c;可满足测试过程的各个方面的需求。 在本博客中&#xff0c;…

如何快速的在线编辑pdf?6个软件让你轻松编辑pdf

如何快速的在线编辑pdf&#xff1f;6个软件让你轻松编辑pdf 在线编辑PDF文件是一项非常方便的任务&#xff0c;以下是六款让您轻松进行在线PDF编辑的软件&#xff1a; 嗨动PDF编辑器&#xff1a;这是一个功能强大的PDF编辑器&#xff0c;可以帮助您快速编辑PDF文档&#xff…

封装了一个iOS对号成功动画

基本思路其实很简单&#xff0c;就是通过贝塞尔曲线画出路径&#xff0c;然后 使用CAShapeLayer 渲染路径&#xff0c;然后通过strokeEnd 动画实现 路径的效果&#xff0c;这里注意&#xff0c;这个过程中过遇到过一个问题&#xff0c;就是 对号动画完成之后&#xff0c;整个对…

Superset二次开发之更新 SECRET_KEY

SECRET_KEY 的作用 加密和签名:SECRET_KEY用于对敏感数据(如会话、cookie、CSRF令牌)进行加密和签名,防止数据被篡改。安全性:确保应用的安全性,防止跨站请求伪造(CSRF)攻击和会话劫持等安全问题。如何生成 SECRET_KEY openssl rand -base64 42 配置 SECRET_KEY 在sup…