Java七大排序详解

news2024/10/2 6:26:00

排序

排序的概念

所谓排序 ,就是让一串记录,按照其中某些或者某个关键字的大小,递增或递减的排列起来的操作。
稳定性:就比如在待排序的序列中,存在多个具有相同关键字的记录 ,如果经过排序这些相同的关键字相对位置还是不变,则称这种排序是稳定的;否则就是不稳定的。下面用图例来解析一下:
在这里插入图片描述
排序还分为内部排序和外部排序:
内部排序: 数据元素全部在内存中排序。
外部排序: 数据元素大多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

插入排序

插入排序

直接插入排序就是一种简单的插入排序法:他就是把待排序的记录按照其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为一个新的有序序列。在实际生活中 我们玩扑克牌时,就应用了插入排序的思想。

步骤:
从第2个元素开始如果第一个元素比第二个元素大 那就得交换 一直往前遍历直到小于0下标 在待排序元素中,假设前n-个元素已经有序 如果第n个元素比第n-1个元素大 那说明前n个已经有序 ,如果比他小就按照遍历一直找到比前面的数字大为止 找到就插入进去就行。
因为我们不能够确定待排序中哪一部分是有序的 ,所以我们从第二个元素开始遍历 默认第一个元素是有序的 ,再依次遍历后面的元素 再慢慢插入进来 ,变成一个新的有序序列。
下面让我们用动图演示一遍:
在这里插入图片描述
代码实现如下:

 //插入排序
    public static void insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            //要定义一个变量存一下i下标的值
            int tmp = array[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                if (array[j] > tmp) {
                    array[j + 1] = array[j];
                } else {
                    break;
                }
            }
            array[j + 1] = tmp;
        }
    }

时间复杂度:最好情况下(待排序列是升序的)为O(N);最坏情况下(待排序列是逆序的)为O(N2),
空间复杂度:O(1);而且插入排序是稳定的

希尔排序

希尔排序

希尔排序又称为缩小增量法。希尔排序法的基本思想是:先给定一个整数gap,把待排序文件中所有的记录分为多个组,所有距离为gap的记录分为一组,并对每一组的记录进行排序 然后重复上诉操作直到gap= 1时 所有记录都排好序了
动图表示如下:
在这里插入图片描述
代码如下:

//希尔排序
    public static void shellSort(int[] array) {
        int gap = array.length;
        while (gap > 1) {
            gap = gap / 2; //或者可以写成 gap = gap / 3 + 1
            shell(array, gap);
        }
    }

    private static void shell(int[] array, int gap) {
        //每组的数据都在变化
        for (int i = gap; i < array.length; i++) {
            int tmp = array[i];
            int j = i - gap;
            for (; j >= 0; j -= gap) {
                if (array[j] > tmp) {
                    array[j + gap] = array[j];

                } else {
                    break;
                }
                array[j + gap] = tmp;
            }
        }
    }

时间复杂度:希尔排序的时间复杂度 是不好计算的 他会根据gap的取值的不同而不同。通过大量的实验,现在时间复杂度只能在O(n1.25) ~O(1.6*n1.25)来计算。
空间复杂度:O(1);
希尔排序是快速排序的优化 ,希尔排序是不稳定的。

选择排序

选择排序

选择排序的思想就是 每次遍历待待排序中的元素 选出最小值,排到序列的起始位置 ,一直排 直到全部排完 比如说现在第一个元素是4 后面找完待排序如果有比4小的就换 没有就不换。
动图演示:
在这里插入图片描述
代码表示如下:

 //选择排序
    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            //定义一个临时变量把i下标存下来
            int minIndex = i;
            int j = i + 1;
            for (; j < array.length; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            swap(array, minIndex, i);
        }
    }

时间复杂度:最坏情况:O(N2),最好情况:O(N2);
空间复杂度:O(1)
选择排序不稳定

冒泡排序

冒泡排序
冒泡排序的思想 :就是遍历和交换 如果左边的大于右边就交换 排下来 最大的就在右边了 。
具体情况看动图演示:
在这里插入图片描述
代码实现如下:


    // 冒泡排序
    public static void bubbleSort(int[] array) {
        // write code  here
        for (int i = 0;i<array.length;i++){
            for (int j =0;j < array.length-1-i;j++){
                if (array[j]<array[j+1]){
                    swap(array,j,j+1);
                }
            }
        }
    }

时间复杂度:最坏情况下:O(N2),最好情况下:O(N)
空间复杂度:O(1)

快速排序法

快速排序算法

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任意取待排序元素序列中的某元素作为基准值,按照该排序码将排序集合分割为两个子序列,让左子序列中所有元素均小于基准值,右子序列均大于基准值,然后递归左和右 直到所有元素有序。

