选择排序工作原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
时间复杂度:O(n²)
空间复杂度:O(1)
稳定性:不稳定。
算法如下:
import java.util.Arrays;
import java.util.Random;
/**
* @hla
* 最简单的选择排序
*/
public class SelectionSort {
public static void main(String[] args) {
Random r = new Random();
int arr[] = new int[100000];
long count = 0;
//随机复制10万个整数
for(int i=0;i<arr.length;i++){
arr[i] = r.nextInt(100000);
}
//复制一份随机数以验证算法正确与否
int[] arrcopy = new int[arr.length];
System.arraycopy(arr,0,arrcopy,0,arr.length);
//计算算法开始时间
long startStamp = System.currentTimeMillis();
//算法开始
for(int j=0;j<arr.length-1;j++) {
int minPos = j;
for (int i = j+1; i < arr.length; i++) {
if (arr[i] < arr[minPos]) {
minPos = i;
}
count++;
}
int temp = arr[minPos];
arr[minPos] = arr[j];
arr[j] = temp;
}
//计算算法结束时间
long endStamp = System.currentTimeMillis();
System.out.println("用时总长:"+(endStamp-startStamp));
System.out.println("循环次数:"+count);
//利用jdk自带的方法排序
Arrays.sort(arrcopy);
boolean same = true;
for(int i = 0;i<arrcopy.length;i++){
if(arr[i]!=arrcopy[i]) {
same = false;
System.out.println(arr[i]+" "+arrcopy[i]);
}
}
System.out.println(same==true?"算法正确":"算法错误");
}
}
结果:
用时总长:11253
循环次数:4999950000
算法正确
优化版如下:
import java.util.Arrays;
import java.util.Random;
/**
* @hla
**/
/**
* 优化版:
* 每次排序时找出最大值和最小值,最大值往右边放,最小值往左边放。
*/
public class SelectionSort2 {
public static void main(String[] args) {
Random r = new Random();
int arr[] = new int[100000];
for(int i=0;i<arr.length;i++){
arr[i] =r.nextInt(100000);
}
//复制一份随机数组以便下面验证算法正确性
int[] arrcopy = new int[arr.length];
System.arraycopy(arr,0,arrcopy,0,arr.length);
int ArrLength = (arr.length/2);
int temp1,temp2;
long count = 0;
//记录开始时间
long startStamp = System.currentTimeMillis();
//算法开始
for(int j=0;j<ArrLength;j++){
int minPos = j;
int maxPos = j;
for(int i=j;i<arr.length-j;i++){
if (arr[minPos] > arr[i]) {
minPos = i;
}
if (arr[maxPos] < arr[i]) {
maxPos = i;
}
count++;
}
temp1 = arr[minPos];
arr[minPos] = arr[j];
arr[j] = temp1;
/**
这个判断是为了:
例如9 8 5 1 3 2 数组。当上面互换语句执行后
就变成了1 8 5 9 3 2数组。这时maxPos的位置不再是原本的位置了。
而是再互换后的minPos的位置上
**/
if(j!=maxPos) { //maxPos不能再原本的minPos位置上
temp2 = arr[maxPos];
arr[maxPos] = arr[arr.length - j - 1];
arr[arr.length - j - 1] = temp2;
}else{
temp2 = arr[minPos];
arr[minPos] = arr[arr.length - j - 1];
arr[arr.length - j - 1] = temp2;
}
}
//计算算法结束时间
long endStamp = System.currentTimeMillis();
System.out.println("用时总长:"+(endStamp-startStamp));
System.out.println("循环次数:"+count);
//验证该算法是否正确。
Arrays.sort(arrcopy);
boolean same = true;
for(int i = 0;i<arrcopy.length;i++){
if(arr[i]!=arrcopy[i]) {
same = false;
System.out.println(arr[i]+" "+arrcopy[i]);
}
}
System.out.println(same==true?"算法正确":"算法错误");
}
}
结果
用时总长:6839
循环次数:2500050000
算法正确
如果哪里有错,希望指出!