• 原地排序算法


    1、选择排序

      参考算法:每一轮循环都选择出当前范围最大值,然后从右到左开始占位存储

        第一轮循环

          1)从数组0~N中选择出最大,与索引位0的数进行交换。

        第二轮循环

          1)从数组中1~N选择出最大,与索引位1的数进行交换。

          2)……

        第N-1轮循环

          3)从数组N-1~N中选择出最大,与索引位N-1的数进行交换。   

      时间复杂度:

       1)交换操作0~N-1次;最好的情况:已经有序,O(0)。最差的情况每次比较都需要交换O(N-1)

         2)比较操作(N-1)+(N-2)+(N-3)+……+(N+1-N)次【等差数列】O(n^2)

        N*(N-1)/2

          3)不稳定性:个人感觉是指交换操作在值相等的情况下,是不需要操作的。以后有更深的理解后再看。如果当前值已经在排序后的位置上,那么也不需要交换

      示例:

        2 5 3 1 3 8 -> 索引0和6位置交换

            8 5 3 1 3 2 -> 不变

        8 5 3 1 3 2 -> 不变

        8 5 3 3 1 2 -> 索引3和4位置交换

        8 5 3 3 2 1 -> 索引4和5位置交换

      代码示例:

      

         // 从0~N选出一个最小的值放到0索引位置
            // 从1~N选出一个最小的值放到1索引位置
            // ……
            // 第一层循环,N-1次循环
            for (int i = 0; i < arr.length - 1; i++) {
                int min = arr[i];
                int idx = i;
                // 第二次循环N阶减次循环,可以理解为从左开始占位,每次占1位用于存储当前范围内的最小值
                for (int i1 = i + 1; i1 < arr.length; i1++) {
                    if (arr[i1] < min) {
                        min = arr[i1];
                        idx = i1;
                    }
                }
                if (idx != i) {
                    arr[idx] = arr[i];
                    arr[i] = min;
                }
            }

    2、冒泡排序

      参考算法:每一轮循环都不断比较数组中的左右值,大的往右冒,一轮结束,最右侧为当前最大,特点是每次比较都可能包含交换

        第一轮循环

          1)索引位置0和索引位置1比较,左边大于右边,则交换

          2)索引位置1和索引位置2比较,左边大于右边,则交换

          3)……

          4)索引位置N-2和索引位置N-1比较,左边大于右边,则交换

        第二轮循环

          1)索引位置0和索引位置1比较,左边大于右边,则交换

          2)索引位置1和索引位置2比较,左边大于右边,则交换

          3)……

          4)索引位置N-3和索引位置N-2比较,左边大于右边,则交换

          ……

        第N-1轮循环

          1)索引位置0和索引位置1比较,左边大于右边,则交换 

      时间复杂度:

        1)交换操作0~(N-1)+(N-2)+(N-3)+……+1 ->  套用上面的结果 N*(N-1)/2

        2)比较操作(N-1)+(N-2)+(N-3)+……+1      ->  N*(N-1)/2

        3)不稳定性,也是交换上面,有些是不需要交换的

      示例:

        2 5 3 1 3 8

            2 5 3 1 3 8 -> 不变

        2 3 5 1 3 8 -> 索引1和2的位置交换

        2 3 1 5 3 8 -> 索引3和4位置交换

        2 3 1 3 5 8 -> 索引4和5位置交换

        2 3 1 3 5 8 -> 不变

        2 3 1 3 5 8 -> 不变

        2 1 3 3 5 8 -> 索引1和2的位置交换

        2 1 3 3 5 8 -> 不变

        2 1 3 3 5 8 -> 不变

        1 2 3 3 5 8 -> 索引0和1的位置交换

        1 2 3 3 5 8 -> 不变

        ……

        1 2 3 3 5 8 -> 不变

      代码示例:

            // N-1外层循环
            for (int i = 0; i < arr.length - 1; i++) {
                // N-1递减循环,最右侧不断占位
                for (int j = 0; j < arr.length - 1 - i; j++) {
                    if (arr[j] > arr[j + 1]) {
                        int tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                    }
                }
            }    

    3、插入排序(模拟扑克牌的排序原则,抽到一张牌之后找到合适的位置插入)

      参考算法:从第二个数值开始往左比较,如果右值小于左值,则交换。一直判断到最左侧。再开始下一轮循环。则左侧一部分始终保持有序。

        由于索引位置0必为有序,所以不处理

        第一轮循环

          1)从索引1位置开始与索引0位置比较,小于则交换

        第二轮循环

          1)从索引2位置与索引1位置比较,小于则交换

          2)从索引1位置开始与索引0位置比较,小于则交换

        第三轮循环

          1)从索引3位置与索引2位置比较,小于则交换

          2)从索引2位置开始与索引1位置比较,小于则交换

          3)从索引1位置开始与索引0位置比较,小于则交换

        ……

        第N-1轮循环

          1)从索引N-1位置与索引N-2位置比较,小于则交换

          2)从索引N-2位置与索引N-2位置比较,小于则交换

          ……

          N-1)从索引1位置与索引0位置比较,小于则交换

      时间复杂度:

        1)交换操作:0~(0+1+2+3+……+N-1) -> 0~(N*(N-1)/2)

        2)比较操作:N-1~(0+1+2+3+……+N-1) -> (N*(N-1)/2)。当左值始终比右值大的情况下,就不需要继续向左比较了,所以最好的情况下是每一轮循环值需要做一次比较的情况

        3)不稳定性:如果数值正好处于最终排序后的位置,则当前循环可以不必向左比较和交换。此特性在数组已经有部分排好序的情况下,将提升效率

      示例:

        2 5 3 1 3 8

        2 5 3 1 3 8 

        2 3 5 1 3 8

        2 3 1 5 3 8 

        2 1 3 5 3 8 

        1 2 3 5 3 8

        1 2 3 3 5 8

        1 2 3 3 5 8

      代码示例:

            // 从1开始,进行N-1次循环
            for (int i = 1; i < arr.length; i++) {
                // 从当前比较的值索引位开始,向左比较
                for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
            }    
  • 相关阅读:
    2020 CCPC Wannafly Winter Camp Day2 K题 破忒头的匿名信(AC自动机+dp)
    CF1446C Xor Tree(01Trie)
    day04---系统重要文件
    day03--vi和vim快捷方式及操作系统目录介绍
    day02---虚拟机上网模式
    day01---操作系统安装环境准备
    django中一些快捷函数
    django中的一些装饰器用法
    auth模块的一些方法
    celery中异步延迟执行任务apply_anysc的用法
  • 原文地址:https://www.cnblogs.com/gabin/p/15931102.html
Copyright © 2020-2023  润新知