八大基础排序总结

BOOST电路分析与计算 Boost电路设计,电感、输入输出电容选型计算 阅读详情

前言

大概花了一周的时间把八大基础排序过了一遍,这篇博文主要是用来回顾一下八大基础排序的要点和一些总结~

回顾:

总的来说:快速排序是用得比较广泛的一个排序,也是经常出现的一个排序,应该重点掌握~

二、八大排序总结

2.1冒泡排序

思路:

  • 俩俩交换,大的放在后面,第一次排序后最大值已在数组末尾。
  • 因为俩俩交换,需要n-1趟排序,比如10个数,需要9趟排序

代码实现要点:

  • 两个for循环,外层循环控制排序的趟数,内层循环控制比较的次数
    • 每趟过后,比较的次数都应该要减1
  • 优化:如果一趟排序后也没有交换位置,那么该数组已有序~


    //外层循环是排序的趟数
    for (int i = 0; i < arrays.length -1 ; i++) {

        //每比较一趟就重新初始化为0
        isChange = 0;

        //内层循环是当前趟数需要比较的次数
        for (int j = 0; j < arrays.length - i - 1; j++) {

            //前一位与后一位与前一位比较,如果前一位比后一位要大,那么交换
            if (arrays[j] > arrays[j + 1]) {
                temp = arrays[j];
                arrays[j] = arrays[j + 1];
                arrays[j + 1] = temp;


                //如果进到这里面了,说明发生置换了
                isChange = 1;

            }
        }
        //如果比较完一趟没有发生置换,那么说明已经排好序了,不需要再执行下去了
        if (isChange == 0) {
            break;
        }

    }
    System.out.println("公众号Java3y" + arrays);

2.2选择排序

思路:

  • 找到数组中最大的元素,与数组最后一位元素交换
  • 当只有一个数时,则不需要选择了,因此需要n-1趟排序,比如10个数,需要9趟排序

代码实现要点:

  • 两个for循环,外层循环控制排序的趟数,内层循环找到当前趟数的最大值,随后与当前趟数组最后的一位元素交换

    //外层循环控制需要排序的趟数
    for (int i = 0; i < arrays.length - 1; i++) {

        //新的趟数、将角标重新赋值为0
        pos = 0;

        //内层循环控制遍历数组的个数并得到最大数的角标
        for (int j = 0; j < arrays.length - i; j++) {

            if (arrays[j] > arrays[pos]) {
                pos = j;
            }

        }
        //交换
        temp = arrays[pos];
        arrays[pos] = arrays[arrays.length - 1 - i];
        arrays[arrays.length - 1 - i] = temp;


    }

    System.out.println("公众号Java3y" + arrays);

2.3插入排序

思路:

  • 将一个元素插入到已有序的数组中,在初始时未知是否存在有序的数据,因此将元素第一个元素看成是有序的
  • 与有序的数组进行比较,比它大则直接放入,比它小则移动数组元素的位置,找到个合适的位置插入
  • 当只有一个数时,则不需要插入了,因此需要n-1趟排序,比如10个数,需要9趟排序

代码实现:

  • 一个for循环内嵌一个while循环实现,外层for循环控制需要排序的趟数,while循环找到合适的插入位置(并且插入的位置不能小于0)


    //临时变量
    int temp;

    //外层循环控制需要排序的趟数(从1开始因为将第0位看成了有序数据)
    for (int i = 1; i < arrays.length; i++) {

        temp = arrays[i];

        //如果前一位(已排序的数据)比当前数据要大,那么就进入循环比较[参考第二趟排序]
        while (i >= 1 && arrays[i - 1] > temp) {

            //往后退一个位置,让当前数据与之前前位进行比较
            arrays[i] = arrays[i - 1];

            //不断往前,直到退出循环
            i--;

        }

        //退出了循环说明找到了合适的位置了,将当前数据插入合适的位置中
        arrays[i] = temp;

    }
    System.out.println("公众号Java3y" + arrays);

2.4快速排序

思路:

  • 在数组中找一个元素(节点),比它小的放在节点的左边,比它大的放在节点右边。一趟下来,比节点小的在左边,比节点大的在右边。
  • 不断执行这个操作….

代码实现:

  • 快速排序用递归比较好写【如果不太熟悉递归的同学可到:递归就这么简单】。支点取中间,使用L和R表示数组的最小和最大位置
    • 不断进行比较,直到找到比支点小(大)的数,随后交换,不断减小范围~
  • 递归L到支点前一个元素(j)(执行相同的操作,同上)
  • 递归支点后一个元素(i)到R元素(执行相同的操作,同上)


