选择排序(Selection Sort)

举报
林太白 发表于 2025/11/12 17:12:18 2025/11/12
【摘要】 选择排序(Selection Sort)

选择排序(Selection Sort)

认识

选择排序基本思想是

  • 首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置。
  • 接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。
  • 以此类推,直到所有元素均排序完毕。

分类:属于选择排序类,是原地排序算法

稳定性:不稳定排序算法(相等元素的相对位置可能改变)

时间复杂度:

  • 最坏情况:O(n²)
  • 最好情况:O(n²)
  • 平均情况:O(n²)

空间复杂度:

O(1),只需要常数级别的额外空间

特点:

交换次数少,每次只交换一次

比较次数多,无论数组初始状态如何

不适合大规模数据排序

选择排序的原理

选择排序的工作过程可以分为以下步骤:

  1. 将数组分为已排序区和未排序区,初始时已排序区为空
  2. 在未排序区中找到最小(或最大)的元素
  3. 将这个元素与未排序区的第一个元素交换位置
  4. 将已排序区的范围扩大一个元素
  5. 重复步骤2-4,直到整个数组排序完成

适用场景

选择排序适用于以下场景:

  1. 小规模数据排序
  2. 内存受限的环境(空间复杂度低)
  3. 对交换操作有较高成本的情况(交换次数少)
  4. 对算法简单性要求高的情况

选择排序的优缺点

优点:

  1. 实现简单,容易理解
  2. 空间复杂度低,只需要O(1)的额外空间
  3. 交换次数少,每次排序只交换一次
  4. 不受数据初始顺序影响,时间复杂度始终是O(n²)

缺点:

  1. 时间复杂度高,不适合大规模数据
  2. 不稳定排序,相等元素的相对位置可能改变
  3. 即使数组已经有序,仍然需要进行O(n²)的比较

实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>选择排序</title>
</head>

<body>
    <script>
    // 解法1 选择排序
    const optimizedSelectionSort = (arr) => {
        const n = arr.length;

         // 外层循环控制排序轮数
        for(let i=0;i<n-1;i++){
            // 假设当前未排序区的第一个元素是最小的
            let minIndex = i;

            // 内层循环在未排序区找最小元素的索引
            for(let j=i+1;j<n;j++){
                if(arr[j]<arr[minIndex]){
                    minIndex=j;
                }
            }
            // 如果找到的最小元素不是当前位置,则交换
            if(minIndex!==i){
                [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
            }
        }
        return arr;
    };
    // 示例使用
    const arr = [38, 27, 43, 3, 9, 82, 10];
    console.log("原始数组:", arr);
    console.log("排序后数组:", optimizedSelectionSort(arr));
    </script>
</body>

</html>

优化-双向选择排序,减少比较次数

// 1 优化 -双向选择排序,减少比较次数
    const optimizedSelectionSort = (arr) => {
        const n = arr.length;
        let left = 0;
        let right = n - 1;
        while(left < right){
            let minIndex = left;
            let maxIndex = left;  
             // 优化内层循环,减少比较次数
            for (let i = left + 1; i <= right; i++) {
                // 一次比较同时更新最小和最大值
                if (arr[i] < arr[minIndex]) {
                    minIndex = i;
                } else if (arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }
            // 交换最小值到左端
            if (minIndex !== left) {
                [arr[left], arr[minIndex]] = [arr[minIndex], arr[left]];
                // 如果最大值原本在left位置,已经被交换到minIndex位置
                if (maxIndex === left) {
                    maxIndex = minIndex;
                }
            }
            // 交换最大值到右端
            if (maxIndex !== right) {
                [arr[right], arr[maxIndex]] = [arr[maxIndex], arr[right]];
            }
            left++;
            right--;
            return arr;
        }
    };

添加提前终止条件

在排序的过程之中,有时候我们会遇到后面已经排序的情况,就可以避免重复比对,这个时候可以提前添加终止条件

// 2 添加提前终止条件
    function optimizedSelectionSort(arr) {
        const n = arr.length;

        let left = 0;
        let right = n - 1;

        while (left < right) {
            let minIndex = left;
            let maxIndex = left;
            let isSorted = true; // 添加标记,假设已排序

            for (let i = left + 1; i <= right; i++) {
                // 如果发现逆序对,标记为未排序
                if (arr[i] < arr[i - 1]) {
                    isSorted = false;
                }

                if (arr[i] < arr[minIndex]) {
                    minIndex = i;
                } else if (arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }

            // 如果已经有序,提前终止
            if (isSorted) {
                break;
            }

            // 交换最小值到左端
            if (minIndex !== left) {
                [arr[left], arr[minIndex]] = [arr[minIndex], arr[left]];

                if (maxIndex === left) {
                    maxIndex = minIndex;
                }
            }

            // 交换最大值到右端
            if (maxIndex !== right) {
                [arr[right], arr[maxIndex]] = [arr[maxIndex], arr[right]];
            }

            left++;
            right--;
        }

        return arr;
    }
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。