数据结构与算法-排序(二)选择排序(Selection Sort)
摘要
选择排序的逻辑是先遍历比较出序列中最大的,然后把最大的放在最后位置。
遵循这个逻辑,用代码实现时,做到1.减少比较次数之外,这里引入一个新的指标 - 稳定性,2.保证排序过程中的稳定性也是一个优化处理
代码逻辑
- 从头遍历序列,分别和尾部元素比较,记录最大的元素坐标
- 遍历完成后,和尾部位置交换位置
- 忽略尾部已经交换的元素,执行 1 和 2 步骤
实现
依据逻辑来看,最大值是放在尾部,并放置后,下次循环排除这个放置最大值的位置,for 循环从尾部开始最合适。
小循环开始前,需要先创建变量记录最大值坐标,这里使用的是 0 位置坐标,那么小循环开始时,就可以直接从 1 位置遍历,这就减少比较次数。
for (int end = array.length-1; end > 0; end--) {
int maxIndex = 0;
for (int begin = 1; begin <= end; begin++) {
if (cmp(maxIndex, begin) < 0) {
maxIndex = begin;
}
}
swap(maxIndex, end);
}
进阶
开始前,先解释一下稳定性,稳定性是尽量保持序列中两个元素在排序前和排序后的相对位置。比如下面伪代码:
// a1 与 a2 的值相等
a1 = a2 = 3
// 序列中 a1 值的位置在 a2 前面
array = [5, a1, 4, a2, 2]
// 排序之后, a1 值位置在 a2 前面,保持了稳定性
array = [2, a1, a2, 4, 5]
为什么稳定性重要?
序列中需要保证多次排序后数据位置的相对稳定。比如信息表中,以 age 从小到大排序,不希望 age 相等的一组数据中,它的名称在每一次排序之后都会有不同的顺序。
稳定性的优化
这里为了保证排序之后的稳定性,就当出现最大值时,也更新最大值的坐标。
为什么这样就可以保证稳定性?
首先最大值被交换到尾部之后,下次遍历比较的时候,就不再比较这个位置,小循环的比较是从头开始的,如果出现等于最大值时,不更新最大值的位置,排序之后,相等的值,最靠前的值就被放在了最后面,改变了之前序列中相等值的相对位置。
for (int end = array.length-1; end > 0; end--) {
int maxIndex = 0;
for (int begin = 1; begin <= end; begin++) {
if (cmp(maxIndex, begin) <= 0) { // 保证稳定性
maxIndex = begin;
}
}
swap(maxIndex, end);
}
时间和空间复杂度
- 最好、平均、最坏时间复杂度:O(n^2),n 的 2 次方
- 空间复杂度:O(1)
- 属于稳定排序
数据结构与算法-排序(二)选择排序(Selection Sort)的更多相关文章
- 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- 数据结构和算法(Golang实现)(25)排序算法-快速排序
快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- 数据结构和算法(Golang实现)(21)排序算法-插入排序
插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序
优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...
- 数据结构与算法(1)----->排序
这一版块,把必备的数据结构和算法做一个总结!包括排序.队列.链表.二叉树.排组合,动态规划....... 总结的过程包括理论部分,练题目可以自己去leetcode/牛客网刷起来- 第一篇文章讲排序- ...
- 排序算法系列:选择排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)
在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 我总结一个清晰不罗嗦版: 原理: 从数组头元素索引i开始,寻找后面最小的值(比i位 ...
随机推荐
- 【NX二次开发】 删除面操作
录制修改封装删除面 DeleteFaces 1 #include <uf_defs.h> 2 #include <NXOpen/NXException.hxx> 3 #incl ...
- spring赌上未来的一击:WebFlux性能实测
最近花了一点时间系统的测试验证了在SpringBoot框架下使用SpringMVC和Spring WebFlux两种框架开发接口,对比了响应时间以及压测吞吐量的区别. WebFlux&Spri ...
- Java JDK 动态代理(AOP)使用及实现原理分析
一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式U ...
- docker入门详解
这可能是最为详细的Docker总结 Docker是什么? 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是十分普遍的,甚至成为了一些企 ...
- 使用axios模拟表单提交
1.需求背景 最近在实验室写一个Spring前后端分离的项目,项目中使用Spring Security组件实现系统的认证和授权,当Security的认证模式设置为FormLogin时(如下代码),前端 ...
- Docker与k8s的恩怨情仇(三)—后浪Docker来势汹汹
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 上一节我们为大家介绍了Cloud Foundry等最初的PaaS平台如何解决容器问题,本文将为大家展示Doc ...
- jwt-在asp.net core中的使用jwt
JWT学习文章: 第一篇:JWT原理 第二篇:JWT原理实现代码 第三篇:在asp.net core中的使用JWT 前两篇文章中我写了jwt的原理,并且也用原理实现了jwt的验证.如果要看前两篇文章, ...
- testt
一级标题 二级标题 三级标题 四级标题 l 1
- .net获取项目根目录方法集合
这篇文章是别的博客复下来,收藏的: 编写程序的时候,经常需要用的项目根目录.自己总结如下 1.取得控制台应用程序的根目录方法 方法1.Environment.CurrentDirectory ...
- keycloak~自定义rest接口
rest资源 对于我们集成keycloak来说,你可能会遇到它没有实现的功能,这时需要对kc进行扩展,资源的扩展是其中一个方面,它需要实现RealmResourceProvider和RealmReso ...