/**
 * 快速排序
 *
 * @param arr
 * @param L   指向数组第一个元素
 * @param R   指向数组最后一个元素
 */
public static void quickSort(int[] arr, int L, int R) {
    int i = L;
    int j = R;

    //支点
    int pivot = arr[(L + R) / 2];

    //左右两端进行扫描,只要两端还没有交替,就一直扫描
    while (i <= j) {

        //寻找直到比支点大的数
        while (pivot > arr[i])
            i++;

        //寻找直到比支点小的数
        while (pivot < arr[j])
            j--;

        //此时已经分别找到了比支点小的数(右边)、比支点大的数(左边),它们进行交换
        if (i <= j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
    }
    //上面一个while保证了第一趟排序支点的左边比支点小,支点的右边比支点大了。


    //“左边”再做排序,直到左边剩下一个数(递归出口)
    if (L < j)
        quickSort(arr, L, j);

    //“右边”再做排序,直到右边剩下一个数(递归出口)
    if (i < R)
        quickSort(arr, i, R);
}

2.5归并排序

思路:

  • 将两个已排好序的数组合并成一个有序的数组。
    • 将元素分隔开来,看成是有序的数组,进行比较合并
    • 不断拆分和合并,直到只有一个元素

代码实现:

  • 在第一趟排序时实质是两个元素(看成是两个已有序的数组)来进行合并,不断执行这样的操作,最终数组有序
  • 拆分左边,右边,合并…

    public static void main(String[] args) {
        int[] arrays = {9, 2, 5, 1, 3, 2, 9, 5, 2, 1, 8};
        mergeSort(arrays, 0, arrays.length - 1);

        System.out.println("公众号:Java3y" + arrays);


    }

    /**
     * 归并排序
     *
     * @param arrays
     * @param L      指向数组第一个元素
     * @param R      指向数组最后一个元素
     */
    public static void mergeSort(int[] arrays, int L, int R) {

        //如果只有一个元素,那就不用排序了
        if (L == R) {
            return;
        } else {

            //取中间的数,进行拆分
            int M = (L + R) / 2;

            //左边的数不断进行拆分
            mergeSort(arrays, L, M);

            //右边的数不断进行拆分
            mergeSort(arrays, M + 1, R);

            //合并
            merge(arrays, L, M + 1, R);

        }
    }


    /**
     * 合并数组
     *
     * @param arrays
     * @param L      指向数组第一个元素
     * @param M      指向数组分隔的元素
     * @param R      指向数组最后的元素
     */
    public static void merge(int[] arrays, int L, int M, int R) {

        //左边的数组的大小
        int[] leftArray = new int[M - L];

        //右边的数组大小
        int[] rightArray = new int[R - M + 1];

        //往这两个数组填充数据
        for (int i = L; i < M; i++) {
            leftArray[i - L] = arrays[i];
        }
        for (int i = M; i <= R; i++) {
            rightArray[i - M] = arrays[i];
        }


        int i = 0, j = 0;
        // arrays数组的第一个元素
        int  k = L;


        //比较这两个数组的值,哪个小,就往数组上放
        while (i < leftArray.length && j < rightArray.length) {

            //谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个
            if (leftArray[i] < rightArray[j]) {
                arrays[k] = leftArray[i];

                i++;
                k++;
            } else {
                arrays[k] = rightArray[j];
                j++;
                k++;
            }
        }

        //如果左边的数组还没比较完,右边的数都已经完了,那么将左边的数抄到大数组中(剩下的都是大数字)
        while (i < leftArray.length) {
            arrays[k] = leftArray[i];

            i++;
            k++;
        }
        //如果右边的数组还没比较完,左边的数都已经完了,那么将右边的数抄到大数组中(剩下的都是大数字)
        while (j < rightArray.length) {
            arrays[k] = rightArray[j];

            k++;
            j++;
        }
    }

2.6堆排序

思路:

  • 堆排序使用到了完全二叉树的一个特性【不了解二叉树的同学可到:二叉树就这么简单学习一波】,根节点比左孩子和右孩子都要大,完成一次建堆的操作实质上是比较根节点和左孩子、右孩子的大小,大的交换到根节点上,直至最大的节点在树顶
  • 随后与数组最后一位元素进行交换
  • ……

代码实现:

  • 只要左子树或右子树大于当前根节点,则替换。替换后会导致下面的子树发生了变化,因此同样需要进行比较,直至各个节点实现父>子这么一个条件


public static void main(String[] args) {

    int[] arrays = {6, 3, 8, 7, 5, 1, 2, 23, 4321, 432, 3,2,34234,2134,1234,5,132423, 234, 4, 2, 4, 1, 5, 2, 5};

    for (int i = 0; i < arrays.length; i++) {

        //每完成一次建堆就可以排除一个元素了
        maxHeapify(arrays, arrays.length - i);

        //交换
        int temp = arrays[0];
        arrays[0] = arrays[(arrays.length - 1) - i];
        arrays[(arrays.length - 1) - i] = temp;

    }

    System.out.println("公众号:Java3y" + arrays);


}

/**
 * 完成一次建堆,最大值在堆的顶部(根节点)
 */
public static void maxHeapify(int[] arrays, int size) {

    for (int i = size - 1; i >= 0; i--) {
        heapify(arrays, i, size);
    }

}


/**
 * 建堆
 *
 * @param arrays          看作是完全二叉树
 * @param currentRootNode 当前父节点位置
 * @param size            节点总数
 */
public static void heapify(int[] arrays, int currentRootNode, int size) {

    if (currentRootNode < size) {
        //左子树和右字数的位置
        int left = 2 * currentRootNode + 1;
        int right = 2 * currentRootNode + 2;

        //把当前父节点位置看成是最大的
        int max = currentRootNode;

        if (left < size) {
            //如果比当前根元素要大,记录它的位置
            if (arrays[max] < arrays[left]) {
                max = left;
            }
        }
        if (right < size) {
            //如果比当前根元素要大,记录它的位置
            if (arrays[max] < arrays[right]) {
                max = right;
            }
        }
        //如果最大的不是根元素位置,那么就交换
        if (max != currentRootNode) {
            int temp = arrays[max];
            arrays[max] = arrays[currentRootNode];
            arrays[currentRootNode] = temp;

            //继续比较,直到完成一次建堆
            heapify(arrays, max, size);
        }
    }
}

2.7希尔排序

思路:

  • 希尔排序实质上就是插入排序的增强版,希尔排序将数组分隔成n组来进行插入排序,直至该数组宏观上有序,最后再进行插入排序时就不用移动那么多次位置了~

代码思路:

  • 希尔增量一般是gap = gap / 2,只是比普通版插入排序多了这么一个for循环罢了,难度并不大

   /**
     * 希尔排序
     *
     * @param arrays
     */
    public static void shellSort(int[] arrays) {


        //增量每次都/2
        for (int step = arrays.length / 2; step > 0; step /= 2) {

            //从增量那组开始进行插入排序,直至完毕
            for (int i = step; i < arrays.length; i++) {

                int j = i;
                int temp = arrays[j];

                // j - step 就是代表与它同组隔壁的元素
                while (j - step >= 0 && arrays[j - step] > temp) {
                    arrays[j] = arrays[j - step];
                    j = j - step;
                }
                arrays[j] = temp;
            }
        }


    }

2.8基数排序

思路:

  • 基数排序(桶排序):将数字切割成个、十、百、千位放入到不同的桶子里,放一次就按桶子顺序回收一次,直至最大位数的数字放完~那么该数组就有序了

代码实现:

  • 先找到数组的最大值,然后根据最大值/10来作为循环的条件(只要>0,那么就说明还有位数)
  • 将个位、十位、…分配到桶子上,每分配一次就回收一次


    public static void main(String[] args) {

        int[] arrays = {6, 4322, 432, 344, 55, 234, 45, 243, 5, 2, 4, 5, 6, 7, 3245, 345, 345, 234, 68, 65};

        radixSort(arrays);

        System.out.println("公众号:Java3y" + arrays);

    }

    public static void radixSort(int[] arrays) {

        int max = findMax(arrays, 0, arrays.length - 1);

        //需要遍历的次数由数组最大值的位数来决定
        for (int i = 1; max / i > 0; i = i * 10) {

            int[][] buckets = new int[arrays.length][10];

            //获取每一位数字(个、十、百、千位...分配到桶子里)
            for (int j = 0; j < arrays.length; j++) {

                int num = (arrays[j] / i) % 10;

                //将其放入桶子里
                buckets[j][num] = arrays[j];
            }

            //回收桶子里的元素
            int k = 0;

            //有10个桶子
            for (int j = 0; j < 10; j++) {
                //对每个桶子里的元素进行回收
                for (int l = 0; l < arrays.length ; l++) {

                    //如果桶子里面有元素就回收(数据初始化会为0)
                    if (buckets[l][j] != 0) {
                        arrays[k++] = buckets[l][j];

                    }

                }

            }

        }
    }


    /**
     * 递归,找出数组最大的值
     *
     * @param arrays 数组
     * @param L      左边界,第一个数
     * @param R      右边界,数组的长度
     * @return
     */

    public static int findMax(int[] arrays, int L, int R) {

        //如果该数组只有一个数,那么最大的就是该数组第一个值了
        if (L == R) {
            return arrays[L];
        } else {

            int a = arrays[L];
            int b = findMax(arrays, L + 1, R);//找出整体的最大值

            if (a > b) {
                return a;
            } else {
                return b;
            }
        }
    }

三、总结

对于排序的时间复杂度和稳定性网上的图也很多很多,我就随便找一张了(侵删)

要是对某个排序不太理解的同学最好是到我写的单个文章中进行查阅,因为有分解的步骤~

我也将代码(包括分解过程)上传到了GitHub上了,算法和数据结构的代码我都往上面放了,欢迎star~后序还会写栈、队列相关的博文,敬请期待…

休闲时间:

参考资料:

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y

Boost电路占空比工程设计:从CCM/DCM边界到7项非理想补偿 Boost变换器占空比是开关电源设计的核心参数,其本质是能量传递的时间配额,受连续导通模式(CCM)与断续导通模式(DCM)切换、伏秒平衡原理及系统效率共同约束。在实际工程中,理想公式D=1−V_in/V_out因忽略二极管压降、MOSFET导通损耗、PCB走线电阻等非理想因素而严重失准,导致稳压失效、轻载震荡或高温掉压。本文聚焦Boost电路的占空比动态建模与实测修正,结合伏秒平衡法与功率守恒法,量化分析CCM/DCM临界电流、效率η影响、死区时间损失等关键因子,提供可落地的7项工程补偿项。适用于车载电源 阅读详情

相关推荐

从零到一:用AXI DataMover在Zynq MPSoC上实现高效DMA传输(附Vitis HLS驱动示例)

本文详细介绍了如何在Xilinx Zynq UltraScale+ MPSoC平台上使用AXI DataMover实现高效的DMA数据传输。通过解析AXI DataMover架构、Vivado工程配置、Vitis HLS驱动开发及性能优化技巧,帮助开发者快速构建高性能数据传输通道,并提供了可直接复用的代码示例。

weixin_42520796的博客 425

常见八大排序详解

冒泡排序: 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。 作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交

qq_56999918的博客 3万+

DELL SC存储扩容避坑指南:6Gb vs 12Gb扩展柜混插的真相

本文深入解析DELL SC存储扩容中6Gb与12Gb扩展柜混插的核心规则与性能影响。文章指出,从SCOS 7.3版本起允许混插,但整个SAS环路速率将降至最低设备水平,尤其在12Gb控制器上接入6Gb扩展柜会严重拖累性能。指南提供了清晰的兼容性矩阵、实战操作流程及关键避坑清单,帮助管理员安全、高效地完成存储扩容。

weixin_28314575的博客 459

八大基本排序方法

介绍了比较常见的八种排序的思想及实现

Masquerena114514的博客 4476

TSMC65nm工艺下Virtuoso仿真gm-id曲线的保姆级教程(含ADE设置详解)

本文提供了一份在TSMC 65nm工艺下使用Cadence Virtuoso绘制gm-id曲线的详细教程。内容涵盖从理解gm/id方法学、搭建仿真环境、深度解析ADE设置,到运行DC仿真、提取数据并生成对数坐标曲线的完整流程。教程重点解析了Virtuoso ADE中的关键设置与常见避坑点,旨在帮助模拟集成电路设计初学者快速掌握这一核心设计工具,为高性能电路设计奠定基础。

grpc6streamer的博客 1173

UBUNTU使用RTL8811CU网卡(包含树莓派)

下载驱动 从绿联中下载:链接 下载解压后,chmod Linux文件夹 sudo chmod -R 777 ./Linux/ 修改系统的BOOT Secure为disable,参考链接:链接 sudo apt install mokutil sudo mokutil --disable-validation 重启电脑后,按照提示选择change secure boot state,并输入对应的字母(并不是全部密码,而是第几个),选择disable即可 进入Linux文件夹,运行命令 ..

Hot_Ant的博客 6246

三大基础排序算法

本文介绍三种最简单的排序算法:1.冒泡排序;2.选择排序;3.插入排序

secretboys的博客 1790

从机械到数字:EC11旋转编码器与ESP32的PWM控制艺术

本文详细解析了EC11旋转编码器与ESP32的PWM控制技术,探讨了如何将机械旋转动作转换为精确的数字信号控制。通过硬件连接、信号处理和软件优化等实践技巧,开发者可以构建高效的人机交互系统,适用于智能照明、电机控制等多种应用场景。

android的专栏 785

八大基础排序算法

八大基础排序算法冒泡排序选择排序插入排序快速排序归并排序希尔排序堆排序桶排序(基数排序) 稳定排序 前提:只有当在"二次"排序时不想破坏原先的次序,稳定性才有意义 概念:数据排序前后依然能保持相同数据的相对顺序 例子:对数组[3,3,1]进行选择排序算法进行排序,拿出最大的数3和最小的数1交换位置后变为[1,3,3],此时第一个3的下标本来是0,现在变成了2,排在了第二个3的后面.没有保持原先第一个3依旧保持在第二个3的前面的的相对顺序,这就是不稳定的排序 意义:如果我们只对一串数字排序,那么稳定与否确实不

sclieshare的博客 404

【计算机三级-数据库技术】操作题大题(第1套)

从触发器的语法中可知,【1】处应该填写的是执行触发器的表,【2】处应该填写指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。使用FOR或AFTER选顶定义的触发器为后触发器,即只有在引发触发器执行的语句中的操作都已成功执行,并且所有的约束检查也成功完成后,才执行触发器。转换成新的独立的模式,模式的属性由联系本身的属性及两个实体的键构成,主键由两端实体的键组合而成。实体的转换:在从ER图转换为关系模式时,一个实体转换成一个关系模式,实体的属性就是关系模式的属性,实体的键就是关系的主键。

放纵小开爱的博客 1101

7.1华为OD机试真题 新系统 - 奇偶三数之和 (Java/Py/C/C++/Js/Go)

7.1华为OD机试真题 新系统 - 奇偶三数之和 (Java/Py/C/C++/Js/Go)

算法大师! 445

编织时光:八大基础排序总结

通过选择一个基准元素,将数组分成两部分,一部分小于基准元素,一部分大于基准元素,然后递归地对子数组进行排序。冒泡排序是最简单的排序算法之一,它通过比较相邻的元素并交换位置,将最大(或最小)的元素逐步移动到最后(或最前)。选择排序也是一种简单直观的排序算法,它每次从未排序的部分中选择最小(或最大)的元素,并将其放到已排序部分的末尾。无论是舞动的冒泡排序,还是谐美的归并排序,每个排序算法都如诗如画,为我们的程序增添了魅力。将数组分成两部分,左边部分的元素都小于基准元素,右边部分的元素都大于基准元素。

good7ob的博客 85

javafx结合Scene Builder自定义fxml实现漂亮的登录界面、自定义最小化、关闭按钮

本节主要介绍了如何结合Scene Builder工具来制作一个好看又漂亮的登录界面,以及介绍了如何在程序中调用生成界面文件fxml文件,如何获取到fxml文件中的组件等,并演示登录、最小化和关闭等功能。

c1007857613的专栏 5221

算法基础之八大排序

通过学习和理解不同的排序算法,我们可以在实际开发中选择合适的算法来解决问题。本文将介绍八大常用排序算法,并分别用 Python、C++ 和 Java 三种语言实现

m0_49633491的博客 1021

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

八大基础排序

#include<stdio.h> #include<string.h> #include<stdlib.h> void InsertSort(int arr[],int len) { int i=1; int j=i-1; int tmp; for(i;i<len;i++) { tmp=arr[i]; for(j=i-1;j>=0...

weixin_45730574的博客 266

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

八大基础排序:冒泡排序,插入排序,选择排序,归并排序,快速排序,桶排序,计数排序,基数排序

八大基础排序算法分别是:冒泡排序,插入排序,选择排序;归并排序,快速排序;桶排序,计数排序,基数排序。我们根据其性质,将其分为三类:冒泡排序,插入排序,选择排序;归并排序,快速排序;桶排序,计数排序,基数排序。

somemoods的博客 564

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

八大基础排序 C/C++

八大基础排序 C/C++ 一、冒泡排序 时间复杂度: 空间复杂度: 二、选择排序 时间复杂度: 空间复杂度: 三、插入排序 时间复杂度: 空间复杂度: 四、快速排序 时间复杂度: 空间复杂度: 五、归并排序 时间复杂度: 空间复杂度: 六、希尔排序 时间复杂度: 空间复杂度: 七、堆排序 时间复杂度: 空间复杂度: 八、桶排序(基数排序) 时间复杂度: 空间复杂度: 总结 提示:这里对文章进行总结: 例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷

weixin_57722445的博客 154
上一篇: Druid数据库连接池就这么简单
下一篇: Java实现单向链表
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值