快排右可以分为两种方法去实现 Hoare法 和 挖坑法。

Hoare法

用最左边的值作为一个tmp,定义一个left和right,left从左往右走 ,right从右往左走 ,一定要right先走,这样才能保证相遇时候的值是小于tmp的值。 在走的过程中,如果right遇到比tmp小的值,就停下来等left走直到left遇到一个比tmp大的数 left和right的值交换 right继续走 直到他们相遇,将相遇的值和tmp交换。此时tmp的左边都是小于tmp的数 ,右边都是大于tmp的数。
动图演示:
在这里插入图片描述
代码表示如下:

 //快速排序
    public static void quickSort(int[] array) {
        quick(array,0,array.length-1);//取闭区间
    }

    private static void quick(int[] array,int start,int end) {
        if (start >= end){
            return;
        }
        int pivot = partitionHoare(array,start,end);
        quick(array,start,pivot-1);
        quick(array,pivot+1,end);
    }
     //Hoare法
    private static int partitionHoare(int[] array,int left,int right) {
        int tmp = array[left];//基准
        int i =left;
        while (left < right) {
            while (left < right && array[right] >= tmp) {
                right--;
            }
            while (left < right && array[left] <= tmp) {
                left++;
            }
            swap(array,left,right);
        }
        //相遇了  换
        swap(array,i,left);
        return left;
    }
挖坑法

挖坑法的思路和Hoare法差不多
就是选最左边或者最右边的数据作为一个坑,也是定义两个指针在两边走
我们直接看动图演示:
在这里插入图片描述
代码实现如下:

 //快速排序
    public static void quickSort(int[] array) {
        quick(array,0,array.length-1);//取闭区间
    }

    private static void quick(int[] array,int start,int end) {
        if (start >= end){
            return;
        }
        int pivot = partition(array,start,end);
        quick(array,start,pivot-1);
        quick(array,pivot+1,end);
    }
//挖坑法
    private static int partition(int[] array,int left,int right) {
        int tmp = array[left];
        while (left < right){
            while (left < right && array[right] >= tmp) {
                right--;
            }
            if (left >= right){
                break;
            }
            array[left] = array[right];
            while (left < right && array[left] <= tmp) {
                left++;
            }
            if (left >= right){
                break;
            }
            array[right] = array[left];
        }
        array[left] = tmp;
        return left;
    }

还有非递归写法:

//快速排序非递归实现
    public static void quickSortNor(int[] array) {

        Stack<Integer> stack = new Stack<>();
        int left = 0;
        int right = array.length-1;
        int pivot = partition(array,left,right);

        if(pivot-1 > left) {
            stack.push(left);
            stack.push(pivot-1);
        }
        if(pivot + 1 < right) {
            stack.push(pivot+1);
            stack.push(right);
        }
        while (!stack.isEmpty()) {
            right = stack.pop();
            left = stack.pop();
            pivot = partition(array,left,right);

            if(pivot-1 > left) {
                stack.push(left);
                stack.push(pivot-1);
            }
            if(pivot + 1 < right) {
                stack.push(pivot+1);
                stack.push(right);
            }
        }

    }

归并排序

归并排序
归并排序和快速排序一样采用了分治的思想,他就是将待排序的数组不断拆分,直到拆到区间里只有一个元素为止,然后开始合并 一层一层地合并 直到整个数组有序。这里很显然要用递归的方式去实现归并排序。 归并排序就是典型用空间换时间的一种排序。
动图演示
在这里插入图片描述
代码实现:


    //归并排序
    public static void mergeSort(int[] array) {
        mergeFunc(array,0,array.length-1);
    }

    private static void mergeFunc(int[] array,int left,int right) {
        if (left >= right) {
            return;
        }
        int mid = left +((right - left) >> 1);
        mergeFunc(array,left,mid);
        mergeFunc(array,mid+1,right);
        //左边分解完 ,右边分解完  开始合并
        merge(array,left,mid,right);

    }
    private static void merge(int[] array,int left,int mid,int right) {
        int s1 = left;
        int e1 = mid;
        int s2 = mid+1;
        int e2 = right;

        int[] tmpArray = new int[right-left+1];
        int k = 0;
        //得保证两个表都有数据
        while (s1 <= e1 && s2 <= e2) {
            if (array[s1] <= array[s2]) {
                tmpArray[k++] = array[s1++];
            }else {
                tmpArray[k++] = array[s2++];
            }
        }
        //2.看还有哪个数组还有数据  直接加在数组后面
        while (s1 <= e1) {
            tmpArray[k++] = array[s1++];
        }
        while (s2 <= e2) {
            tmpArray[k++] = array[s2++];
        }
        //拷贝到原来的数组
        for (int i = 0;i < k;i++) {
            array[i+left] = tmpArray[i];
        }
    }

