选择排序:优雅而朴素的排序艺术

选择排序:优雅而朴素的排序艺术

  1. 算法简介
  2. 算法原理
  3. ️ 算法步骤详解
  4. C++ 实现
  5. Python 实现
  6. 性能分析
  7. 应用场景
  8. 总结

算法简介

选择排序(Selection Sort)是一种简单直观的排序算法,它像一位精明的收藏家,每次从待排序的数据中"选择"出最小(或最大)的元素,放到已排序序列的末尾,直到全部元素排序完毕。

尽管它的时间复杂度不如快速排序或归并排序那样高效,但选择排序以其简单性低空间复杂度(O(1))在特定场景下依然有其用武之地。

算法原理

选择排序的核心思想可以概括为:“每次选择最小的,放到最前面”。具体来说:

  1. 将序列分为已排序未排序两部分
  2. 初始时,已排序部分为空,未排序部分为整个序列
  3. 每次从未排序部分中找出最小(或最大)元素
  4. 将该元素与未排序部分的第一个元素交换位置
  5. 此时已排序部分长度增加1,未排序部分长度减少1
  6. 重复上述过程,直到未排序部分为空

️ 算法步骤详解

让我们通过一个具体的例子来理解选择排序的工作过程:

排序数组: [64, 25, 12, 22, 11]

  1. 第一轮:

    • 找到最小值11,与第一个元素64交换
    • 结果: [11, 25, 12, 22, 64]
  2. 第二轮:

    • 在剩余部分[25, 12, 22, 64]中找到最小值12,与25交换
    • 结果: [11, 12, 25, 22, 64]
  3. 第三轮:

    • 在剩余部分[25, 22, 64]中找到最小值22,与25交换
    • 结果: [11, 12, 22, 25, 64]
  4. 第四轮:

    • 在剩余部分[25, 64]中找到最小值25,已在正确位置
    • 结果: [11, 12, 22, 25, 64]
  5. 第五轮:

    • 只剩64一个元素,排序完成
    • 最终结果: [11, 12, 22, 25, 64]

C++ 实现

#include 
#include 
#include  // 用于swap函数

// 炫酷的选择排序实现
void selectionSort(std::vector<int>& arr) {
    int n = arr.size();
    
    // 外层循环:控制已排序部分的边界
    for (int i = 0; i < n - 1; ++i) {
        // 假设当前元素是最小的
        int min_idx = i;
        
        // 内层循环:在未排序部分中寻找最小值
        for (int j = i + 1; j < n; ++j) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j; // 更新最小值的索引
            }
        }
        
        // 炫酷的交换操作
        if (min_idx != i) {
            std::swap(arr[i], arr[min_idx]);
        }
        
        // 可选:打印每轮排序后的数组状态
        std::cout << "第 " << i + 1 << " 轮排序后: ";
        for (int num : arr) {
            std::cout << num << " ";
        }
        std::cout << "\n";
    }
}

int main() {
    std::vector<int> data = {64, 25, 12, 22, 11};
    
    std::cout << "✨ 原始数组: ";
    for (int num : data) {
        std::cout << num << " ";
    }
    std::cout << "\n\n";
    
    selectionSort(data);
    
    std::cout << "\n 排序后数组: ";
    for (int num : data) {
        std::cout << num << " ";
    }
    std::cout << "\n";
    
    return 0;
}

Python 实现

def selection_sort(arr):
    """
    炫酷的选择排序实现
    :param arr: 待排序的列表
    :return: 无返回值,直接修改原列表
    """
    n = len(arr)
    
    for i in range(n - 1):
        # 假设当前元素是最小的
        min_idx = i
        
        # 在未排序部分中寻找最小值
        for j in range(i + 1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        
        # Python风格的交换操作
        if min_idx != i:
            arr[i], arr[min_idx] = arr[min_idx], arr[i]
        
        # 打印每轮排序后的数组状态(可选)
        print(f"第 {i + 1} 轮排序后: {arr}")
    
    return arr

if __name__ == "__main__":
    data = [64, 25, 12, 22, 11]
    
    print("✨ 原始数组:", data)
    print("\n 开始排序过程:\n")
    
    selection_sort(data)
    
    print("\n 排序后数组:", data)
    
    # 额外炫技:一行Python实现选择排序(不推荐实际使用)
    selection_sort_one_liner = lambda arr: [arr.pop(arr.index(min(arr))) for _ in range(len(arr.copy()))]
    print("\n 一行Python选择排序:", selection_sort_one_liner(data.copy()))

性能分析

指标 说明
时间复杂度 O(n²) 最坏、平均和最好情况都是O(n²),因为无论如何都需要完整的两层循环
空间复杂度 O(1) 原地排序,只需要常数级的额外空间
稳定性 不稳定 交换操作可能改变相等元素的相对位置
适应性 无论输入数据如何,比较次数相同
交换次数 O(n) 最多进行n-1次交换

优点:

  • 实现简单直观
  • 不占用额外内存空间
  • 交换次数少(相对于冒泡排序)

缺点:

  • 时间复杂度较高,不适合大数据量
  • 不稳定排序
  • 每次只能确定一个元素的位置,效率不高

应用场景

虽然选择排序在实际应用中不如快速排序、归并排序等高效算法常用,但在以下场景仍有其价值:

  1. 小规模数据排序:当数据量很小时,选择排序的简单性使其成为不错的选择
  2. 内存受限环境:由于空间复杂度为O(1),在内存有限的嵌入式系统中可能有应用
  3. 教育目的:作为入门排序算法,帮助理解基本排序概念
  4. 特定硬件优化:在某些特定硬件上,减少交换次数的特性可能带来优势

总结

选择排序就像一位耐心的园丁,每次精心挑选出最美丽的花朵,将它们依次排列。虽然它不是最快的排序算法,但它的简单性直观性使其成为算法学习的重要基石。

开始
将数组分为已排序和未排序部分
在未排序部分中寻找最小元素
将最小元素与未排序部分的第一个元素交换
未排序部分是否为空?
排序完成

记住,在编程的世界里,没有绝对的好坏,只有适合与不适合。选择排序可能不是最快的,但在正确的场景下,它依然可以闪耀光芒!

你可能感兴趣的:(算法,算法,排序算法,c++,python)