【Java排序算法】选择排序

选择排序

选择排序算法的基本思路是为每一个位置选择当前最小的元素。选择排序的基本思想是,基于直接选择排序和堆排序这两种基本的简单排序方法。首先从第1个位置开始对全部元素进行选择,选出全部元素中最小的给该位置,再对第2个位置进行选择,在剩余元素中选择最小的给该位置即可,以此类推。

选择排序图解

在这里插入图片描述

原理及思路

每次循环时在待排序列中找出最小值,将其与待排序列头元素进行交换

  • 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,
  • 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。
  • 以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
排序的效率
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1) -> 未新开辟内存
算法稳定性

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。

选择排序的优化

每次循环时在待排序列中找出最小值和最大值,将最小值与左下标进行交换,将最大值与右下标进行交换。

此处的优化仅仅减少了在找值的时候的次数,对整体时间复杂度没有影响

代码实现
private static <T>  void swap(T[] arr,int index1,int index2){
    T temp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = temp;
}
//一般性选择排序,只在序列中找最小值
public static <T extends Comparable<T>> void selectSort(T[] arr){
    if(arr == null || arr.length == 0 || arr.length == 1){
        return;
    }
    //遍历整个数组
    for(int i = 0;i < arr.length;i++){
        //定义最小值下标为待排序列头元素下标
        int minIndex = i;
        //进行判断更换最小值下标
        for(int j = i;j < arr.length;j++){
            //如果遇到比目前最小值下标元素还小的进行更新最小值下标
            if(arr[minIndex].compareTo(arr[j]) > 0){
                minIndex = j;
            }
        }
        //将其值与待排序列头元素进行交换
        swap(arr,minIndex,i);
    }
}
//优化性选择排序,在序列中寻找最小值和最大值
public static <T extends Comparable<T>> void selectSortToOptimize(T[] arr){
    if(arr == null || arr.length == 0 || arr.length == 1){
        return;
    }
    //定义左下标和右下标
    int left = 0,right = arr.length - 1;
    while (left < right) {
        //初始化最小值下标和最大值下标
        int minIndex = left,maxIndex = left;
        //遍历待排序列进行找值
        for (int i = left; i <= right; i++) {
            //如果遇到比目前最小值下标元素还小的进行更新最小值下标
            if(arr[minIndex].compareTo(arr[i]) > 0){
                minIndex = i;
            }
            //如果遇到比目前最大值下标元素还大的进行更新最大值下标
            if(arr[maxIndex].compareTo(arr[i]) < 0){
                maxIndex = i;
            }
        }
        //此处进行数据交换
        //注意特殊情况
        //如果最大值下标在左下标处,最小值下标在右下标处,直接交换最小值下标和最大值下标元素
        if(minIndex == right && maxIndex == left){
            swap(arr,minIndex,maxIndex);
        }else {
            //否则将最小值与左下标进行交换,将最大值与右下标进行交换
            swap(arr, minIndex, left);
            //此处存在另一种特殊情况
            // -> 如果最大值下标在左下标处或者最小值下标在右下标处,有可能进行重复交换,所以进行判断
            if(arr[minIndex].compareTo(arr[maxIndex]) < 0) {
                swap(arr, maxIndex, right);
            }
        }
        //更新左下标和右下标
        left++;right--;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值