当前位置: 首页 > news >正文

选择排序专栏

选择排序是最基础也最容易理解的排序算法之一,它的核心思想简单直接,非常适合排序算法的入门学习。本文将从原理、实现、特性到优化,全面解析选择排序算法。

一、选择排序的核心思想

选择排序的工作原理就像它的名字一样 ——"选择":在未排序的元素中找到最小(或最大)的那个元素,然后将它与未排序部分的第一个元素交换位置。重复这个过程,直到所有元素都被排序。

形象地说,就好像你在整理一手扑克牌:每次从剩余的牌中挑出最小的一张,按顺序放在左手边,直到所有牌都被挑完。

排序过程分解

以数组 [5, 2, 4, 6, 1, 3] 为例,升序排序过程如下:

  1. 初始状态:[5, 2, 4, 6, 1, 3](全部未排序)
  2. 第 1 轮:找到最小值 1,与第一个元素 5 交换 → [1, 2, 4, 6, 5, 3]
  3. 第 2 轮:从剩余元素中找到最小值 2,位置不变 → [1, 2, 4, 6, 5, 3]
  4. 第 3 轮:找到最小值 3,与 4 交换 → [1, 2, 3, 6, 5, 4]
  5. 第 4 轮:找到最小值 4,与 6 交换 → [1, 2, 3, 4, 5, 6]
  6. 第 5 轮:剩余元素已有序,排序完成

二、Java 实现选择排序

下面是选择排序的 Java 实现代码,包含详细注释:

public class Selection {public static void main(String[] args) {Integer[] a = {1,9,6,7,66,11,326,98};sort(a);System.out.println(Arrays.toString(a));}public static void sort(Comparable[] a){//定义i为首个数据for (int i = 0; i < a.length-1; i++) {//定义最小值为minint min = i;//for (int j = i+1; j < a.length; j++) {if(greater(a[min],a[j])){min = j;}}//得到最小的放到最前面exchange(a,i,min);}}//比较v是否大于n;public static boolean greater(Comparable v,Comparable n){//调用comparable的方法//v大于n是返回 1,//v等于n时返回 0,//v小时n时返回 -1int i = v.compareTo(n);return i==1;}//交换方法public static void exchange(Comparable[] a,int i,int j){Comparable temp = a[i];a[i] = a[j];a[j] = temp;}}

代码解析

上面的实现包含三个主要部分:

  1. sort 方法:核心排序逻辑

    • 外层循环控制需要排序的元素范围
    • 内层循环在未排序部分中寻找最小值
    • 找到最小值后与未排序部分的第一个元素交换
  2. main 方法:测试排序算法,包含测试用例

  3. exchange方法:传入对象,实现位置的交换

  4. greater方法:实现数据比较

三、选择排序的特性分析

    选择排序的时间复杂度主要由比较操作交换操作两部分构成,其中比较操作占主导地位。

    时间复杂度分析

    对于长度为 n 的数组,选择排序的执行过程如下:

    • 第 1 轮:需要比较 n-1 次(在 n 个元素中找最小值)
    • 第 2 轮:需要比较 n-2 次(在 n-1 个元素中找最小值)
    • ...
    • 第 n-1 轮:需要比较 1 次

    总比较次数为:(n-1) + (n-2) + ... + 1 = n(n-1)/2,这是一个关于 n 的二次函数。

    时间复杂度情况

    • 最好情况:O (n²) - 即使数组已经有序,仍需完整遍历寻找最小值
    • 最坏情况:O (n²) - 数组完全逆序时
    • 平均情况:O(n²)

    选择排序的时间复杂度不受输入数据的有序程度影响,这是它与冒泡排序、插入排序的重要区别。

    因为不管你有没有序,我都要比较。

    空间复杂度分析

    选择排序的空间特性非常优秀:

