每日一算法——选择排序

0 阅读4分钟

算法概述

选择排序 是一种简单直观的排序算法,它的基本思想是:每次从待排序的数据元素中选出 最小(或最大) 的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。

选择排序是学习排序算法的入门级算法,虽然时间复杂度较高,但它的实现简单、逻辑清晰,非常适合初学者理解排序算法的基本思想。在实际应用中,选择排序适用于数据量较小(n < 100)的场景,或者内存空间受限的环境,因为它不需要额外的存储空间。

核心思路和原理

选择排序的核心思想可以概括为 " 逐个挑选,放到对应位置 "。算法将待排序数组分为两个区域:已排序区和未排序区。初始时,已排序区为空,未排序区包含所有元素。

算法执行步骤:

  1. 外层循环:从第一个元素开始,遍历到倒数第二个元素(共进行 n-1 轮)
  2. 假设最小值:假设当前元素是最小值,记录其索引
  3. 内层循环:从当前位置的下一个元素开始,遍历到数组末尾,寻找真正的最小值
  4. 更新最小值:如果找到更小的元素,更新最小值索引
  5. 交换位置:将找到的最小值与当前位置的元素交换
  6. 重复执行:直到所有元素都排好序

选择排序的特点是:无论输入数据的初始状态如何,比较次数都是固定的 n(n-1)/2 次,交换次数最多为 n-1 次。相比冒泡排序,选择排序的交换次数更少,因此在小规模数据排序时效率更高。

算法流程图

流程图说明:

  1. 外层循环控制排序轮数(i 从 0 到 n-2)
  2. 内层循环在未排序部分查找最小值位置
  3. 找到最小值后,如果不在当前位置则交换
  4. 重复执行直到所有元素排序完成

详细示例演示

让我们通过一个具体例子来理解选择排序的执行过程。假设我们要对数组  [64, 25, 12, 22, 11]  进行升序排序:

初始状态: [64, 25, 12, 22, 11]

第 1 轮排序:

  • 在未排序部分  [64, 25, 12, 22, 11]  中找到最小值 11(索引 4)
  • 将 11 与第一个元素 64 交换
  • 结果: [11, 25, 12, 22, 64]
  • 已排序区:[11],未排序区:[25, 12, 22, 64]

第 2 轮排序:

  • 在未排序部分  [25, 12, 22, 64]  中找到最小值 12(索引 2)
  • 将 12 与第二个元素 25 交换
  • 结果: [11, 12, 25, 22, 64]
  • 已排序区:[11, 12],未排序区:[25, 22, 64]

第 3 轮排序:

  • 在未排序部分  [25, 22, 64]  中找到最小值 22(索引 3)
  • 将 22 与第三个元素 25 交换
  • 结果: [11, 12, 22, 25, 64]
  • 已排序区:[11, 12, 22],未排序区:[25, 64]

第 4 轮排序:

  • 在未排序部分  [25, 64]  中找到最小值 25(索引 3)
  • 25 已经在正确位置,无需交换

最终结果: [11, 12, 22, 25, 64]

Python 代码实现

def selection_sort(arr):
    n = len(arr)
    # 外层循环:控制排序轮数(n-1轮)
    for i in range(n - 1):
        # 假设当前元素是最小值
        min_index = i
        # 内层循环:在未排序部分查找真正的最小值
        for j in range(i + 1, n):
            if arr[j] < arr[min_index]:
                min_index = j
        # 如果最小值不在当前位置,则交换
        if min_index != i:
            arr[i], arr[min_index] = arr[min_index], arr[i]
    return arr

if __name__ == "__main__":
    # 测试用例
    test_array = [6425122211]
    print("排序前:", test_array)
    # 调用选择排序
    sorted_array = selection_sort(test_array)
    print("排序后:", sorted_array)
    
    # 输出结果:
    # 排序前: [64, 25, 12, 22, 11]
    # 排序后: [11, 12, 22, 25, 64]

代码说明:

  1. 外层循环从 0 到 n-2,共进行 n-1 轮排序
  2. 内层循环从 i+1 到 n-1,在未排序部分查找最小值
  3. 每次找到最小值后,如果不在当前位置则交换
  4. 算法是原地排序,不需要额外空间