目录
1.选择排序算法:
选择排序是不稳定的算法:选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。
原理:从0索引开始,依次和后面元素比较,大的往前放,第一次完毕,最大值出现在了最小索引处;再将第二个元素依次与后面的元素比较,依次类推直到倒数第二个元素为止。即选择排序的基本思想是每轮循环都能得到一个最大值或者最小值。
代码书写分析:需要使用两层循环:以升序为例。第一层从第一个元素遍历到倒数第二个元素,每遍历一个元素进入第二层循环,即将该元素与他后面的每一个元素进行对比,将最大值放到该元素的索引位置。依次类推直到倒数第二个元素为止。
public class SelectSortDemo {
public static void swap(int[] arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* 选择排序:
* isAsc:true 升序 ;false 降序
* @param arr
* @param isAsc
* @return 数组对象
*/
public static int[] selectSort(int[] arr,boolean isAsc) {
for(int i=0;i<arr.length-1;i++) {
for(int j=i+1;j<arr.length;j++) {
if(isAsc == true) {
if(arr[i]<arr[j]) {
swap(arr,i,j);
}
}else {
if(arr[i]>arr[j]) {
swap(arr,i,j);
}
}
}
}
return arr;
}
}
2.选择排序的优化分析
选择排序的基本思想是每轮循环都能得到一个最大值或者最小值,并将它放在合适的位置上。因此选择排序的优化思想是:每轮循环在得到最大值的同时,也得到一个最小值,并将他们放在合适的位置上。这样算法的循环次数就会减少一半。
public class SelectSort_Opt {
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void selectSort(int[] arr) {
int left = 0;
int right = arr.length-1;
while(left <= right) {
//定义存放规则:左侧放最小值,右侧放最大值
int min = left;
int max = right;
for(int i=left ; i<right ; i++) {
if(arr[i] < arr[min]) {
swap(arr,min,i); //将较小值放在左侧位置
}
if(arr[i] > arr[max]) {
swap(arr,max,i); //将较大值放在右侧位置
}
}
//维护最大值和最小值的索引
left++;
right--;
}
}
}
3.时间复杂度分析:
3.1优化前
对于元素个数为N的数组:
1.第一个元素需要与后面所有的元素比较,需要比较 (N-1) 次,考虑均交换的情况是 3(N-1);
2.第二个元素同样需要与后面所有的元素比较,需要比较 (N-2) 次,考虑均交换的情况是 3(N-2);
......
3.总共循环 (N-1)次
注:复杂度与数组是否有序无关,每次都需要遍历才能找到最大/最小值,最好,最坏或平均时间复杂度均为O(N^2)
3.2优化后
对于元素个数为N的数组:
1.第一个元素和最后一个元素需要与前面的N-1个元素比较,需要比较2 (N-1) 次,考虑均交换的情况是 3(N-1);
2.第二个元素和倒数第二个元素同样需要与中间的N-3个元素比较,需要比较 2(N-3) 次,考虑均交换的情况是 3(N-3);
......
3.总共循环 (N/2)整数次
优化后最坏的时间复杂度为 O(N^2)/2
4.空间复杂度分析:
因为在数组元素位置交换时,需要一个临时变量。因此选择排序算法的空间复杂度为 O(1)