10大排序算法之一:选择排序【不稳定】,一般不用选择排序的

10大排序算法之一:选择排序【不稳定】,一般不用选择排序的

提示:整个算法界,一共有十大排序算法,每一个算法都要熟悉,才算是算法入门

算法界的十大排序算法分别是:
选择排序、冒泡排序、插入排序、堆排序、希尔排序、归并排序、快速排序、桶排序、计数排序,基数排序
在这里插入图片描述
如果你想进互联网大厂,至少这上面的其中最重要的8种,是必须熟练掌握的:
去掉希尔排序,希尔排序是一种改进的插入排序算法——所以只需要掌握插入排序
桶排序中最重要的就是计数排序和基数排序,都是桶的思想
在这里插入图片描述
根据算法复杂度低一点的,又稳定的
咱们可以最常用的算法实际上就四种:
插入排序(o(n^2))【当数据量小时,这个方法简单】【稳定】、
堆排序o(nlog(n))【不稳定】、
归并排序o(nlog(n))【稳定】,
快速排序o(nlog(n))(虽然快排不稳定,但是很多不需要稳定情况下,快排非常快)
因此,o(n)的桶排序很少用,除非面试官特别申明,否则都用比较排序。
归并排序是最常用的,复杂度低,而且稳定,达到了一个非常好的折中。


题目

今天先讲:选择排序
arr有N个数字,请你将其排序(升序);


一、选择排序的思想

首先,从0–N-1范围内选择最小的数,交换到0位置;
然后,从1–N-1范围内选择最小的数,交换到1位置;
然后,从2–N-1范围内选择最小的数,交换到2位置;
……
然后,从N-1–N-1范围内选择最小的数,交换到N-1位置;

啥意思?比如:arr=1 3 2 6 5 4
在这里插入图片描述
i从0–N-1遍历arr:
每一次从j=i–N-1找min的位置k
如果min比i小,交换i和k位置的数,让min去最左边

直到最后,每一次都把最小的值放到最左边,自然,就排序好了

看代码:

//复习选择排序
    public static void chooseSortReview(int[] arr){
        if (arr == null || arr.length < 2) return;

        int N = arr.length;
        //从i遍历
        //枚举j从i--N-1范围,找min,有就交换i位置和min
        for (int i = 0; i < N; i++) {
            //令目前i位置就是min
            int minPos = i;
            for (int j = i; j < N; j++) {
                //每次找是否还有更小的位置:
                if (arr[j] < arr[i]) minPos = j;//更新
            }
            if (i != minPos) swap(arr, i, minPos);//确实有比i更小的,交换它的位置
            //否则不管
        }
    }

    //常用的交换数组函数
    public static void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

显然,时间复杂度是o(n^2),
为啥呢,i遍历一遍N个元素,每个元素下的j要遍历N下
那你说为啥最后一趟,j只遍历了1下,你凭啥算N下呢?
注意,记住,我们说时间复杂度,要算最坏的情况!!!,所以,第一趟就要遍历N*N,即o(n^2)

如果遇到2个一样的数,可能位置会被调开
下面处在最前面的5,被选择排序,调到最后去了,5 5 5 的相对顺序被改变,则就是不稳定!!!!
如果相同的数字在同一个数组中,排序到最后他们的相对位置没变,那就是稳定的
在这里插入图片描述
如果下面这样就算是稳定的:
也就是黑5,绿5,红5,相对的位置,排序之后,仍然是黑5,绿5,红5,没变的话,就是稳定的排序算法。
在这里插入图片描述

因此,十大排序算法之1:选择排序,时间复杂度o(n^2),不稳定,
这是最差劲的排序算法,系统中不会用的。做个了解即可。

你怎么判断你写得算法代码对,还是不对呢?
左神教我们用对数器验证

所谓对数器,就是写一个绝对正确的代码:要么是系统的自带函数,那是必须绝对正确的,要么暴力解,暴力解就能保证对
也就是说,方法一是绝对对的
你的方法是优化方法2

每次操作,输出一组结果或者一个结果,你随机生成一些数据,拿绝对正确的方法1和你的方法2的结果来对比,有错就说明你的方法不对
如果验证了很多随机输入,输出都没有差异,那必然你的方法是对的

这就是对数器!!!
在这里插入图片描述

对于本题:对数器非常好写,显然就系统函数排序,天然绝对正确啊!

Arrays.sort(arr);

怎么造随机数组:
Math函数中
Math.random()可以生成0–1的随机数
(int)(maxValue * Math.random());//0-N-1的随机数,×最大的maxValve
不妨设maxValue =10,那(int)10*Math.random()就是0–9的随机数
这个就很简单了

对数器如下:

//对数器之构建随机数组
    public static int[] createArray(int arrSize, int maxValue){
        int[] arr = new int[arrSize];
        for (int i = 0; i < arrSize; i++) {
            arr[i] = (int)(maxValue * Math.random());//0-N-1的随机数,×最大的maxValve
        }
        return arr;
    }

    public static void checker(){
        //生成检验数组
        int[] arr = createArray(10000,10000);
        int[] arr2 = new int[arr.length];//赋值同样一个数组arr
        for (int i = 0; i < arr.length; i++) {
            arr2[i] = arr[i];//copy即可
        }
        int[] arr3 = new int[arr.length];//赋值同样一个数组arr
        for (int i = 0; i < arr.length; i++) {
            arr3[i] = arr[i];//copy即可
        }

        //绝对的正确方法——暴力方法,或系统函数,操作arr
        //对数器,校验,不对报错
        Arrays.sort(arr);
        //优化方法,操作arr2
        chooseSort(arr2);
        //复习,我写的选择排序代码,操作arr3
        chooseSort(arr3);

        //然后两个数组对位校验
        boolean isSame = true;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] != arr2[i]) {
                isSame = false;
                break;//只要有一个不等,不必继续判断了
            }
        }
        System.out.println(isSame == false ? "oops,wrong!" : "right!");

        //然后两个数组对位校验
        boolean isSame2 = true;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] != arr2[i]) {
                isSame2 = false;
                break;//只要有一个不等,不必继续判断了
            }
        }
        System.out.println(isSame2 == false ? "oops,wrong!" : "right!");
    }

测试代码:

//psvm固然可以直接生成main函数,快捷,但是刷题的界面有没有很难说,
    // 我看看LeetCode,它只已经给定了函数了,只需要写算法,不过真实的企业面试可能没有这么便捷
    //所以建议今后还是一五一十的手敲代码
    public static void main(String[] args){
        //但凡遇到一个算法,一定先写对数器,再写优化算法,这样可保证算法的可靠性。
        checker();
    }

总结

提示:重要经验:

1)十大排序算法,其8必须掌握,他们的时间复杂度分为为o(n^2),o(nlog(n)),o(n+k)=o(n)
2)今天将的选择排序,就是选择最小值放在最左边。了解了核心思想,写代码不是问题。
3)你会再牛的算法也没关系,但是你要是疏忽了最基础的这些算法,恐怕你就麻烦了,根基不牢地动山摇!!!!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值