时间复杂度:O(Nlog2N)
空间复杂度:O(N)
归并排序稳定

堆排序

排序的思想:首先得将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是**堆结构的顶端。**然后将顶端的数将最后一个元素交换,此时末尾为最大值,待排序元素就剩n-1个了。然后再将剩下的n-1个元素调整为大根堆,循环去执行此操作最后便可以得到有序的数组。
升序用大根堆 ,降序用小根堆。
图解:
在这里插入图片描述
时间复杂度:O(N*logN);
空间复杂度:O(1);
堆排序不稳定
代码实现如下:

  //堆排序
    public static void heapSort(int[] array) {
        //创建大根堆
        createHeap(array);
        int end = array.length - 1;
        while (end > 0) {
            swap(array, 0, end);
            siftDown(array, 0, end);
            end--;
        }
    }

    private static void createHeap(int[] array) {
        for (int parent = (array.length - 1 - 1) / 2; parent >= 0; parent--) {
            siftDown(array, parent, array.length);
        }
    }

    private static void siftDown(int[] array, int parent, int len) {
        int child = (2 * parent) + 1;
        while (child < len) {
            if (child + 1 < len && array[child] < array[child + 1]) {
                child = child + 1;
            }
            if (array[child] > array[parent]) {
                swap(array, child, parent);
                parent = child;
                child = 2 * parent + 1;

            } else {
                break;
            }
        }
    }

    private static void swap(int[] array, int i, int j) {
        int tmp = array[j];
        array[j] = array[i];
        array[i] = tmp;
    }

到这里就讲完了 数据结构7大排序 当然还有很多排序 如果有兴趣可以去查找一下资料 比如说:
基数排序

计数排序

桶排序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1412989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过FileZilla配置FTP

FileZilla服务端的安装 在虚拟机里安装FileZilla服务器 FileZilla的官网 下载一个客户端和一个服务端的FileZilla 如果已经有了一个客户端&#xff0c;可以不下用载。 FileZilla的配置 说明一下&#xff1a;通过FileZilla配置FTP有两种模式&#xff0c;我们先用被动模式 下载…

Javaweb之SpringBootWeb案例之阿里云OSS服务集成的详细解析

2.3.3 集成 阿里云oss对象存储服务的准备工作以及入门程序我们都已经完成了&#xff0c;接下来我们就需要在案例当中集成oss对象存储服务&#xff0c;来存储和管理案例中上传的图片。 在新增员工的时候&#xff0c;上传员工的图像&#xff0c;而之所以需要上传员工的图像&…

CDR绘图软件|安装教程来了(小白福利:有红包封面领取哦!)

前言 今天给小伙伴们讲讲&#xff1a;如何安装CDR软件。 如果未来的你想从事平面设计/广告行业&#xff0c;那应该就会接触到CDR这款软件。 CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件&#xff1b;该软件是Corel公司出品的矢量图形制作工具软件&#xff0c;这…

GPT应用程序的限制

尽管GPT&#xff08;Generative Pre-trained Transformer&#xff09;应用程序具有强大的自然语言生成能力&#xff0c;但也存在一些限制和挑战。以下是一些常见的GPT应用程序的限制&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公…

HCIA-HarmonyOS设备开发认证-2.设备开发入门

目录 HarmonyOS设备开发学习路径一、开发项目与工具介绍1.1、设备开发环境准备1.2、设备开发流程1.3、Huawei DevEco Device Tool 二、OpenHarmony介绍OpenHarmony目录结构详细介绍 待续... HarmonyOS设备开发学习路径 一、开发项目与工具介绍 1.1、设备开发环境准备 Window、…

Leetcode刷题笔记题解(C++):1971. 寻找图中是否存在路径

思路&#xff1a; 1.建立图集&#xff0c;二维数组&#xff0c;path[0]里面存放的就是与0相连的节点集合 2.用布尔数组来记录当前节点是否被访问过&#xff0c;深度优先会使用到 3.遍历从起点开始能直接到达的点&#xff08;即与起点相邻的点&#xff09;&#xff0c;判断那…

【Image captioning】论文阅读七—Efficient Image Captioning for Edge Devices_AAAI2023

中文标题:面向边缘设备的高效图像描述(Efficient Image Captioning for Edge Devices) 文章目录 1. 引言2. 相关工作3. 方法3.1 Model Architecture(模型结构)3.2 Model Training (模型训练)3.3 Knowledge Distillation (知识蒸馏)4. 实验4.1 数据集和评价指标4.2 实施细…

Element UI样式修改之NavMenu导航菜单箭头样式修改

UI设计稿给的菜单箭头样式可能与我们饿了么组件NavMenu的菜单箭头样式不一致,目前我们侧边导航菜单的上下翻转箭头如下所示: 希望得到如下的结果: 找到饿了么Icon里我们想要向下箭头,F12后复制content内容content: “\e790”; content: "\e790";然后将默认的c…

