选择排序的算法描述:
- 选定第一个元素,与剩下的元素逐一比较,找到最小的那个元素,直到数组结束,然后与第一个元素交换。
- 选定第二个元素,与剩下的元素逐一比较,找到最小的那个元素,直到数据结束,然后与第二个元素交换。
- 依次类推。。。直到第N个元素
算法实现为:
public class SelectSort { public static void main(String[] args) { int[] nums = new int[]{1, 15, 3, 78, 34, 23, 46, 2, 8, 34, 57}; System.out.println(Arrays.toString(nums)); sort(nums); System.out.println(Arrays.toString(nums)); } public static void sort(int[] arrays) { for(int i=0; i< arrays.length; i++ ) { int min = i; for(int j=i+1; j< arrays.length; j++) { if (arrays[min] > arrays[j]) min = j; } //exchange the min and current arrays[i] if (min != i) { int temp = arrays[i]; arrays[i] = arrays[min]; arrays[min] = temp; } } } }
算法复杂度分析:
灰色的是已经排好序的元素,黑色的是待排序的元素,红色元素是在一次完整的查找过程中找到的最小的元素
可以看到每次找到的最小元素会放在已经排序的元素后面,也就是--在第 n 次循环中,找到最小的那个元素,然后与第n个元素交换。
算法分析:
按照算法的流程来分析:
每次循环,选出最小元素需要比较N-i +1次,i 的范围[0-n-1]所以,所有循环需要比较的次数为:N-1, N-2, N-3,.....1,等差数列求和为 (N-1 + 1)(N-1)/2 近似:N2/2
所有交换的次数最多为N-1次
总的时间复杂度为 N2/2(N的平方)
选择排序是两层循环,我们分为外循环和内循环:外循环最多的交换次数为N-1次,内循环最多的比较次数为N-1次,所有的内循环次数和外循环次数中的操作综合加起来,很容易得出上面的结果.
选择排序的缺点是,在内循环中,他是逐一比较的,不管数组是否有序,都会从头到尾的依次比较,这样的缺点是,如果数组已经是有序状态,或者是部分有序,选择排序不会利用这个有序条件而减少比较次数,下篇会介绍插入排序,可以利用数据的有序或者部分有序状态来大大的减少比较次数,从而提高排序速度!
另外说一个小的优化点,很重要!
可以看到我们在每一次内循环中查找最小的元素时,有一个优化点:我们选定第 i(0到n-1) 个元素与后面的元素逐一比较,当发现有更小的元素时,并不是直接将a[i] 与这个更小的元素交换,而是用这个更小元素去与剩下的元素比较,同时记录这个更小元素的索引,内循环结束是,我们还没有发生依次交换,只是找出了最小元素的索引而已,找到最小索引后,才执行交换操作,而不是每次比较满足条件时就执行交换操作!
我把这段代码发出来,可以仔细体会下,
public class SelectSort { public static void main(String[] args) { int[] nums = new int[]{1, 15, 3, 78, 34, 23, 46, 2, 8, 34, 57}; System.out.println(Arrays.toString(nums)); sort(nums); System.out.println(Arrays.toString(nums)); } public static void sort(int[] arrays) { for(int i=0; i< arrays.length; i++ ) { for(int j=i+1; j< arrays.length; j++) { if (arrays[i] > arrays[j]) { //exchange int temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } //exchange the min and current arrays[i] // if (min != i) { // int temp = arrays[i]; // arrays[i] = arrays[min]; // arrays[min] = temp; // } } } }
下一篇:冒泡排序