详解十大经典排序算法(二):选择排序(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的函数。

相关推荐
慕容魏16 分钟前
入门到入土,Java学习 day16(算法1)
java·学习·算法
认真的小羽❅17 分钟前
动态规划详解(二):从暴力递归到动态规划的完整优化之路
java·算法·动态规划
Vacant Seat1 小时前
图论-实现Trie(前缀树)
java·开发语言·数据结构·图论
LiDAR点云1 小时前
Matlab中快速查找元素索引号
数据结构·算法·matlab
CYRUS_STUDIO1 小时前
安卓逆向魔改版 Base64 算法还原
android·算法·逆向
JKHaaa2 小时前
数据结构之线性表
数据结构
CYRUS_STUDIO2 小时前
安卓实现魔改版 Base64 算法
android·算法·逆向
一只_程序媛2 小时前
【leetcode hot 100 142】环形链表Ⅱ
算法·leetcode·链表
Luis Li 的猫猫3 小时前
基于MATLAB的冰块变化仿真
开发语言·图像处理·人工智能·算法·matlab
郭涤生3 小时前
并发操作的同步_第四章_《C++并发编程实战》笔记
开发语言·c++·算法