选择排序( Selection Sort ) 是基本排序算法之一。
其基本工作原理是将数组的后端部分保留为无序区,在前端逐渐建立有序区。
在每一次躺的操作中,从后端无序区中挑选出最小的元素,然后与无序区的第一个元素交换,于是有序区的范围被扩大了一个元素。
如果某个元素已经位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素后,它们当中至少有一个被移动到了最终位置上,因此对n个元素的表进行排序总共进行至多n-1次的交换操作,在所有的完全依靠交换来实施排序的方法中,选择排序属于非常好的一种。相比之下,插入排序需要大量的挪位操作,在操作开销上要大于选择排序法。
以下给出选择排序法的java代码实现:
public class SelectionSort{
public static <AnyType extends Comparable<? super AnyType>>
void SelectionSort(AnyType[] a){
int index; //To mark the min position during each turn.
AnyType temp;
for(int i=0;i<a.length;i++){
index=i;
for(int j=i+1;j<a.length;j++)
//Attention! a[j] is compared with a[index], not a[i]!
//Since a[index] remains the minimum while a[i] doesn't.
//Otherwise, index will point to the last element which is smaller than a[i],
//instead of the smallest!
if(a[j].compareTo(a[index])<0) index=j;
temp=a[i];
a[i]=a[index];
a[index]=temp;
}
}
public static void main(String[] args){
System.out.println("Selection Sort:");
Integer[] elements={3,4,1,8,10,2,0,6,5};
System.out.print("Original elements: ");
for(int i=0;i<elements.length;i++) System.out.print(elements[i]+" ");
System.out.println();
SelectionSort(elements);
System.out.print("After sorting: ");
for(int i=0;i<elements.length;i++) System.out.print(elements[i]+" ");
System.out.println();
}
}
内循环 j 的扫描是在从i+1的无序区开始的,遍历整个无序区,index标明了在该趟 j 的扫描中找到的最小元素的位置。
在扫描无序区完成,index找到最小位置后,实行与 i 位置元素的互换。
着重讨论一下选择排序与插入排序的比较与差别:
1.插入排序最显著的代码特征是a[j]=a[j-1]的挪位操作。选择排序最显著的代码特征是temp=a[i]; a[i]=a[index]; a[index]=temp的交换操作。
2.插入排序与选择排序都是在前端建立有序区,后端保留为无序区。但是插入操作是先从无序区直接取出第一个元素,然后在依次向前比较挪位的过程中找到正确的位置进行插入,是先提出再找位置。选择排序是先扫描后面无序区,找出要提出的最小元素,然后便直接插入有序区的末尾,是先找后放的过程。这两者在逻辑上的操作顺序是不同的。
3.插入排序比较的开销小,交换的开销大。在挪位的过程中只要找到正确位置即可插入,不需要对整个有序区的每个元素都作比较。但是挪位的时候进行的交换才做非常多。
选择排序的比较开销大,交换开销小。在扫描无序区的过程中,为了找到最小元素,无序区的每个元素都必须进行比较操作。但是最后的交换只需进行一次。
选择排序的平均时间复杂度也为O(n^2),典型的二次时间的基本排序算法。
附图一张,以便理解记忆: