/**
*
* 名称: 直接选择排序
* 时间复杂度: O(N^2) 时间复杂度较高一般不选用
* 空间复杂度: O(1)
*
*/
代码实现(每一次只比较交换一个最小值)
public static void main(String[] args) {
int[] array = {8, 3, 10, 2, 7};
selectsort1(array);
System.out.println(Arrays.toString(array));
}
public static void selectsort1(int[] arr){
int tmp = 0;
int minindex = 0;
for (int i = 0; i < arr.length; i++) {
minindex = i;
for (int j = i+1 ; j < arr.length ; j++) {
if(arr[minindex] > arr[j]){
minindex = j;
}
}
tmp = arr[i];
arr[i] = arr[minindex];
arr[minindex] = tmp;
}
}
运行截图
代码实现(每一次比较交换一个最小值和一个最大值) 效率较高但实现有个容易忽视的地方,会出现BUG
public static void main(String[] args) {
int[] array = {8, 3, 10, 2, 7};
selectsort2(array);
System.out.println(Arrays.toString(array));
}
public static void selectsort2(int[] arr){
int left = 0;
int right = arr.length - 1;
int minindex = 0;
int maxindex = 0;
while (left < right){
minindex = left;
maxindex = left;
for (int i = left+1; i <= right; i++) {
if(arr[i] > arr[maxindex]){
maxindex = i;
}
if(arr[i] < arr[minindex]){
minindex = i;
}
}
swap(arr, left, minindex);
swap(arr, right, maxindex);
left++;
right--;
}
}
private static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
运行截图
但是如果换一组数据
将{8, 3, 10, 2, 7} 换为 {12, 1, 2, 5, 71, 4, 8, 2, 3, 5}后再看截图
预期结果应该是 [1, 2, 2, 3, 4, 5, 5, 8, 12, 71 ]
其原因是因为
解决方案 (对max进行下标修正,具体如下)
public static void selectsort2(int[] arr){
int left = 0;
int right = arr.length - 1;
int minindex = 0;
int maxindex = 0;
while (left < right){
minindex = left;
maxindex = left;
for (int i = left+1; i <= right; i++) {
if(arr[i] > arr[maxindex]){
maxindex = i;
}
if(arr[i] < arr[minindex]){
minindex = i;
}
}
swap(arr, left, minindex);
//maxindex 下标修正
if(maxindex == left)
maxindex = minindex;
swap(arr, right, maxindex);
left++;
right--;
}
}
当我们发现在在进行一次for循环后,max的值并没有改变,我们就让max = min,这样无论arr[min]值否与arr[left]进行交换,都可以保证max下标一定是正确的.
运行结果如下
时间复杂度问题
数据是否相对有序对直接选择排序的影响几乎没有,这就导致了如果是一组有序的数据如果选用直接插入排序的效率会比直接选择排序的效率高上许多
如图
//使用有序的相同数据来进行测试,比较直接插入排序和直接选择排序所消耗的时间
public static void main(String[] args) {
int[] array1 = new int[10_0000];
int[] array2 = new int[10_0000];
for (int i = 0; i < array1.length; i++) {
array1[i] = i + 1;
array2[i] = i + 1;
}
long startTime1 = System.currentTimeMillis();
selectsort(array1);
long endTime1 = System.currentTimeMillis();
System.out.println("直接选择排序对相同有序数据进行排序所需要的时间:" + (endTime1 - startTime1));
long startTime2 = System.currentTimeMillis();
InsertSort(array2);
long endTime2 = System.currentTimeMillis();
System.out.println("直接插入排序对相同有序数据进行排序所需要的时间:" + (endTime2 - startTime2));
}
运行截图
//使用无序的相同数据来进行测试,比较直接插入排序和直接选择排序所消耗的时间
public static void main(String[] args) {
int[] array1 = new int[10_0000];
int[] array2 = new int[10_0000];
Random random = new Random();
for (int i = 0; i < array1.length; i++) {
array1[i] = random.nextInt();
}
array2 = Arrays.copyOf(array1, array2.length);
long startTime1 = System.currentTimeMillis();
selectsort(array1);
long endTime1 = System.currentTimeMillis();
System.out.println("直接选择排序对相同有序数据进行排序所需要的时间:" + (endTime1 - startTime1));
long startTime2 = System.currentTimeMillis();
InsertSort(array2);
long endTime2 = System.currentTimeMillis();
System.out.println("直接插入排序对相同有序数据进行排序所需要的时间:" + (endTime2 - startTime2));
}
运行截图
如图可看出鲜明对比差距
至于为什么直接选择排序在处理有序数组时比处理无序数组快其原因并不是应为时间复杂度降低了而是因为少执行了某些代码
如图