此博客用于个人学习,来源于算法的书籍和网上的资料,对知识点进行一个整理。
1. 概述:
选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。这种方法叫做选择排序,因为它在不断地选择剩余元素之中的最小者(最大者)。
2. 算法:
- 找到数组中最小的那个元素。
- 将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。
- 在剩下的元素中,找到最小的元素,将它与数组的第二个元素交换位置。
- 如此往复,直到整个数组排序完成。
3. 代码实现:
/**
* 选择排序
*/
public class Selection {
/**
* 通过两层for循环,每一次找出i后面元素的最小值,并且与i调换顺序,直至顺序正确,默认升序排序
* @param a
*/
public static void sort(Comparable[] a){
for (int i = 0;i < a.length;i++){
int min = i;
//将a[i]与a[i+1 ... N]中最小元素交换
for (int j = i+1;j < a.length;j++){
if (less(a[j],a[min])){
min = j;
}
}
exchange(a,i,min);
}
}
private static boolean less(Comparable v,Comparable w){
return v.compareTo(w) < 0;
}
private static void exchange(Comparable[] a,int i,int j){
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private static void show(Comparable[] a){
//在单行中打印数组
for (int i = 0;i < a.length;i++){
System.out.println(a[i]+" ");
}
System.out.println();
}
/**
* 测试数组元素是否有序
* @param a
* @return
*/
public static boolean isSorted(Comparable[] a){
for (int i = 1;i < a.length;i++){
if (less(a[i],a[i-1])){
return false;
}
}
return true;
}
}
4. 特点:
- 运行时间和输入无关。未来找出最小的元素遍历一遍数组并不能为下次扫描提供任何信息,即,一个已经有序的数组或者是主键全部相等的数组和一个元素随机排列的数组所用的排序时间一样长。
- 数据移动是最少的。每次交换都会改变两个数组元素的值,因此选择排序用了 N 次交换——交换次数和数组的大小是线性关系。
5. 算法分析:
-
时间复杂度:0 到 n-1 的任意 i 都会进行一次交换和 n-1-i 次比较,因此总共有 n 次交换以及 (n-1)+(n-2)+(n-3)+…+2+1 ~ n^2/2 次比较,时间复杂度为 O(n^2)。
-
空间复杂度:只是用了2个循环变量以及1到2个标志和交换等的中间变量,这个与待排序的记录个数无关,空间复杂度为 O(1)。
-
稳定性:选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第 n - 1 个元素,第 n 个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等 的元素后面,那么交换后稳定性就被破坏了。举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。