    • 它只需要几个额外的变量(如用于记录最小值索引的 minIndex 和交换用的临时变量 temp
    • 排序过程在原数组上进行,不需要额外的数组或数据结构

    因此,选择排序的空间复杂度为 O (1),属于原地排序(In-place Sorting) 算法。

    稳定性

    选择排序是不稳定的排序算法。

    例如,对于数组 [2, 2, 1],排序后第一个 2 会被交换到最后,导致两个 2 的相对顺序改变。

    交换次数

    选择排序的交换次数很少,最多为 n-1 次(每轮最多交换一次),这是它相比冒泡排序的一个优势。

    四、选择排序的优化思路

    基础的选择排序每次只寻找一个最小值,我们可以优化为双向选择排序,同时寻找最小值和最大值:

    双向选择排序的Java实现

    public class Selection {public static void main(String[] args) {Integer[] a = {1,9,6,7,66,11,326,98};sort(a);System.out.println(Arrays.toString(a));}public static void sort(Comparable[] a){int left = 0;int right = a.length - 1;while (left < right) {int minIndex = left;int maxIndex = right;// 在未排序部分中同时找出最小值和最大值的索引for (int i = left; i <= right; i++) {if (greater(a[minIndex], a[i])) {minIndex = i;}if (greater(a[i], a[maxIndex])) {maxIndex = i;}}// 处理最小值if (minIndex != left) {exchange(a, minIndex, left);// 如果最大值在 left 位置,交换后最大值位置变为 minIndexif (maxIndex == left) {maxIndex = minIndex;}}// 处理最大值if (maxIndex != right) {exchange(a, maxIndex, right);}// 缩小未排序部分的范围left++;right--;}}// 比较v是否大于n;public static boolean greater(Comparable v, Comparable n){// 调用comparable的方法// v大于n时返回 1,// v等于n时返回 0,// v小于n时返回 -1int i = v.compareTo(n);return i > 0;}// 交换方法public static void exchange(Comparable[] a, int i, int j){Comparable temp = a[i];a[i] = a[j];a[j] = temp;}
    }

    双向选择排序的优势是将外层循环的次数减少了一半,虽然时间复杂度仍然是 O (n²),但实际运行效率有所提升。

    五、选择排序的适用场景

    选择排序虽然时间复杂度较高,但也有其适用场景:

    1. 数据量较小的情况:对于 n≤1000 的小规模数据,选择排序简单有效
    2. 内存空间有限的场景:原地排序特性使其适合内存受限环境
    3. 交换成本较高的场景:相比冒泡排序,选择排序的交换次数少得多

    在实际开发中,Java 标准库中的排序算法(如 Arrays.sort ())在不同场景下会使用不同的排序策略,但对于理解排序算法的基本思想,选择排序是一个很好的起点。

    总结

    选择排序是一种简单直观的排序算法,其核心思想是 "选择最小(大)元素,放到正确位置"。虽然时间复杂度为 O (n²),不适合大规模数据排序,但它实现简单、空间复杂度低、交换次数少的特点,使其在特定场景下仍有应用价值。

    http://www.dtcms.com/a/328693.html

    相关文章:

  • Docker安装influxdb以及python基本操作
  • 传输层协议 TCP(1)
  • latex 中将新的一个section重新从1开始排序,而不是和前面的section继续排序
  • 更改webpack默认配置项
  • 第二十二天:指针与内存
  • 【C++详解】用红黑树封装模拟实现mymap、myset
  • 代码随想录刷题Day30
  • UnityWeb打包注意事项及与网页端通信
  • 初识c语言————排序方法
  • 【游戏开发记录】一款网游+修仙为背景的游戏
  • 美国英语 8 You‘re Going to Be Fine 早日康复
  • Dify 从入门到精通(第 32/100 篇):Dify 的日志分析与监控
  • 1688跨境寻源通API接入||跨境寻源通有哪些具体的功能和优势?
  • 反射的详解
  • CAP理论深度解析与工程实践指南
  • USB基础 -- USB2.0设备插入的过程
  • 陕西西安一家IPO四年亏损近25亿负债率攀升,控制权稳定性遭质疑
  • 力扣121:买卖股票的最佳时机
  • 100、【OS】【Nuttx】【构建】cmake 配置保存
  • Xsens惯性动作捕捉系统
  • 数据库事务隔离:详解及Java面试题
  • MyBatis-Plus 分页失效问题解析:@Param 注解的影响与解决方案
  • amis表单较验
  • Datawhale AI夏令营第三期多模态RAG方向 Task3
  • AAAI论文速递 | NEST:超图小世界网络让自动驾驶轨迹预测更精准
  • 基于R语言的现代贝叶斯统计学方法(贝叶斯参数估计、贝叶斯回归、贝叶斯计算实践过程
  • 从聚合到透视:SQL 窗口函数的系统解读
  • 谷歌、facebook、tiktok广告账户多开怎么安全?亚马逊、ebay、shopee多店铺怎么做好?看看adspower工具,注册免费试用及实用技巧分享
  • SQL详细语法教程(一)--数据定义语言(DDL)
  • 基于R语言的现代贝叶斯统计学方法(贝叶斯参数估计、贝叶斯回归、贝叶斯计算)实践