一种最简单的排序算法是这样的:首先,找到数组中最小的那个元素,其次,将它和数组中的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小元素,将它与数组的第二个元素交换位置。如此反复,直到将整个数组排序。这种方法就叫做选择排序,因为它在不断的选择剩余元素中的最小者。
选择排序是种很容易理解和实现的简单排序算法,它有两个很鲜明的特点。
运行时间和输入无关。为了找出最小的元素而扫描遍数组并不能为下一遍扫描提供什么信息,这种性质在某些情况下是缺点,因为使用选择排序的人可能会惊讶地发现,一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长! 我们将会看到,其他算法会更善于利用输人的初始状态。
数据移动是最少的。每次交换都会改变两个数组元素的值,因此选择排序用了N次交换一交换次数和数组的大小是线性关系。我们将研究的其他任何算法都不具备这个特征(大部分的增长数量级都是线性对数或是平方级别)。
以下是实现代码:
public class Selection
{
static int compareCount = 0;
static int changeCount = 0;
static int loopCount = 0;
public static boolean less(Comparable v, Comparable w){
compareCount++;
return v.compareTo(w) < 0;
}
public static void exch(Comparable[] a, int i, int j)
{
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
changeCount++;
}
//在单行中打印数组
public static void show(Comparable[] a)
{
for (int i = 0; i < a.length; i++)
{
if (i == a.length - 1)
System.out.print(a[i]);
else
System.out.print(a[i] + ",");
}
}
//测试数组元素是否有序
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;
}
public static void sort(Comparable[] a)
{
//将a[]按升序排序
int N = a.length;
for (int i = 0; i < N; i++)
{ //将a[i]和a[i+1..N]中最小的元素交换
int min = i; //最小元素的索引
for (int j = i + 1; j < N; j++)
{
if (less(a[j], a[min])) min = j;
}
exch(a, i, min);
System.out.print("第" + (i + 1) + "次排序," + "交换的位置索引:" + i + "\t[" );
show(a);
System.out.println("]");
}
}
public static void main(String[] args){
Integer[] a = {4,5,2,9,6,3,7,1,8,0};
System.out.print("\t\t\t\t\t\t[");
show(a);
System.out.println("]");
sort(a);
assert isSorted(a);
System.out.println("一共交换了:" + changeCount + "次,比较了:" + compareCount + "次");
}
}
红色标注的是交换的元素
[4,5,2,9,6,3,7,1,8,0]
第1次排序,交换的位置索引:0 [0,5,2,9,6,3,7,1,8,4]
第2次排序,交换的位置索引:1 [0,1,2,9,6,3,7,5,8,4]
第3次排序,交换的位置索引:2 [0,1,2,9,6,3,7,5,8,4]
第4次排序,交换的位置索引:3 [0,1,2,3,6,9,7,5,8,4]
第5次排序,交换的位置索引:4 [0,1,2,3,4,9,7,5,8,6]
第6次排序,交换的位置索引:5 [0,1,2,3,4,5,7,9,8,6]
第7次排序,交换的位置索引:6 [0,1,2,3,4,5,6,9,8,7]
第8次排序,交换的位置索引:7 [0,1,2,3,4,5,6,7,8,9]
第9次排序,交换的位置索引:8 [0,1,2,3,4,5,6,7,8,9]
第10次排序,交换的位置索引:9 [0,1,2,3,4,5,6,7,8,9]
一共交换了:10次,比较了:45次