选择排序(Selection Sort)

选择排序是一种简单直观的排序算法,其工作原理是通过n-1趟直接选择找到最小(大)元素并交换。尽管其时间复杂度为O(n^2),但它不需要额外的内存空间。文章详细介绍了选择排序的算法描述、动图演示、代码实现、算法分析以及代码思路讲解,强调了其不稳定性,并与冒泡排序进行了对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

选择排序(Selection Sort)

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

算法描述

n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:

  • 初始状态:无序区为R[1…n],有序区为空;
  • 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1…i-1]和R(i…n)。该趟排序从当前无序区中-选出关键字最小的记录
    R[k],将它与无序区的第1个记录R交换,使R[1…i]和R[i+1…n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;

n-1趟结束,数组有序化了。

动图演示

在这里插入图片描述

代码实现

public static void selectionSort(int[] array){
        int len=array.length;
        int minIndex;
        for (int i = 0; i < len-1; i++) {
            minIndex=i;
            for (int j = i+1; j < len; j++) {
                if(array[j]<array[minIndex]){
                    minIndex=j;
                }
            }
            if(minIndex!=i){
               int temp=array[minIndex];
               array[minIndex]=array[i];
               array[i]=temp;
            }
        }
    }

算法分析

表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

代码思路讲解

冒泡排序可以说是十大排序算的鼻祖,几乎后面所有的排序算法都是基于冒泡排序一步步改进,所做的优化。选择排序也不例外。

这就要从冒泡排序的缺点说起:冒泡通过从头遍历,比较相邻元素,满足条件则换位的方式实现排序。
每次比较,一旦满足左>右则立刻发生换位操作。这样一轮下来,最坏可能要换位length-1次

而选择排序采用标记,延迟换位。减少了算法排序中的元素换位操作次数。提升算法效率
  1. 首先,选择排序也是两两比较排序。每轮选出一个该轮的最小数,追加到左侧有序部分的尾部。所以对于长度为n的数组,需要排序n-1轮
  2. 由于每轮会得出一个最小数,将其与该轮用来比较的元素换位(从宏观上只关注左侧有序序列构建方式来看,好比每轮往左侧有序列表的尾部追加元素一样),下一轮待排序元素便从上一轮用来比较的元素下标+1开始。也就是内层循环的j=i+1开始到数组的最后一个元素。
  3. 我们先定义一个minIndex变量,用来存储每一轮排序得出的最小值下标。
  4. 待该轮遍历比较结束,判断minIndex最小值下标和用来做比较的元素下标是否一致。不一致则换位,否则不换位(一致说明用来比较的元素是该轮的最小值,不用动。然后指针右移)。
  5. 这样每一轮依照这种方式,进行比较,延迟换位排序实现对无列表的排序。

注意:
选择排序是不稳定排序。为什么这么说呢?假设有一个数组`array={1,2,5,5,3}
这里省略具体排序细节
1.第一轮排序,用1和右侧所有元素比较,1最小,不换位array={1,2,5,5,3}
2.第二轮排序,用2和2后面的所有元素比较,2最小,不换位array={1,2,5,5,3}
3.第三轮排序,用第三个5和其后面元素比较,3最小,换位array={1,2,3,5,5}
4.注意,本来在下标2位置的5和元素3(下标4)换位后,被移动到了数组末尾。而这个5和下标3位置的5大小相等。原本在下标4位置的5的前面,换位后被移动到了后面
5.第四轮,用下标3位置的5和最后一个元素5比较,相等,不换位。得出数组array={1,2,3,5,5}

在这个过程中原本在前面的5,在排序结束后被移动到了同为5的另一个元素后面。实际中,对于基本类型这点倒不会引发问题。但对于引用类型,比如我们使用选择排序对一个对象列表,据其元素的某一个字段name,进行排序(除name外其他属性字段值不同)。会发现得出的列表。相同name值得元素a,b
有时a在前,有时b在前。所以当我们对引用类型序列进行排序并着重关注其顺序时,不稳定排序则不适用。应选用稳定排序

总结

其实,可以看出。上节所讲的冒泡排序和本章的选择排序都可看做:通过遍历一个待排序无序序列,通过比较换位,来在序列的一段构建有序序列的方式来实现排序。关于冒泡排序,之前只示例了一个最简单的优化排序算法,还有很多比如如鸡尾酒排序(使用分治法进行双向冒泡排序)等等,有很多基于经典算法衍生出来的优化算法,名字千奇百怪。后续我也会陆续更新和完善。

文章有任何语言表达不当,或者讲解枯燥晦涩的地方也望有缘的读者可以提出。本人将不胜感激,并努力修正。

关于算法的理论和动图资料借鉴https://www.cnblogs.com/onepixel/articles/7674659.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值