每日一算-选择排序算法

news2024/12/27 13:53:44

大家好,我是易安!

今天我们开始每日一算的篇章,今天带来的是选择算法。

选择排序是一种简单而高效的排序算法,它通过从列表的未排序部分中重复选择最小(或最大)元素并将其移动到列表的已排序部分来工作。该算法反复从列表的未排序部分中选择最小(或最大)的元素,并将其与未排序部分的第一个元素交换。对列表中剩余的未排序部分重复此过程,直到整个列表排序完毕。选择排序的一种变体称为“双向选择排序”,它通过在最小元素和最大元素之间交替遍历元素列表,这种方式在某些情况下可以更快。

alt

选择排序算法

该算法在给定数组中维护两个子数组。

  • 已经排序的子数组。
  • 剩余的子数组未排序。

在选择排序的每次迭代中,从未排序的子数组中选取最小元素(考虑升序)并将其移动到已排序子数组的开头。

每次迭代后,已排序的子数组大小增加一,未排序的子数组大小减少一。

在 N(数组的大小)次迭代之后,我们将得到一个排序的数组。

选择排序流程图:

alt

选择排序原理?

让我们以下面的数组为例:arr[] = {64, 25, 12, 22, 11}

第一步:

  • 对于排序数组中的第一个位置,整个数组从索引 0 到 4 依次遍历。 当前存放64的第一个位置,遍历整个数组后显然 11是最低值。
6425122211
  • 因此,将 64 替换为11。经过一次迭代后,恰好是数组中最小值的 11 往往会出现在排序列表的第一个位置。
1125122264

第二步:

  • 对于存在 25 的第二个位置,再次按顺序遍历数组的其余部分。
1125122264
  • 遍历后发现 12是数组中倒数第二的值,应该出现在数组的第二位,因此交换这些值。
1112252264

第三步:

  • 现在,对于第三位,再次出现 25 的地方遍历数组的其余部分并找到数组中第三小的值。
1112252264
  • 遍历时, 22是第三小的值,它应该出现在数组的第三位,因此将 22与第三位的元素交换。
1112222564

第四步:

  • 同样,对于第四个位置,遍历数组的其余部分,找到数组中第四小的元素
  • 由于 25是第四低的值,因此它将排在第四位。
1112222564

第五步:

  • 最后,数组中存在的最大值自动放置在数组的最后一个位置
  • 结果数组是排序后的数组。
1112222564

实战演练

请按照以下步骤实现代码:

  • 将最小值 ( min_idx ) 初始化为位置 0。
  • 遍历数组,找到数组中的最小元素。
  • 在遍历时,如果找到任何小于 min_idx 的元素,则交换两个值。
  • 然后,递增 min_idx以指向下一个元素。
  • 重复直到数组被排序。

下面是上述方法的实现:

  • java版本
import java.io.*;
public class SelectionSort
{
 void sort(int arr[])
 {
  int n = arr.length;

  // 逐步移动未排序数组的边界
  for (int i = 0; i < n-1; i++)
  {
   //查找未排序数组中的最小元素
   int min_idx = i;
   for (int j = i+1; j < n; j++)
    if (arr[j] < arr[min_idx])
     min_idx = j;

   // 将找到的最小元素与第一个元素进行交换
   int temp = arr[min_idx];
   arr[min_idx] = arr[i];
   arr[i] = temp;
  }
 }

 // 打印排序后的数组结果
 void printArray(int arr[])
 {
  int n = arr.length;
  for (int i=0; i<n; ++i)
   System.out.print(arr[i]+" ");
  System.out.println();
 }


 public static void main(String args[])
 {
  SelectionSort ob = new SelectionSort();
  int arr[] = {64,25,12,22,11};
  ob.sort(arr);
  System.out.println("Sorted array");
  ob.printArray(arr);
 }
}

输出

排序数组:
11 12 22 25 64

选择排序的复杂度分析:

时间复杂度:选择排序的时间复杂度为 O(N 2 ),因为有两个嵌套循环:

  • 一个循环一个一个地选择Array的一个元素= O(N)
  • 将该元素与每个其他数组元素进行比较的另一个循环 = O(N)

因此整体复杂度 = O(N) * O(N) = O(N*N) = O(N 2 )

辅助空间: O(1) 作为唯一使用的额外内存用于临时变量,同时交换数组中的两个值。选择排序永远不会进行超过 O(N) 次交换,并且在内存写入是一项代价高昂的操作时非常有用。

选择排序算法是否稳定?

稳定性:默认实现不稳定。然而,它可以变得稳定。这个后续再讲。

