普通版选择排序
一.听说你是最没用的算法,复杂高,而且不稳定,但是还是学一学吧
1.先谈谈算法的思路再分析复杂度和稳定性
思路就是
1.遍历一遍数组,找到最小的值,记录其下标,放在第一个位置上,这样就处理好第一个位置;
以此类推。
初始数组元素: int[] arr : 5 , 4 , 3 , 2 , 1
第一轮 (从下标0开始,找到最小值为1,与第1个位置交换) : 1, 4, 3, 2 ,5 下标0位置搞定
第二轮 (从下标1开始,找到最小值为2,与第2个位置交换) : 1, 2, 3, 4 ,5 下标0、1位置搞定
第三轮 (从下标2开始,找到最小值为3,与第3个位置交换) : 1, 2, 3, 4 ,5 下标0、1、2位置搞定
第四轮 (从下标3开始,找到最小值为4,与第4个位置交换) : 1, 2, 3, 4 ,5 下标0、1、2、3位置搞定
2.根据思路实现代码
package DoExercise;
public class SeletionSort {
/**
* 打印数组
* @param arr
*/
public static void printArr(int[] arr) {
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
/**
* 交换两个数
* @param arr
* @param i
* @param j
*/
private static void swap(int[] arr, int i, int j) {
int temp = arr[i] ;
arr[i] = arr[j];
arr[j] = temp;
}
/**
* 选择排序
* @param arr
*/
private static void selectionSort(int[] arr) {
if(arr == null || arr.length < 2) {//处理边界条件
return;
}
//思路:遍历一遍数组,找到最小的值,记录其下标,放在第一个位置上,这样就处理好第一个位置;以此类推。
//1.遍历数组
//2.找到最小的值,记录其下标
for(int i = 0; i < arr.length; i++) {//i表示当前处理的位置
int minIndex = i; //先默认开始位置最小
for(int j = i + 1; j < arr.length; j++) {// 处理的位置为 i,所以需要从i + 1开始找最小值
if(arr[j] < arr[i]) {//如果 j 下标的值下于 i 下标的值,则更新最小值下标
minIndex = j; //记录最小值下标
}
}
swap(arr,i,minIndex); // 交换 最小值下标 与 需要处理位置 的值
}
}
public static void main(String[] args) {
int[] arr = {5,4,3,2,1};//1.定义测试数据
printArr(arr); //2.打印测试数据
selectionSort(arr);//3.进行选择排序
printArr(arr); //4..打印排序后数据数据
}
}
运行结果:
2.复杂度
for(int i = 0; i < arr.length; i++) {//i表示当前处理的位置
int minIndex = i; //先默认开始位置最小
for(int j = i + 1; j < arr.length; j++) {// 处理的位置为 i,所以需要从i + 1开始找最小值
if(arr[j] < arr[i]) {//如果 j 下标的值下于 i 下标的值,则更新最小值下标
minIndex = j; //记录最小值下标
}
}
swap(arr,i,minIndex); // 交换 最小值下标 与 需要处理位置 的值
}
经历了两次for循环,复杂度是O(n^2)
3.稳定性
稳定性 所谓 稳定性,通俗的来说就是如果一个 数组 中有两个相等的数字,arr [i]=arr [j],i<j,且通过排序后仍然有i<j。
举个栗子:
初始数据: 2 , 8 , 5 , 7 , 5
目前arr[2] = arr[4] , 2 < 4,用5(2)一开始下标为2的5, 用5(4)一开始下标为4的5
初始数据: 2 , 8 , 5 (2), 7 , 5(4)
第一轮: 2, 8 ,5(2),7, 5 (4)
第二轮: 2, 5 (4),5(2),7, 8 排序完成
最后发现 5(4)在 5(2)的前面,破坏了稳定性。