十大排序算法之选择排序

选择排序也是一种O(n ^ 2)时间复杂度的排序算法,选择排序是每一次循环都将找到最小值,依次将最小值、次小值分别从左至右进行排序。以下是具体实现过程,其中使用的工具类这篇博客已经给出,(http://www.javashuo.com/article/p-ngnidmzv-nr.html

import cn.zjut.util.SortTestUtil;

public class SelectSort {
 public void selectSort(int[] arr, int n) {
  int minIndex;                //声明小值索引
  for(int i = 0; i < n; i++) {
   minIndex = i;              //最小值索引初始化为i
   int j;
   for(j = i + 1; j < n; j ++)//内层循环遍历arr[i]之后元素与当前最小值索引进行比较
    if(arr[j] < arr[minIndex]) //如果arr[j]比当前最小值还要小,则将j赋给当前最小值索引
     minIndex = j;
   SortTestUtil.swap(arr, i, minIndex);//将本次循环找到的最小值与排序后应该在的位置上的相应元素交换值
  }
 }
}

这种选择排序,每一次只能找最小值,可以对其进行优化,每一次循环找一个最小值和最大值,头尾同时进行,因此需要两个标定点分别指向头尾元素。以下是优化后的选择排序实现过程

import cn.zjut.util.SortTestUtil;

public class SelectSortImprove {
 public void selectSort(int[] arr, int n) {
  int left = 0, right = n - 1;
  int minIndex, maxIndex;
  while(left < right) {
   minIndex = left;
   maxIndex = right;
   
   //保证每轮搜索时arr[minIndex] <= arr[maxIndex]
   if(arr[minIndex] > arr[maxIndex])
    SortTestUtil.swap(arr, minIndex, maxIndex);
   
   for(int i = left + 1; i < right; i++) {
    if(arr[i] < arr[minIndex])
     minIndex = i;
    else if(arr[i] > arr[maxIndex])
     maxIndex = i;
   }
   SortTestUtil.swap(arr, minIndex, left);
   SortTestUtil.swap(arr, maxIndex, right);
   left++;
   right--;
  }
 }
}

下面是测试代码,测试数据是10000个数据,分别对随机数组,和近乎有序的数组进行测试

import cn.zjut.util.SortTestUtil;

public class Main {

 public static void main(String[] args){
  int n = 10000;
  System.out.println("Test for Random Array, size = " + n + ", random range [0, " + n + ']');
  int[] arr1 = SortTestUtil.generateRandomArray(n, 0, n); 
  int[] arr2 = SortTestUtil.copyIntArray(arr1, n);
  
  SortTestUtil.testSort("SelectSort", "cn.zjut.sort.SelectSort", "selectSort", arr1, n);
  SortTestUtil.testSort("SelectSortImprove", "cn.zjut.sort.SelectSortImprove", "selectSort", arr2, n);

  System.out.println("--------------------------------");
  
  int swapTime = 10;
     System.out.println("Test for Random Nearly Ordered Array, size = " + n + ", swap time = " + swapTime);
     arr1 = SortTestUtil.generateNearlyOrderedArray(n, swapTime);
     arr2 = SortTestUtil.copyIntArray(arr1, n);
   
  SortTestUtil.testSort("SelectSort", "cn.zjut.sort.SelectSort", "selectSort", arr1, n);
  SortTestUtil.testSort("SelectSortImprove", "cn.zjut.sort.SelectSortImprove", "selectSort", arr2, n);
 }
}

测试结果如下

 

根据结果,双路选择排序时间效率优于简单选择排序 。以上整个过程就是选择排序的实现过程。