Administrator
发布于 2025-09-25 / 11 阅读
0
0

C#6.4 排序和查找-选择排序法

1. 先从生活例子开始理解

想象一下你要整理一副扑克牌,按照从小到大的顺序排列:

初始牌序:9, 105, 23, 19, 1

选择排序的思路就像这样:

  1. 找最小:在未排序部分中找到最小元素

  2. 记录位置:记录最小元素的索引,而不是直接交换

  3. 一次交换:每轮外层循环只进行一次交换

2. 用简单语言解释算法步骤

// 假设我们有这些数字:9, 105, 23, 19, 1
​
// 第1轮:找到最小的数字1,和第一个数字9交换
// 结果:1, 105, 23, 19, 9
​
// 第2轮:从剩下的数字中找到最小的9,和第二个数字105交换  
// 结果:1, 9, 23, 19, 105
​
// 第3轮:从剩下的数字中找到最小的19,和第三个数字23交换
// 结果:1, 9, 19, 23, 105
​
// 第4轮:剩下的已经有序,不需要交换
// 最终结果:1, 9, 19, 23, 105

3. 基础代码演示(带详细注释)

using System;
​
class Program
{
    static void Main()
    {
        // 我们要排序的数字数组
        int[] numbers = { 9, 105, 23, 19, 1 };
        
        Console.WriteLine("原始数组: " + string.Join(", ", numbers));
        
        // 调用选择排序方法
        SelectionSort(numbers);
        
        Console.WriteLine("排序后数组: " + string.Join(", ", numbers));
    }
    
    static void SelectionSort(int[] arr)
    {
        // 数组长度
        int n = arr.Length;
        
        // 外层循环:控制排序的轮数
        // 每轮确定一个最小元素的位置
        for (int i = 0; i < n - 1; i++)
        {
            Console.WriteLine($"\n=== 第{i+1}轮开始 ===");
            Console.WriteLine("当前数组: " + string.Join(", ", arr));
            
            // 假设当前轮次的第一个元素是最小的
            int minIndex = i;
            Console.WriteLine($"假设位置{i}的数字{arr[i]}是最小的");
            
            // 内层循环:在剩余元素中寻找真正的最小值
            for (int j = i + 1; j < n; j++)
            {
                Console.WriteLine($"  比较: 当前最小值{arr[minIndex]} vs 位置{j}的数字{arr[j]}");
                
                // 如果找到更小的数字,更新最小值的索引
                if (arr[j] < arr[minIndex])
                {
                    minIndex = j;
                    Console.WriteLine($"  → 发现更小的数字! 新的最小值是位置{minIndex}的数字{arr[minIndex]}");
                }
            }
            
            // 如果最小值不在当前位置,进行交换
            if (minIndex != i)
            {
                Console.WriteLine($"交换位置{i}的数字{arr[i]}和位置{minIndex}的数字{arr[minIndex]}");
                
                // 交换两个数字
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
                
                Console.WriteLine($"交换后数组: " + string.Join(", ", arr));
            }
            else
            {
                Console.WriteLine("最小值已在正确位置,不需要交换");
            }
        }
    }
}

4. 可视化执行过程

让我用表格展示每一轮的变化:

轮次

操作

结果数组

初始

-

[9, 105, 23, 19, 1]

第1轮

找到最小值1,与9交换

[1, 105, 23, 19, 9]

第2轮

找到最小值9,与105交换

[1, 9, 23, 19, 105]

第3轮

找到最小值19,与23交换

[1, 9, 19, 23, 105]

第4轮

找到最小值23,已在正确位置

[1, 9, 19, 23, 105]

5. 关键概念解释

什么是"索引"(Index)?

int[] numbers = {9, 105, 23, 19, 1};
// 索引:       0    1   2   3   4
  • 索引就是每个数字的位置编号

  • C#中索引从0开始计数

为什么用 minIndex 而不是直接比较值?

// 正确做法:记录最小值的索引
int minIndex = i;
if (arr[j] < arr[minIndex])
{
    minIndex = j;  // 只更新索引,不修改数组
}
​
// 错误做法:直接修改数组值
if (arr[j] < arr[minIndex])
{
    arr[minIndex] = arr[j];  // 这样会丢失数据!
}

6. 练习:自己动手试试

任务1: 修改代码,实现从大到小排序

// 提示:只需要修改比较条件
// 把 < 改为 >

任务2: 对字符串数组按字母顺序排序

string[] words = {"banana", "apple", "cherry", "date"};
// 提示:字符串比较用 CompareTo 方法

7. 常见问题解答

Q: 为什么外层循环是 i < n-1 而不是 i < n A: 因为当确定了n-1个元素的位置后,最后一个元素自然就在正确位置了。

Q: 选择排序快吗? A: 对于小数据集可以,大数据集比较慢。时间复杂度是O(n²)。

Q: 什么时候用选择排序? A: 当数据量小,或者需要简单易懂的排序方法时。

8. 总结

选择排序的核心思想:

  1. :在未排序部分中找到最小元素

  2. :把最小元素放到已排序部分的末尾

  3. 重复:直到所有元素都排好序

记住这个口诀:"找最小,放前面,重复做,就排好!"


评论