选择排序算法
选择排序算法的思路是:第一次将集合中最小的数挑选出来放在第一个位置,第二次将集合中最小的数挑选出来放在第二个位置,依此类推。
例如:我们需要对{2,9,5,7,8,0,1,3,4,6}进行排序
经过第1次循环最小位置是:5 结果是:[0, 9, 5, 7, 8, 2, 1, 3, 4, 6];
经过第2次循环最小位置是:6 结果是:[0, 1, 5, 7, 8, 2, 9, 3, 4, 6];
经过第3次循环最小位置是:5 结果是:[0, 1, 2, 7, 8, 5, 9, 3, 4, 6];
经过第4次循环最小位置是:7 结果是:[0, 1, 2, 3, 8, 5, 9, 7, 4, 6];
经过第5次循环最小位置是:8 结果是:[0, 1, 2, 3, 4, 5, 9, 7, 8, 6];
经过第6次循环最小位置是:5 结果是:[0, 1, 2, 3, 4, 5, 9, 7, 8, 6];
经过第7次循环最小位置是:9 结果是:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
经过第8次循环最小位置是:7 结果是:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
经过第9次循环最小位置是:8 结果是:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
选择排序算法初始版本代码如下:
//选择排序算法
public static void main(String[] args) {
int[] arr={2,9,5,7,8,0,1,3,4,6};
int min_pos=0;
for (int j=0;j<arr.length-1;j++ ){
min_pos=j;
//找到数组中最小的值对应的索引
for(int i =j+1;i<arr.length;i++ ){
if(arr[i]<arr[min_pos])
min_pos=i;
}
//将最小位置和 数组中还未排序的第一个进行交换
int temp= arr[j];
arr[j]=arr[min_pos];
arr[min_pos] = temp;
System.out.println("经过第"+(j+1)+"次循环最小位置是:"+min_pos+" 结果是:"+Arrays.toString(arr));
}
System.out.println(Arrays.toString(arr));
}
我们对代码进行一些优化(每次循环同时找出最大和最小值分别与未排序得最后一个位置和第一个位置进行交换),方法的抽取等操作
public static void main(String[] args) {
int arr[] ={2,9,5,7,8,0,1,3,4,6};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void selectionSort(int[] arr){
int min_pos=0;
int max_pos=0;
for (int j=0;j<arr.length/2;j++ ){
min_pos=j;
max_pos=arr.length-1-j;
//找到数组中最小的值对应的索引
for(int i =j+1;i<arr.length;i++ ){
min_pos=arr[i]<arr[min_pos]?i:min_pos;
max_pos=arr[arr.length-i-1]>arr[max_pos]?(arr.length-i-1):max_pos;
}
//将最小位置和 数组中还未排序的第一个进行交换
swap(arr,j,min_pos);
//将最小位置和 数组中还未排序的最后一个进行交换
if(j == max_pos ){//处理最大位置刚好被最小数换走的情况
swap(arr, min_pos, arr.length-j-1);
} else if(max_pos!=min_pos){//防止最小位置交换后 又换回来
swap(arr,arr.length-j-1,max_pos);
}
System.out.println("经过第"+(j+1)+"次循环最小位置是:"+min_pos+"最大位置是:"+max_pos+" 结果是:"+ Arrays.toString(arr));
}
}
//交换数组中两个数的位置
public static void swap(int[] arr,int i,int j){
int temp= arr[j];
arr[j]=arr[i];
arr[i] = temp;
}
运行结果:
经过第1次循环最小位置是:5最大位置是:1 结果是:[0, 6, 5, 7, 8, 2, 1, 3, 4, 9]
经过第2次循环最小位置是:6最大位置是:4 结果是:[0, 1, 5, 7, 4, 2, 6, 3, 8, 9]
经过第3次循环最小位置是:5最大位置是:3 结果是:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
经过第4次循环最小位置是:3最大位置是:6 结果是:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
算法验证
写一个数组生成的方法和数组比较的方法来验证我们的算法是否真的正确
/*
验证器
*/
private static Boolean matcher(int[] arr1,int[] arr2){
for (int i = 0; i < arr1.length ; i++) {
if(arr1[i]!=arr2[i]){
System.out.println(arr2[i]);
System.out.println(arr1[i]);
return false;
}
}
return true;
}
/*
*产生随机数组
*/
public static int[] randomArr(Integer length){
int arr[] =new int[length] ;
Random random = new Random();
for (int i=0;i<length;i++){
int randomNum = random.nextInt(length);
arr[i]=randomNum;
}
return arr;
}
主方法中调用
public static void main(String[] args) {
int arr[] =randomArr(1000);
//拷贝一份用于验证
int[] copy = Arrays.copyOf(arr, arr.length);
// 用自己实现的算法排序
selectionSort(arr);
//用arrays工具类对复制的数组排序
Arrays.sort(copy);
//验证
System.out.println(matcher(copy, arr));
// System.out.println(Arrays.toString(arr));
// System.out.println(Arrays.toString(copy));
}
经过多次验证,问题不大