选择排序算法的优点:

  • 简单易懂。
  • 保留具有相同键的项目的相对顺序,这意味着它是稳定的。
  • 适用于小型数据集。
  • 它适用于各种类型的数据类型。
  • 选择排序是一种就地排序算法,这意味着它不需要任何额外的内存来对列表进行排序。
  • 它具有 O(n^2) 的最佳情况和平均情况时间复杂度,使其对于小型数据集非常有效。
  • 很容易修改为按升序或降序排序。
  • 它可以很容易地在硬件中实现,使其适用于实时应用。
  • 它也可以用作更有效的排序算法中的子程序。
  • 它不需要任何特殊的内存或辅助数据结构,使其成为轻量级解决方案。
  • 该算法可以轻松并行,允许在多核处理器上进行高效排序。
  • 它可以在有限的内存环境中使用,因为它需要最少的额外内存。
  • 它易于理解,使其成为教学目的的热门选择。
  • 它适用于对唯一键很少的数据进行排序,因为它在这种情况下表现良好。

选择排序算法的缺点:

  • 选择排序在最坏和平均情况下的时间复杂度为 O(n^2)。
  • 在大型数据集上效果不佳。
  • 选择排序算法需要多次迭代列表,因此会导致不平衡分支。
  • 选择排序的缓存性能很差,因此对缓存不友好。
  • 不是自适应的,这意味着它没有利用列表可能已经排序或部分排序的事实
  • 对于具有慢速随机存取存储器 (RAM) 的大型数据集来说不是一个好的选择
  • 它不是比较排序,也没有像合并排序或快速排序那样的任何性能保证。
  • 它的缓存性能很差
  • 由于其高分支预测错误率,它可能导致分支预测不佳
  • 它有很多写操作,导致在存储速度慢的系统上性能不佳。
  • 它不是可并行算法,这意味着它不能轻易拆分以在多个处理器或内核上运行。
  • 它不能很好地处理具有许多重复项的数据,因为它会进行许多不必要的交换。
  • 在大多数情况下,它可以被其他算法(如快速排序和堆排序)超越。

总结:

  • 选择排序是一种简单易懂的排序算法,其工作原理是从列表的未排序部分重复选择最小(或最大)的元素并将其移动到列表的已排序部分。
  • 对列表中剩余的未排序部分重复此过程,直到整个列表排序完毕。
  • 在最坏和平均情况下,它的时间复杂度为 O(n^2),这使得它对于大型数据集的效率较低。
  • 选择排序是一种稳定的排序算法。
  • 它可用于对不同类型的数据进行排序。
  • 它在特定应用程序中很有用,例如小型数据集和内存受限系统。

本文由 mdnice 多平台发布

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

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

相关文章

Kubernetes集群安全加固

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130678814 一、系统账户加固 1、对账户的登录次数进行检查&#xff0c;连续超过3次登录失败后&#xff0c;对用户锁定150s # 每个设备上都运行 sed -i~ 2iauth required pam_faillock.so deny3 unloc…

玩转Google开源C++单元测试框架Google Test系列(gtest)之五 - 死亡测试

一、前言 “死亡测试”名字比较恐怖&#xff0c;这里的“死亡”指的的是程序的崩溃。通常在测试过程中&#xff0c;我们需要考虑各种各样的输入&#xff0c;有的输入可能直接导致程序崩溃&#xff0c;这时我们就需要检查程序是否按照预期的方式挂掉&#xff0c;这也就是所谓的…

CBFS Shell .NET 22.0.85 Crack

使用虚拟文件夹、自定义菜单、工具栏、详细信息列等扩展和自定义 Windows 资源管理器&#xff01; CBFS Shell 窗口资源管理器自定义 使用 CBFS Shell 为您的用户扩展 Windows 资源管理器。定义用户如何与文件和文件夹交互、自定义上下文菜单、添加信息列等。与可能导致资源管…

详细解释什么是LNMP架构

LNMP(Linux-Nginx-MySQL-PHP)是一种常见的Web服务器架构&#xff0c;适用于中小型网站和应用。 它包括四个核心组件&#xff1a; 1. Linux:LNMP架构是在Linux操作系统上运行的。通常选择Ubuntu、Debian等基于Debian的发行版作为Linux系统。 2. Nginx:Nginx是一个高性能的Web服…

支付系统设计三:支付网关设计09-总结

文章目录 前言一、设计目标二、设计实现1. 开发框架2. 配置管理后台3. 屏蔽渠道差异4. 各阶段工作内容4.1 业务处理前期准备阶段4.2 业务处理阶段4.2.1 交易处理模板获取4.2.2 参数验证4.2.3 幂等性验证4.2.4 交易数据准备服务获取4.2.5 路由处理4.2.6 支付渠道数据补全4.2.7 交…

Docker高级(完结)

一、DockerFile DockerFile简介 Docker是用来构建Docker镜像文件&#xff0c;由一条条docker指令和参数构成的脚本。 DockerFile构建过程 小总结 从应用软件的角度来看&#xff0c;Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段&#xff0c; Dockerfile是…

浅析垃圾回收

大家好&#xff0c;我是易安&#xff01; Java虚拟机的自动内存管理&#xff0c;将原本需要由开发人员手动回收的内存&#xff0c;交给垃圾回收器来自动回收。不过既然是自动机制&#xff0c;肯定没法做到像手动回收那般精准高效 &#xff0c;而且还会带来不少与垃圾回收实现相…

