详解十大经典排序算法(二):选择排序(Selection Sort)

算法原理

选择排序通过重复选择数组中最小元素,将其与未排序部分的第一个元素交换,实现排序。

算法描述

选择排序是一种简单的排序算法,它每次从待排序的元素中选择最小(或最大)的元素,将其放到已排序序列的末尾,直到整个序列排序完成。

选择排序的基本思想是通过不断选择剩余元素中的最小(或最大)元素,将其放置到已排序序列的末尾,从而逐步构建有序序列。具体步骤如下:

  1. 遍历待排序序列,找到最小(或最大)的元素。
  2. 将最小(或最大)元素与待排序序列的第一个元素交换位置,将该元素放置到已排序序列的末尾。
  3. 缩小待排序序列的范围,将已排序序列的长度增加1。
  4. 重复步骤1-3,直到待排序序列为空。

动画演示

代码实现

java 复制代码
public void selectSort(int arr[]) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            //交换 arr[i]和arr[minIndex]
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

算法复杂度

时间复杂度(最坏) 时间复杂度(最好) 时间复杂度(平均) 空间复杂度 稳定性
O(n^2) O(n^2) O(n^2) O(1) 不稳定

选择排序的优化方式:

  1. 设置一个标志位,记录每一趟遍历中最小(或最大)元素的位置,避免不必要的交换操作。
java 复制代码
public void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }
  1. 使用双指针,分别指向已排序序列的末尾和待排序序列的开头,减少交换操作的次数。
java 复制代码
public void selectionSort(int[] arr) {
        int n = arr.length;
        int left = 0;
        int right = n - 1;
    
        //直到left和right指针相遇。
        while (left < right) {
            int minIndex = left;
            int maxIndex = left;
            //寻找最小和最大元素下标
            for (int i = left + 1; i <= right; i++) {
                if (arr[i] < arr[minIndex]) {
                    minIndex = i;
                }
                if (arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }
            //如果最小元素的位置不等于left,则将最小元素与已排序序列的末尾元素交换位置。
            //此处的末尾是数值越来越大:1 3 4 ...
            if (minIndex != left) {
                int temp = arr[left];
                arr[left] = arr[minIndex];
                arr[minIndex] = temp;
            }
            //如果最大元素的位置等于left,则将最大元素的位置更新为最小元素的位置。
            //因为上一步已经把最大元素换到了最小元素位置,所以需要重新设置下标
            if (maxIndex == left) {
                maxIndex = minIndex;
            }
            //如果最大元素的位置不等于right,则将最大元素与待排序序列的开头元素交换位置。
            //此处的开头是数值越来越小:... 5 6 9
            if (maxIndex != right) {
                int temp = arr[right];
                arr[right] = arr[maxIndex];
                arr[maxIndex] = temp;
            }
            left++;
            right--;
        }
    }

通过使用双指针的优化方式,可以减少交换操作的次数。在每一趟遍历中,同时找到最小元素和最大元素的位置,并根据情况进行交换操作。这样可以减少不必要的交换操作,提高排序的效率。同时,由于每一趟遍历中的交换操作次数减少,也减少了数据的移动次数,进一步提高了排序的效率。


相关概念

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

相关推荐
2501_924889553 小时前
商超高峰客流统计误差↓75%!陌讯多模态融合算法在智慧零售的实战解析
大数据·人工智能·算法·计算机视觉·零售
jingfeng5144 小时前
C++模板进阶
java·c++·算法
地平线开发者4 小时前
征程 6X | 常用工具介绍
算法·自动驾驶
地平线开发者5 小时前
理想汽车智驾方案介绍 2|MindVLA 方案详解
算法·自动驾驶
艾莉丝努力练剑5 小时前
【C语言16天强化训练】从基础入门到进阶:Day 7
java·c语言·学习·算法
地平线开发者6 小时前
LLM 中评价指标与训练概要介绍
算法·自动驾驶
Ghost-Face6 小时前
关于并查集
算法
flashlight_hi7 小时前
LeetCode 分类刷题:2529. 正整数和负整数的最大计数
python·算法·leetcode
花火|7 小时前
算法训练营day60 图论⑩ Bellman_ford 队列优化算法、判断负权回路、单源有限最短路
算法·图论
2501_924890527 小时前
商超场景徘徊识别误报率↓79%!陌讯多模态时序融合算法落地优化
java·大数据·人工智能·深度学习·算法·目标检测·计算机视觉