这次要介绍的是选择排序中的简单选择排序,可以看到堆排序也属于选择排序,不着急,会在后面的文章对它进行介绍。
选择排序也是一种很简单的排序,没啥可以介绍的,直接看基本思想。
假设对一个数组进行升序排序,第一次从arr[0] ~ arr[n-1]中选取出最小值,与arr[0]交换;第二次从arr[1] ~ arr[n-1]中选取出最小值,与arr[1]交换;… ;第i次从arr[i-1] ~ arr[n-1]中选取最小值,与arr[i-1]交换;… ;第n-1次(最后一次)从arr[n-2] ~ arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次选择交换操作,得到从小到大排列的有序序列。
虽然很简单,还是举个例子:对6、4、7、2进行升序排列
第1次:从6、4、7、2选择出最小值2,与6进行交换,得到2、4、7、6
第2次:从4、7、6选择出最小值4,与4进行交换(这里刚好重合了),得到2、4、7、6
第3次:从7、6选择出最小值6,与7进行交换,得到2、4、6、7,排序完毕
public static void selectSort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
int min = i;
for (int j = i + 1; j < nums.length; j++) {
min = nums[j] < nums[min] ? j : min;
}
if (i != min) {
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
}
}
每次查找最小值的同时也把最大值查找出来,这样迭代的次数就会减少一半。
public static void selectSort2(int[] nums) {
for (int i = 0; i < nums.length / 2; i++) {
int right = nums.length - i - 1;
int min = i;
int max = right;
for (int j = i + 1; j < nums.length - i; j++) {
min = nums[j] < nums[min] ? j : min;
max = nums[j] > nums[max] ? j : max;
}
if (min != i) {
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
if (max != right) {
int temp = nums[right];
nums[right] = nums[max];
nums[max] = temp;
}
}
}
注意:这种优化只能让性能得到些许提升,使得它大部分时间比不优化时快一点,并不能弥补它天生的性能问题。
可以看到,它比冒泡排序快一些,但是当数据量达到五十万时,耗时100秒,还是很久了。虽然这些都是简单测试,并没有把硬件性能等因素加进去,但是也足以说明不同算法之间的性能问题了。