Java中常见的几种排序算法

Halcon深度图转伪彩图 阅读详情

本文主要记录了几种常见的排序算法的Java实现,如冒泡排序、快速排序、直接插入排序、希尔排序、选择排序等等。
在学数据结构与算法时的部分记录,感觉好难╮(╯▽╰)╭,还需继续努力。

更多文章欢迎访问我的个人博客–>幻境云图

1. 冒泡排序

将序列中所有元素两两比较,将最大的放在最后面。

将剩余序列中所有元素两两比较,将最大的放在最后面。

重复第二步,直到只剩下一个数。

    /**
     * 冒泡排序:两两比较,大者交换位置,则每一轮循环结束后最大的数就会移动到最后.
     * 时间复杂度为O(n²) 空间复杂度为O(1)
     */
    private static void bubbleSort(int[] arr) {
        //外层循环length-1次
        for (int i = 0; i < arr.length-1; i++) { 
            //外层每循环一次最后都会排好一个数
            //所以内层循环length-1-i次
            for (int j = 0; j < arr.length - 1 - i; j++) {  
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

2. 快速排序

快速排序(Quicksort)是对冒泡排序的一种改进,借用了分治的思想,由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列.

具体步骤

快速排序使用分治策略来把一个序列(list)分为两个子序列(sub-lists)。

  • ①. 从数列中挑出一个元素,称为”基准”(pivot)。
  • ②. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  • ③. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

  /**
     * 快速排序
     * 时间复杂度为O(nlogn) 空间复杂度为O(1)
     */
    public static void quickSort(int[] arr, int start, int end) {
        if (start < end) {
            int baseNum = arr[start];//选基准值
            int midNum;//记录中间值
            int left = start;//左指针
            int right = end;//右指针
            while(left<right){
                while ((arr[left] < baseNum) && left < end) {
                    left++;
                }
                while ((arr[right] > baseNum) && right > start) {
                    right--;
                }
                if (left <= right) {
                    midNum = arr[left];
                    arr[left] = arr[right];
                    arr[right] = midNum;
                    left++;
                    right--;
                }
            }
            if (start < right) {
                quickSort(arr, start, right);
            }
            if (end > left) {
                quickSort(arr, left, end);
            }
        }
    }

3. 直接插入排序

直接插入排序(Straight Insertion Sorting)的基本思想:将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过为止。

首先设定插入次数,即循环次数,for(int i=1;i<length;i++),1个数的那次不用插入。

设定插入数和得到已经排好序列的最后一个数的位数。insertNum和j=i-1。

从最后一个数开始向前循环,如果插入数小于当前数,就将当前数向后移动一位。

将当前数放置到空着的位置,即j+1。

    /**
     * 直接插入排序
     * 时间复杂度O(n²) 空间复杂度O(1)
     */
    public static void straightInsertion(int[] arr) {
        int current;//要插入的数
        for (int i = 1; i < arr.length; i++) {  //从1开始 第一次一个数不需要排序
            current = arr[i];
            int j = i - 1;//序列元素个数
            while (j >= 0 && arr[j] > current) {//从后往前循环,将大于当前插入数的向后移动
                arr[j + 1] = arr[j];//元素向后移动
                j--;
            }
            arr[j + 1] = current;//找到位置,插入当前元素
        }
    }

4. 希尔排序

是插入排序的一种高速而稳定的改进版本。

希尔排序是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

    /**
     * 希尔排序
     * 时间复杂度O(n²) 空间复杂度O(1)
     */
    public static void shellSort(int[] arr) {
        int gap = arr.length / 2;
        for (; gap > 0; gap = gap / 2) {
            //不断缩小gap,直到1为止
            for (int j = 0; (j + gap) < arr.length; j++) { 
                //使用当前gap进行组内插入排序
                for (int k = 0; (k + gap) < arr.length; k += gap) { 
                    if (arr[k] > arr[k + gap]) { 
                        //交换操作
                        int temp = arr[k];
                        arr[k] = arr[k + gap];
                        arr[k + gap] = temp;
                    }
                }
            }
        }
    }

5. 选择排序

遍历整个序列,将最小的数放在最前面。

遍历剩下的序列,将最小的数放在最前面。

重复第二步,直到只剩下一个数。

    /**
     * 选择排序
     * 时间复杂度O(n²) 空间复杂度O(1)
     */
    public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) { //循环次数
            int min = arr[i];//等会用来放最小值
            int index = i;//用来放最小值的索引
            for (int j = i + 1; j < arr.length; j++) { //找到最小值
                if (arr[j] < min) {
                    min = arr[j];
                    index = j;
                }
            }
            //内层循环结束后进行交换
            arr[index] = arr[i];//当前值放到最小值所在位置
            arr[i] = min;//当前位置放最小值
        }
    }

6. 堆排序

对简单选择排序的优化。

将序列构建成大顶堆。

将根节点与最后一个节点交换,然后断开最后一个节点。

重复第一、二步,直到所有节点断开。

public  void heapSort(int[] a){
           int len=a.length;
           //循环建堆  
           for(int i=0;i<len-1;i++){
               //建堆  
               buildMaxHeap(a,len-1-i);
               //交换堆顶和最后一个元素  
               swap(a,0,len-1-i);
           }
       }
        //交换方法
       private  void swap(int[] data, int i, int j) {
           int tmp=data[i];
           data[i]=data[j];
           data[j]=tmp;
       }
       //对data数组从0到lastIndex建大顶堆  
       private void buildMaxHeap(int[] data, int lastIndex) {
           //从lastIndex处节点(最后一个节点)的父节点开始  
           for(int i=(lastIndex-1)/2;i>=0;i--){
               //k保存正在判断的节点  
               int k=i;
               //如果当前k节点的子节点存在  
               while(k*2+1<=lastIndex){
                   //k节点的左子节点的索引  
                   int biggerIndex=2*k+1;
                   //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在  
                   if(biggerIndex<lastIndex){
                       //若果右子节点的值较大  
                       if(data[biggerIndex]<data[biggerIndex+1]){
                           //biggerIndex总是记录较大子节点的索引  
                           biggerIndex++;
                       }
                   }
                   //如果k节点的值小于其较大的子节点的值  
                   if(data[k]<data[biggerIndex]){
                       //交换他们  
                       swap(data,k,biggerIndex);
                       //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值  
                       k=biggerIndex;
                   }else{
                       break;
                   }
               }
           }
       }

7. 归并排序

速度仅次于快速排序,内存少的时候使用,可以进行并行计算的时候使用。

选择相邻两个数组成一个有序序列。

选择相邻的两个有序序列组成一个有序序列。

重复第二步,直到全部组成一个有序序列。

public  void mergeSort(int[] a, int left, int right) {  
           int t = 1;// 每组元素个数  
           int size = right - left + 1;  
           while (t < size) {  
               int s = t;// 本次循环每组元素个数  
               t = 2 * s;  
               int i = left;  
               while (i + (t - 1) < size) {  
                   merge(a, i, i + (s - 1), i + (t - 1));  
                   i += t;  
               }  
               if (i + (s - 1) < right)  
                   merge(a, i, i + (s - 1), right);  
           }  
        }  
       
        private static void merge(int[] data, int p, int q, int r) {  
           int[] B = new int[data.length];  
           int s = p;  
           int t = q + 1;  
           int k = p;  
           while (s <= q && t <= r) {  
               if (data[s] <= data[t]) {  
                   B[k] = data[s];  
                   s++;  
               } else {  
                   B[k] = data[t];  
                   t++;  
               }  
               k++;  
           }  
           if (s == q + 1)  
               B[k++] = data[t++];  
           else  
               B[k++] = data[s++];  
           for (int i = p; i <= r; i++)  
               data[i] = B[i];  
        }

8. 基数排序

用于大量数,很长的数进行排序时。

将所有的数的个位数取出,按照个位数进行排序,构成一个序列。

将新构成的所有的数的十位数取出,按照十位数进行排序,构成一个序列。

public void baseSort(int[] a) {
               //首先确定排序的趟数;    
               int max = a[0];
               for (int i = 1; i < a.length; i++) {
                   if (a[i] > max) {
                       max = a[i];
                   }
               }
               int time = 0;
               //判断位数;    
               while (max > 0) {
                   max /= 10;
                   time++;
               }
               //建立10个队列;    
               List<ArrayList<Integer>> queue = new ArrayList<ArrayList<Integer>>();
               for (int i = 0; i < 10; i++) {
                   ArrayList<Integer> queue1 = new ArrayList<Integer>();
                   queue.add(queue1);
               }
               //进行time次分配和收集;    
               for (int i = 0; i < time; i++) {
                   //分配数组元素;    
                   for (int j = 0; j < a.length; j++) {
                       //得到数字的第time+1位数;  
                       int x = a[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                       ArrayList<Integer> queue2 = queue.get(x);
                       queue2.add(a[j]);
                       queue.set(x, queue2);
                   }
                   int count = 0;//元素计数器;    
                   //收集队列元素;    
                   for (int k = 0; k < 10; k++) {
                       while (queue.get(k).size() > 0) {
                           ArrayList<Integer> queue3 = queue.get(k);
                           a[count] = queue3.get(0);
                           queue3.remove(0);
                           count++;
                       }
                   }
               }
        }

9. 总结

排序法平均时间最小时间最大时间稳定度额外空间备注
冒泡排序O(n2)O(n)O(n2)稳定O(1)n小时较好
选择排序O(n2)O(n2)O(n2)不稳定O(1)n小时较好
插入排序O(n2)O(n)O(n2)稳定O(1)大部分已排序时较好
基数排序O(logRB)O(n)O(logRB)稳定O(n)B是真数(0-9),R是基数(个十百)
Shell排序O(nlogn)-O(ns) 1<s<2不稳定O(1)s是所选分组
快速排序O(nlogn)O(n2)O(n2)不稳定O(logn)n大时较好
归并排序O(nlogn)O(nlogn)O(nlogn)稳定O(n)要求稳定性时较好
堆排序O(nlogn)O(nlogn)O(nlogn)不稳定O(1)n大时较好

参考

https://www.cnblogs.com/shixiangwan/p/6724292.html

SAP Event Mesh 简介 Get Started with Messaging for Decoupled Communication Step 1: What is the SAP Event Mesh service? SAP Event Mesh 是一种完全托管的服务,用于连接应用程序、服务和系统,以便它们可以通过消息和事件相互交互。 它通过引入中央消息代理取代了传统的点对点通信。 虽然点对点通信适用于在有限数量的发送方和接收方之间共享数据,但可扩展性很快就会成为一个问题。 SAP Event Mesh 解决了这个问题,并确保 阅读详情

相关推荐

银河麒麟V10离线安装VLC播放器:依赖处理与3.0.9.2版本实操指南

在国产化操作系统日益普及的背景下,软件安装方式成为政企内网用户关注的重点。离线安装作为一种不依赖公网源的部署手段,常用于解决内网环境下的软件获取问题。其核心在于理解Linux包管理机制,如dpkg与apt对依赖关系的处理逻辑。掌握这一原理,不仅能应对多媒体软件的部署,也能提升系统维护效率。VLC作为跨平台多媒体播放器,凭借强大的解码能力与协议支持,广泛应用于本地视频播放、RTSP拉流及监控大屏等场景。本文从离线安装的通用概念出发,结合银河麒麟V10桌面版的实际环境,详细梳理了VLC 3.0.9.2离线包的获

weixin_32247165的博客 367

详解Java常用排序算法(10种,含演示动画)

Java常用的排序算法有以下几种: 1. 冒泡排序;2. 选择排序;3. 插入排序;4. 希尔排序;5. 归并排序;6. 快速排序;7. 堆排序;8. 计数排序;9. 桶排序;10. 基数排序。 这些排序算法都有各自的优缺点,应根据具体情况选择适合的算法。

不积跬步无以至千里,不积小流无以成江海。一个喜欢学习分享的程序员 3万+

关于使用CMT2300A FIFO缓存区间设置为64Byte的问题

帮助你解决在使用CMT2300A 时遇到的各种问题,若有需要,请及时与我交流

teleger的博客 1428

java实现七种经典排序算法

七种常见排序算法java代码及图示,所有代码均可单独独立运行

诸葛浪 4277

想学嵌入式但没开发板?试试这个免费的STM32虚拟仿真平台(含LVGL界面教程)

本文介绍如何利用免费的STM32虚拟仿真平台学习嵌入式开发,特别适合预算有限或零硬件基础的学习者。通过详细的LVGL界面开发教程,展示虚拟仿真在嵌入式学习中的高效性和实用性,涵盖环境搭建、代码实现到实机迁移的全流程,助力快速掌握嵌入式开发核心技能。

weixin_29266647的博客 306

【异常】OpenClaw 飞书端 OpenClaw: access not configured. Pairing code: [] Ask the bot owner to approve with

摘要: OpenClaw飞书机器人交互中出现的access not configured报错,是因用户或组织未配置访问权限触发的拦截提示。报错包含组织单元ID和配对校验码,需管理员审批开通权限。普通用户需提交完整报错信息给管理员处理;管理员可通过执行标准化命令单次审批,或批量配置组织白名单优化权限管理。建议提前梳理权限范围、及时同步组织架构变更,并定期审计权限列表以确保安全合规。

奶爸的编程之路,也就一周冷个三天 370

Java实现十大经典排序算法详解

排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性冒泡排序O(n²)O(n)O(n²)O(1)稳定选择排序O(n²)O(n²)O(n²)O(1)不稳定插入排序O(n²)O(n)O(n²)O(1)稳定希尔排序O(n log n)O(n log²n)O(n²)O(1)不稳定归并排序O(n log n)O(n log n)O(n log n)O(n)稳定快速排序O(n log n)O(n log n)O(n²)O(log n)

weixin_43063624的博客 2785

基于YOLOv26的道路抛洒物检测系统原理实现

本文提出了一种基于YOLOv26的道路抛洒物智能检测系统,通过深度学习技术实现道路抛洒物的实时检测与分类。系统采用分层架构设计,包含视频采集、目标检测、分类评估和预警处理等模块,能够自动识别轮胎碎片、货物包装、金属零件等多种抛洒物,并根据危险程度分级预警。YOLOv26算法在检测精度和速度上的优势使其特别适合道路监控场景,结合背景建模和运动目标提取技术,有效提高了复杂道路环境下抛洒物的识别率。该系统可集成到现有智能交通监控平台,为道路安全管理提供实时决策支持。

一键难忘的博客 1253

十大经典排序算法——java语言

一、冒泡排序 二、选择排序 三、插入排序 四、希尔排序 五、归并排序 六、快速排序 七、堆排序 八、计数排序 九、桶排序 十、基数排序

weixin_56781779的博客 7037

英飞凌TC3xx之一起认识GTM系列(六)如何实现GTM与VADC关联的配置

本文给出了GTM与EVADC之间关联的细节,并通过两个实例分别说明了如何对寄存器进行配置。

无所适从的我的博客 2932

ShardingSphere 分库分表避坑:扩容数据迁移时,如何做到“不停机、不丢数据”?

停机:发布公告,凌晨 0 点停止对外服务。洗数据:跑一个巨大的脚本,把旧库数据 Hash 算出新路由,写入新库。改配置:修改代码里的分片规则。重启:祈祷数据没丢,服务正常。这种“刀耕火种”的方式,风险极高,且随着数据量增大,停机时间会变得不可接受。我们需要的是Online Migration (在线迁移)。分库分表扩容不再是“听天由命”的赌博。通过,我们将一次高风险的“运维操作”变成了一个可控的、可视化的“数据流转过程”。方案停机时间复杂度回滚难度传统停机清洗。

BUG猿的博客 882

Java常用实现八种排序算法与代码实现

一、交换排序 所谓交换,就是序列中任意两个元素进行比较,根据比较结果来交换各自在序列中的位置,以此达到排序的目的。 1. 冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排序为例,其核心思想是: 从第一个元素开始,比较相邻的两个元素。如果第一个比第二个大,则进行交换。 轮到下一组相邻元素,执行同样的比较操作,再找下一组,直到没有相邻元素可比较为止,此时最后的元素应是最大的数。 除了每次排序得到的最后一个元素,对剩余元素重复以上步骤,直到没有任何一对元素需要比较为止。

java_atguigu的博客 2万+

实战!C#整合YOLO+Halcon做玻璃瓶口缺陷检测:裂纹识别+尺寸测量一步到位(附DLL交互代码)

AI擅长语义识别(裂纹、缺陷),传统机器视觉擅长精密测量(尺寸、位置),C#做整合层,才能满足工业生产的“精度+效率+稳定性”要求。这套方案不只是玻璃瓶检测能用,改改模型和测量逻辑,还能用到瓶盖缺陷检测、饮料瓶液位检测等场景。如果你们厂也有类似的质检痛点,评论区留个言,我帮你看看怎么调整算法参数。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 868

常见几种java排序算法

1.插入排序 public class InsertSort { public static void sort(int[] arr) { if (arr.length &amp;amp;amp;gt;= 2) { for (int i = 1; i &amp;amp;amp;lt; arr.length; i++) { //挖出一个要用来插入的值,同时位置上留下...

zzzgd_666的博客 10万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java的几种常见排序算法

Java的几种常见排序算法 一、所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。 二、排序算法可以分为内部排序和外部排序。 内部排序是数据记录在内存中进行排序。 外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访

余生不过半载 151

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

几种常见的Java排序算法

几种常见的Java排序算法前言一、插入排序二、希尔排序三、冒泡排序四、选择排序五、堆排序六、快速排序七、归并排序 前言 本文介绍了Java中几种常见的排序算法 1.插入排序(插入排序,希尔排序) 2.交换排序(冒泡排序,快速排序(递归非递归)) 3.选择排序(选择排序,堆排序) 4.归并排序 一、插入排序 插入排序属于内部排序法,是对内部欲排序的元素以插入的方式移动到合适的位置 即把所有的元素看成两部分,一部分是有序的,另外一部分是无序的,刚开始有序的部分为一个元素,而无序的部分则为n-1个元素,排序的时

weixin_51601437的博客 6203

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java几种常见的排序算法

 一、所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。   二、排序算法可以分为内部排序和外部排序。     内部...

qq_42221826的博客 214

几种常见排序算法的java实现

一、几种常见的排序算法性能比较 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O(n) O(n^2) O(n^2) O(1) 稳定 大部分已有序的较好 冒泡排序 O(n) O(n^2)

晚秋星辰 936

java中常见的几种排序算法

本文总结了10种经典排序算法,包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,并提供了Java实现代码。这些算法虽然不推荐用于生产环境,但作为数据结构与算法学习的重点内容,是面试常考点。文章对比了各算法的时间复杂度、空间复杂度和稳定性,指出Java内置4种排序方法加上手动实现的10种算法,共14种以上排序方式。建议生产环境使用Arrays.sort()或List.sort(),面试则需要掌握快排、归并等至少3种算法实现,小数组优化可考虑插入排序。

BUG糕手的博客 1249

Java——常见的几种排序算法

一、冒泡排序 每次冒泡过程都是从数列的第一个元素开始,然后依次和剩余的元素进行比较, 跟列队一样, 从左到右两两相邻的元素比大小, 高的就和低的换一下位置. 最后最高(值最大)的肯定就排到后面了. 但是这只是把最高的排到后面了, 还得找出第二高的, 于是又从第一个开始两两比较, 高的往后站, 然后第二高的也到后面了. 然后是第三高的再往后排… public class JavaSort { public static void main(String[] args) { .

Vicky_Tang 1万+
上一篇: 基于docker-compose搭建Elasticsearch集群
下一篇: Docker入门教程(二)---docker和docker-compose 快速安装
探索云原生
博客等级 码龄9年 730粉丝 131原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值