计算机网络-PPP与PPPoE协议

我们之前学习的大多是局域网LAN内常用的技术&#xff0c;但是我们总是需要访问Internet&#xff0c;需要访问百度、B站等等&#xff0c;那怎样让局域网访问外面的资源呢&#xff0c;其实我们已经学习过了NAT转换&#xff0c;但是那对于广域网的架构我们还是需要学习下的。 一、…

算法训练营Day60(单调栈)

84.柱状图的最大矩形 84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 注意首尾加0的细节就可 class Solution {public int largestRectangleArea(int[] heights) {Deque<Integer> stack new LinkedList<>();int[] newHeight new int[heights.…

Pandas应用-股票分析实战

股票时间序列 时间序列&#xff1a; 金融领域最重要的数据类型之一 股价、汇率为常见的时间序列数据 趋势分析&#xff1a; 主要分析时间序列在某一方向上持续运动 在量化交易领域&#xff0c;我们通过统计手段对投资品的收益率进行时间序列建模&#xff0c;以此来预测未来的收…

【大根堆】【C++算法】871 最低加油次数

作者推荐 【动态规划】【map】【C算法】1289. 下降路径最小和 II 本文涉及知识点 大根堆 优先队列 LeetCode:871最低加油次数 汽车从起点出发驶向目的地&#xff0c;该目的地位于出发位置东面 target 英里处。 沿途有加油站&#xff0c;用数组 stations 表示。其中 statio…

Python教程48:海龟画图turtle画太极八卦阵

---------------turtle源码集合--------------- Python教程91&#xff1a;关于海龟画图&#xff0c;Turtle模块需要学习的知识点 Python源码45&#xff1a;海龟画图turtle画雪容融 Python源码44&#xff1a;海龟画图turtle&#xff0c;画2022卡塔尔世界杯吉祥物 Python教程…

【c++】什么是面向对象

面向过程和面向对象初步认识 面向过程&#xff08;C语言&#xff09; C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题 面向对象&#xff08;C&#xff09; C是基于面向对象的&#xff0c;关注的是对象&am…

短视频账号矩阵系统+无人直播系统源码技术开发

短视频账号矩阵系统无人直播系统源码技术开发涉及到多个领域&#xff0c;包括但不限于前端开发、后端开发、数据库设计、网络通信等。 以下是一些基本技术的步骤和注意事项&#xff1a; 1.技术需求分析设计&#xff1a;首先&#xff0c;需要明确开发短视频账号矩阵系统和无人直…

《ORANGE’S:一个操作系统的实现》读书笔记(三十八)尾声(三)

这篇文章是尾声的第三部分&#xff0c;也是《ORANGE’S&#xff1a;一个操作系统的实现》读书笔记的最后一篇文章&#xff0c;本篇文章记录如何将我们开发的OS安装到真实的计算机&#xff08;建议在虚拟机中进行&#xff09;。 将OS安装到真实的计算机 其实安装到真实的硬盘和…

Linux--文件链接

目录 1.建立软连接 2.建立硬链接 3.什么是软链接 Linux中软链接的应用场景 4.什么是硬链接 5.文件与目录的硬链接数 6.软链接与硬链接的区别 用户无法对目录建立硬链接&#xff0c;可以建立软连接。 在Linux中文件的链接有两种&#xff1a;1.软连接 2.硬链接 1.建立软…

3656A/B/D矢量网络分析仪

3656A/B/D矢量网络分析仪 3656A/B/D矢量网络分析仪适用于无线通信、有线电视、教育及汽车电子等领域&#xff0c;可用于对滤波器、放大器、天线、电缆、有线电视分接头等射频元件的性能测量。该产品采用WINDOWS操作系统;具有误差校准功能、时域功能、夹具仿真器功能;具有对数幅…

【Linux】Linux进度条小程序(包含色块实现)

我们再将Linux常用工具与命令都学会了之后&#xff0c; 设计进度条这个小程序可以比较好的帮助我们进行一定程度练习与巩固 目录 预备知识&#xff1a;回车换行&#xff1a;缓冲区&#xff1a; 进度条&#xff1a;准备工作&#xff1a;主题思路&#xff1a;代码实现&#xff1a…

理想架构的Doherty功率放大器理论与仿真

Doherty理论—理想架构的Doherty功率放大器理论与仿真 参考&#xff1a; 三路Doherty设计 01 射频基础知识–基础概念 ADS仿真工程文件链接&#xff1a;理想架构的Doherty功率放大器理论与仿真 目录 Doherty理论---理想架构的Doherty功率放大器理论与仿真0、Doherty架构的作用…