排序算法之选择排序
1. 介绍
在冒泡排序算法一篇中,介绍了基本的冒泡排序与几种改进方法,但无论那几种方法怎么改进,都还是基于两两交换不断推进的冒泡排序。
冒泡排序算法最费时的是什么?一是相邻元素两两比较,二是不满足排序规则的元素两两交换,当然交换要比比较费时多了。两两交换的目的是什么呢?是找出最值(最大值或最小值)。
但是冒泡排序算法中找最值的代价是很大的,每次遍历,可能需要很多次交换才能找到最值,而这些交换都是很浪费时间的。如果能减少交换次数,又能达到找到最值的目的,那较冒泡排序来说就是一种改进。
这时,我们很自然就可能会想到,如果每次遍历,只选择最值元素进行交换,这样一次遍历,只需进行一次交换即可,从而避免了其它无价值的交换操作,相较冒泡排序可能多次交换来说就是一种改进。选择排序就是这样一种算法。
2. 算法描述
选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的元素中选出最小(或最大)的一个元素,存放在该序列的起始位置,这样一次遍历,只需一次交换,便可将最值放置到合适位置;重复前述操作直到全部待排序的数据元素排完。
3. 算法实现
package com.demo;
/**
* 选择排序算法
*
* @author 小明
*
*/
public class SelectionSort {
/**
* 选择排序(升序排序)
*
* @param array
* 待排序数组
*/
public static void sort(int[] array) {
for (int i = 0, len = array.length; i < len - 1; i++) { // 外层循环,控制选择的轮数
int min = i; // 使用变量min记录该轮最小值元素的索引
for (int j = i + 1, length = array.length; j < length; j++) { // 循环,查找最小值索引
if (array[j] < array[min]) { // 当遍历元素找到比min索引处元素还小的值时,记录该索引为最小值索引
min = j;
}
}
System.out.print("当前第"+(i+1)+"轮最小值:" + array[min]);
if (min != i) { // min不等于i,说明找到另一个元素比当前轮遍历到的元素小,则交换位置
int tmp = array[i];
array[i] = array[min];
array[min] = tmp;
}
System.out.println(",排序结果为:");
show(array);
}
}
/**
* 显示数组中各元素值
*
* @param array
* 待显示的数组
*/
private static void show(int[] array) {
for (int i : array) {
System.out.print(i + "\t");
}
System.out.println();
}
/**
* 入口方法,测试
*
* @param args
*/
public static void main(String[] args) {
int[] array = { 8, 5, 2, 6, 9, 3, 1, 4, 0, 7 }; // 待排序数组
sort(array);
System.out.println("************************");
System.out.println("排序后:");
show(array);
}
}
运行结果:
当前第1轮最小值:0,排序结果为:
0 5 2 6 9 3 1 4 8 7
当前第2轮最小值:1,排序结果为:
0 1 2 6 9 3 5 4 8 7
当前第3轮最小值:2,排序结果为:
0 1 2 6 9 3 5 4 8 7
当前第4轮最小值:3,排序结果为:
0 1 2 3 9 6 5 4 8 7
当前第5轮最小值:4,排序结果为:
0 1 2 3 4 6 5 9 8 7
当前第6轮最小值:5,排序结果为:
0 1 2 3 4 5 6 9 8 7
当前第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
************************
排序后:
0 1 2 3 4 5 6 7 8 9
4. 结束语
从选择排序的思想或者是上面的代码中,我们都不难看出,寻找最小的元素需要一个循环的过程,而排序又是需要一个循环的过程。因此显而易见,这个算法的时间复杂度也是O(n^2)的。这就意味值在n比较小的情况下,算法可以保证一定的速度,当n足够大时,算法的效率会降低。随着n的增大,算法的时间增长很快,因此使用时需要特别注意。
和插入排序相比,选择排序是固定位置,找元素;而插入排序则是固定元素找位置,是两种思维方式。