八大排序之选择排序

一、基本思想

   每次从待排记录中选出最小值放在有序记录的末尾。等每一个待排元素均被选出后,整个记录排序就完成了。

二、实现步骤

     这里采用双向选择排序,每次从待排记录中选出最大值和最小值,最大值和待排记录的最后一位交换位置,最小值和待排记录的第一位交换位置。

  注意,交换位置分如下情况:

  1)最大值在最左边,最小值在最右边。直接将最大值最小值相互交换即可。

   

  2)最大值在最左边,最小值在中间。必须先将最大值与最后一位交换,再将最小值与第一位交换。否则会出错,不信就试试。

             

  3)最大值在中间,最小值在中间。随意谁先交换都行。

           

  4)最小值在最右边,最大值在中间。必须先将最小值与第一位交换,再将最大值与最后一位交换。

              

  5)最小值在最右边,最大值在最左边。不用交换。

       

  

   对于上述5种情况,其实可以简化成如下情况来做。

  一、如果max在最左边,

        如果min在最右边,两者直接交换

        否则,先交换max,再交换min

  二、其他情况一律先交换min,再交换max。

  max在最左,min在最右这种情况,由于两次交换,等同于没交换,所以不会出现错误。

三、实现代码

测试工具类 点击这里

package sort;

import sort.util.*;

/*
    选择排序思路:
    选择待排记录中最小值,放在左边
    双向选择,一次遍历中选出最大值放在右边,选出最小值放在左边
    
    时间复杂度:O(n2)
    空间复杂度:O(1)
    稳定性:    稳定
*/
public class SelectSort implements ISort{
    
    public void sort(int[] a) {
        int n = a.length;
        for(int i = 0; i < n / 2; i++) {
            int maxId = i;
            int minId = i;
            for(int j = i; j <= n - i - 1; j++) {
                if(a[j] > a[maxId]) {maxId = j;}
                if(a[j] < a[minId]) {minId = j;}
            }
                                                                     //根据maxId的位置走不同的交换顺序
            int t = 0;
            if(maxId == i){
                if(minId == n - 1 - i) {
                    t = a[maxId]; a[maxId] = a[minId]; a[minId] = t; //max和min位于相反的位置上,直接将其交换
                }else{                                               
                    t = a[maxId]; a[maxId] = a[n-1-i]; a[n-1-i] = t; //max位于最左,先交换max
                    t = a[minId]; a[minId] = a[i];     a[i] = t;     //再交换min
                }                
            }else{                                                  
                t = a[minId]; a[minId] = a[i];     a[i] = t;         //min位于最右和其他情况,先交换min
                t = a[maxId]; a[maxId] = a[n-1-i]; a[n-1-i] = t;
            }
        }
    }
    
    
    public static void main(String[] args) {
        int[] array = RandomArrayGenerator.getRandomArray(100 , 30);
        SortTestHelper.test(new SelectSort() , array);
    }
}

测试结果:

四、总结分析

  时间复杂度:O(n2)

  空间复杂度:O(1)

  选择排序是一种比较直观易懂的排序算法,时间复杂度不理想,但几乎不占空间。下篇将展示选择排序的改进算法 ----- 堆排序。

原文地址:https://www.cnblogs.com/wanghang-learning/p/9202899.html