《MongoDB入门教程》 - MongoDB基础介绍

前言 时间也过太快了嘛&#xff0c;一晃上次更新都又过去6个月了&#xff0c;再不更新就变成年更博客了。 对了&#xff0c;第一次疫情也过去了&#xff0c;最近开始二阳了&#xff0c;希望大家能继续挺过去吧 本篇文章初尝试使用ChatGPT进行&#xff0c;博主主要负责排版和总…

mysql使用xtrabackup方式复制过滤某一个数据库

需求&#xff1a; 搭建一个新的从库&#xff0c;只复制过滤源端数据库里的其中一个数据库workflow到新实例上。 一 操作步骤 1.1 在目标端新建一个数据库实例 略 1.2 在源端做备份 /home/urman-agent/bin/xtrabackup --defaults-file/data/mysql/etc/13314/my.cnf --targ…

redis缓存穿透、缓存击穿、缓存雪崩

一、缓存 缓存是数据交换的缓冲区&#xff0c;是存储数据的临时地方&#xff0c;一般读写性能较高。 如浏览器会把静态资源先加载到浏览器缓存中&#xff0c;tomcat中有应用层缓存等&#xff0c;则数据库也有数据库缓存。 缓存的作用&#xff1a; 降低后端负载提高读写效率…

ES8基本命令

ElasticSearch是面向文档型数据库 构造类似于数据库&#xff1a;indexes(索引库数据库)-->types(类型表)-->documents(文档行)-->field(字段字段) 但是在7.X开始&#xff0c;Type已经开始被废弃。 正排索引&#xff1a;根据主键id关联内容&#xff0c;然后再找关键字…

微服务—Redis实用篇-黑马头条项目-达人探店功能(使用set与zset实现)

微服务—Redis实用篇-黑马头条项目-达人探店功能(使用set与zset实现) 1、达人探店 1.1、达人探店-发布探店笔记 发布探店笔记 探店笔记类似点评网站的评价&#xff0c;往往是图文结合。对应的表有两个&#xff1a; tb_blog&#xff1a;探店笔记表&#xff0c;包含笔记中的标…

Liunx基础命令 - mkdir命令

mkdir命令 – 创建目录文件 mkdir命令来自英文词组”make directories“的缩写&#xff0c;其功能是用来创建目录文件。使用方法简单&#xff0c;但需要注意若要创建的目标目录已经存在&#xff0c;则会提示已存在而不继续创建&#xff0c;不覆盖已有文件。而目录不存在&#…

路径规划算法:基于蜉蝣优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于蜉蝣优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蜉蝣优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法蜉蝣…

Linux 无网环境下离线安装rpm

概述 搭建了私有yum仓库&#xff0c;想实现无网环境下Docker rpm离线安装的方法 1. 使用和配置清华源 2. 免安装下载rpm包及其依赖 3. 寻找特定的rpm包并补全依赖 清华的清华源 名称连接帮助文档备注主页清华大学开源软件镜像站 | Tsinghua Open Source MirrorAOSP | 镜像站使…

Swagger 3.0 与 Springboot 集成

springboot版本:2.3.12.RELEASE swagger版本:3.0.0 1&#xff1a;pom文件添加如下代码: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version>&…

离线安装 Docker + Docker registry(Docker仓库)

概述 通过私有yum仓库安装docker 具体内容&#xff1a; 1. 构建私有镜像仓库 2. 准备rpm包 3. 安装部署 4. ansible 安装 卸载 5. shell 脚本安装 卸载 6. 网页连接 7. 构建docker 私有仓库 1. 构建私有镜像仓库 构建简单的yum私有仓库请参考如下文档 http://t.csdn.cn/22bmb…

用chatGPT写chatGPT教学方案

最近从机器学习的原理、数学推理、主流模型架构、chatGPT的Prompt策略&#xff0c;也实际体验了各种AIGC工具&#xff0c;算是较为系统的学习了chatGPT的前世今身&#xff0c;想着有很多人应该跟我一样&#xff0c;没有编程基础、也没有成为chatGPT专家的希望&#xff0c;仅仅通…

LeetCode_Day3 | 反转链表/移除链表的元素/设计个链表

LeetCode_链表 203.移除链表元素1. 题目描述2. 直接使用原表删除1. 思路2. 代码实现 3. 使用虚拟头节点删除1. 思路2. 代码实现 707.设计链表1.题目描述2.单链表&#xff1a;虚拟头节点设计1. 思路2. 代码实现及部分逻辑解释3. 需要注意的点 206.反转链表1.题目描述2. 双指针法…

BIO阻塞模型

作者&#xff1a;V7 博客&#xff1a;https://www.jvmstack.cn 一碗鸡汤 少年辛苦终身事&#xff0c;莫向光阴惰寸功。 —— 杜荀鹤 同步阻塞IO 在介绍阻塞和非阻塞之前先说明一下同步和异步。我们可以将同步和异步看做是发起IO请求的两种方式。同步IO指的是用户空间&…