Java中三大基本排序算法之选择排序

简介

        选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法

        选择排序相较于冒泡排序,选择排序中进行数据的交换进行了减少,因此效率会有所上升。

为什么选择排序是不稳定的?

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

       简单来说就是排序过后那两个4的前后位置可能会发生改变。

选择排序的思路

        首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

代码实现

public class SelectionSort {
    //选择排序
    public static void main(String[] args) {

        //自定义一个数组并赋值
        int[] arr = {3, 2, 1, 3, 6, 7, 8, 9};
        //调用方法排序
        selectionSort(arr);
        //遍历输出
        for (int i : arr) {
            System.out.print(" " + i);
        }
    }

    public static void selectionSort(int[] nums) {
        //从小到大排序
        for (int i = 0; i < nums.length - 1; i++) {
            //存储起始位下标
            int min = i;
            for (int j = i+1; j < nums.length; j++) {
                //判断数据大小,找到最小值的下标
                if (nums[min] > nums[j]) {
                    min = j;
                }
            }

            //把最小值和起始位的值进行交换
            int temp = nums[i];
            nums[i] = nums[min];
            nums[min] = temp;

        }
    }
}

        上面代码实现的就是用基本的选择排序进行数据处理,外层循环少一次的原因就是当最后排序只剩下一个的时候,那么这个数肯定就是排序规则的最值了。所以可以少循环一次。

代码优化 

        在各种排序算法中,有多种不同的优化,在不同场景也要用不同的优化方案以及不同的排序算法,下面是我对于选择排序的一个小优化,优化方式就是当数据达到某种特殊状态时已经排好序了,那么就不用进行接下来的循环了。如何判断数据是否排好序了呢?

        我们从代码中可以看出,我们把内层循环每次遍历的起始位在外层循环中记录了下来,在内层循环中当满足if判断条件时会进行下标数据从新赋值,记录新的较小值的下标,直到内层循环遍历结束,确定新最小值的下标,进行数据交换。

        所以我们可不可以这样去思考,就是内层循环的条件没有达成过,也就是记录下标的变量的值没有变过,那就表示没有数据要交换,所以可以在if判断里面添加个哨兵,用来判断是否需要进行最值的位置交换。

        第二种思想:既然一次外循环可判断出最小值,那是不是也就可以判断出最大值。所以我们可以在内层循环里面把最大值也判断出来。

        下面是第二种思想的实现:

public class SelectionSort {
    //选择排序
    public static void main(String[] args) {

        //自定义一个数组并赋值
        int[] arr = {3, 2, 1, 3, 6, 7, 8, 9};
        //调用方法排序
        selectionSort2(arr);
        //遍历输出
        for (int i : arr) {
            System.out.print(" " + i);
        }
    }

    public static void selectionSort(int[] nums) {
        //从小到大排序
        for (int i = 0; i < nums.length - 1; i++) {
            //存储起始位下标
            int min = i;
            for (int j = i + 1; j < nums.length; j++) {
                //判断数据大小,找到最小值的下标
                if (nums[min] > nums[j]) {
                    min = j;
                }
            }

            //把最小值和起始位的值进行交换
            int temp = nums[i];
            nums[i] = nums[min];
            nums[min] = temp;

        }
    }

    //优化选择排序
    public static void selectionSort2(int[] arr) {

        for (int i = 0; i < arr.length / 2; i++) {
            int maxIndex = i;//假定最大值的下标
            int max = arr[i];//假定最大值
            int minIndex = arr.length - 1 - i;
            int min = arr[minIndex];
            for (int j = i; j < arr.length - i; j++) {//循环找到最大值
                if (max < arr[j]) {// 说明假定的值不是最大的
                    max = arr[j];// 重置max
                    maxIndex = j;// 重置maxIndex
                }
                if (min > arr[j]) {
                    min = arr[j];
                    minIndex = j;
                }
            }

            // 数据交换
            int temp1 = arr[maxIndex];
            int temp2 = arr[minIndex];
            arr[maxIndex] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp1;
            arr[minIndex] = arr[i];
            arr[i] = temp2;

        }

    }
}

总结 

        总而言之,言而总之,我的理解就是在冒泡排序的思想上,不进行多次的数据交换了,一次外循环直接找出最值,然后放在它该呆的位置。还是比较好理解的。看过后感觉有点点触动就留下个赞赞吧!加油!!!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值