携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
往期内容
前言
选择排序是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
算法实现
算法描述
-
将数组分为两个子集,排序的和未排序的,每一轮从未排序的子集中选出最小的元素,放入排序子集
-
重复以上步骤,直到整个数组有序
算法实现
public static void selection(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
// i 代表每轮选择最小元素要交换到的目标索引
int s = i; // 代表最小元素的索引
for (int j = s + 1; j < a.length; j++) {
// j 元素比 s 元素还要小, 更新 s
if (a[s] > a[j]) {
s = j;
}
}
if (s != i) {
int tmp = a[s];
a[s] = a[i];
a[i] = tmp;
}
System.out.println(Arrays.toString(a));
}
}
测试代码
public static void main(String[] args) {
int[] array = {1, 40, 47, 3, 20, 35, 49, 60, 8, 11, 48};
selection(array);
}
运行结果
[1, 40, 47, 3, 20, 35, 49, 60, 8, 11, 48]
[1, 3, 47, 40, 20, 35, 49, 60, 8, 11, 48]
[1, 3, 8, 40, 20, 35, 49, 60, 47, 11, 48]
[1, 3, 8, 11, 20, 35, 49, 60, 47, 40, 48]
[1, 3, 8, 11, 20, 35, 49, 60, 47, 40, 48]
[1, 3, 8, 11, 20, 35, 49, 60, 47, 40, 48]
[1, 3, 8, 11, 20, 35, 40, 60, 47, 49, 48]
[1, 3, 8, 11, 20, 35, 40, 47, 60, 49, 48]
[1, 3, 8, 11, 20, 35, 40, 47, 48, 49, 60]
[1, 3, 8, 11, 20, 35, 40, 47, 48, 49, 60]
- 优化点:为减少交换次数,每一轮可以先找最小的索引,在每轮最后再交换元素
与冒泡排序比较
-
二者平均时间复杂度都是
-
选择排序一般要快于冒泡,因为其交换次数少
-
但如果集合有序度高,冒泡优于选择
-
冒泡属于稳定排序算法,而选择属于不稳定排序
- 稳定排序指,按对象中不同字段进行多次排序,不会打乱同值元素的顺序
- 不稳定排序则反之
稳定排序与不稳定排序
System.out.println("=================不稳定================");
Card[] cards = getStaticCards();
System.out.println(Arrays.toString(cards));
selection(cards, Comparator.comparingInt((Card a) -> a.sharpOrder).reversed());
System.out.println(Arrays.toString(cards));
selection(cards, Comparator.comparingInt((Card a) -> a.numberOrder).reversed());
System.out.println(Arrays.toString(cards));
System.out.println("=================稳定=================");
cards = getStaticCards();
System.out.println(Arrays.toString(cards));
bubble(cards, Comparator.comparingInt((Card a) -> a.sharpOrder).reversed());
System.out.println(Arrays.toString(cards));
bubble(cards, Comparator.comparingInt((Card a) -> a.numberOrder).reversed());
System.out.println(Arrays.toString(cards));
都是先按照花色排序(♠♥♣♦),再按照数字排序(AKQJ...)
-
不稳定排序算法按数字排序时,会打乱原本同值的花色顺序
[[♠7], [♠2], [♠4], [♠5], [♥2], [♥5]] [[♠7], [♠5], [♥5], [♠4], [♥2], [♠2]]原来 ♠2 在前 ♥2 在后,按数字再排后,他俩的位置变了
-
稳定排序算法按数字排序时,会保留原本同值的花色顺序,如下所示 ♠2 与 ♥2 的相对位置不变
[[♠7], [♠2], [♠4], [♠5], [♥2], [♥5]] [[♠7], [♠5], [♥5], [♠4], [♠2], [♥2]]
大家多多讨论学习salute