数据结构与算法_(选择排序)

44 阅读3分钟

核心结论:

  • 选择排序:找「最小 / 最大元素」,放到已排序区末尾(主打 “找了再换”);

一、排序的核心概念(零基础必看)

以升序排序为例,把数组分成两部分:

  • 已排序区间:初始为空,排好序的元素都在这里;
  • 待排序区间:初始是整个数组,需要处理的元素都在这里。排序的本质就是不断缩小(待排序区间),直到它为空。

二、选择排序(Selection Sort):找最小的,缓过来

核心逻辑

比如要排序数组 [64, 25, 12, 22, 11],步骤像 “选班干部”:

1.第一轮:在整个数组里找最小的数(11),和第一个位置的64交换[11,25,12,22,64] (已排序区域:[11]);

2.第二轮:在剩下的[25,12,22,64]里找最小的数(12),和第二个位置的25交换 [11,12,25,22,64] (已排序区域:[11,12]);

3.第三轮:在剩下的 [25,22,64] 里找最小的数(22),和第三个位置的25交换 [11,12,22,25,64] (已排序区域:[11,12,22]);

4.第四轮:在剩下的 [25,64] 里找最小的数 (25),和第四个位置的25交换,最后完成排序。

总结:每轮只做“一次交换”,先找最小元素的位置,再交换

import java.until.Arrays;//用来打印数组,方便看结果

public class SelectionSort {
    //选择排序方法:传入待排序数组,返回排序后的新数组
    public static int[] selectionSort(int[] originalArr) {
        //1.复制原数组,避免修改原数组(新手记住:Arrays.copyOf是数组复制)
        int[] arr = Arrays.copyOf(originalArr,originalArr.length);
        //2.获取数组长度,n = 5(对应例子里的)
        int n = arr.length;
        
        //3.外层循环:控制“已排序区域”的末尾位置(i是待排序区域的第一个位置)
        //循环n-1次啊即可:因为最后1个元素不用比,前面排好它自然再正确位置
        for(int i = 0; i < n - 1 ; i++) {
            //初始化:加上当前待排序区的第一个元素是最小值,记录它的索引
            int minIndex = i;
            //4.内层循环:遍历待排序区域,找真正的最小值的索引
            //j从i+1开始(因为i已经是假设的最小值,不用和自己比)
            for(int j = i + 1; j <n ; j++ ) {
                //如果发现比当前值更小的数,更新最小值的索引
                if(arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            5.交换:把找到的最小值,和待排序区域的第一个元素(arr[i])交换
            //临时遍历temp:用来存交换的中间值(Java里不能直接a = b; b = a;)
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
            
            //打印每轮结果,只管看到排序过程
            System.out.println("第" + (i+1) + "轮排序后:" + Arrays.toString(arr));
        }
   }
    // 6. 返回排序后的数组
        return arr;
}

// 主方法:测试排序
    public static void main(String[] args) {
        // 测试数组
        int[] testArr = {64, 25, 12, 22, 11};
        // 调用排序方法
        int[] sortedArr = selectionSort(testArr);
        // 打印最终结果
        System.out.println("最终排序结果:" + Arrays.toString(sortedArr));
    }

新手易错点

  • 内层循环ji+1开始,不是从 0 开始(否则会重复比较已排序区);
  • 交换时必须用临时变量temp,直接arr[i] = arr[minIndex]; arr[minIndex] = arr[i]会导致两个位置的值都变成同一个数;
  • 选择排序是「不稳定排序」:比如数组[2, 2, 1],第一轮交换后会变成[1, 2, 2],虽然结果对,但两个 2 的相对位置变了(新手暂时记结论即可)。