基础排序算法 java 实现(冒泡、选择、插入、快排、归并、堆排)

Java十大排序算法详解:原理、复杂度对照与手写实现指南 排序算法是计算机程序设计的基石之一,无论是数据检索、统计分析还是业务处理,几乎处处离不开有序数据。从最基础的冒泡排序到工程中广泛使用的快速排序与归并排序,每种算法都体现了时间与空间复杂度的精妙权衡。理解这些原理不仅能提升代码性能直觉,更是攻克Java面试、应对手写代码环节的核心能力。实际开发中,JDK的Arrays.sort内置双轴快排与TimSort,但若不理解其背后的数据结构与算法思想,很难应对真实场景中的定制化排序需求。本文系统梳理十大排序算法的原理、Java实现与复杂度对照,并结合面试高频考点与工程 阅读详情
package demo;

import java.util.Arrays;

public class SortUtil {
    private static void printArr(int[] arr) {
        System.out.println(Arrays.toString(arr));
    }

    private static void checkSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                throw new RuntimeException("Sort Error!");
            }
        }
    }

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

    // 本机测试
    public static void main(String[] args) {
//        int[] arr = {4, 3, 5};

        int[] arr = new int[50000 * 100];
        java.util.Random random = new java.util.Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(arr.length);
        }

//        System.out.println("排序前:");
//        printArr(arr);

        long s = System.currentTimeMillis();

//        bubbleSort(arr);// 50000 数据 5000+ ms
//        selectSort(arr);// 50000 数据 1700+ ms
//        insertSort(arr);// 50000 数据 360+ ms

        quickSort(arr, 0, arr.length - 1);// 50000 * 100 数据 770 ms

//        mergeSort(arr);// 50000 * 100 数据 1300 ms
//        mergeSort(arr, 0, arr.length - 1);// 50000 * 100 数据 1300 ms

//        heapSort(arr);// 50000 * 100 数据 1650 ms

        long e = System.currentTimeMillis();
        System.out.println("耗时:" + (e - s));

        checkSort(arr);
        System.out.println("排序正确!");

//        System.out.println("排序后:");
//        printArr(arr);
    }

    private static void bubbleSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放
            for (int j = len - 1; j > i; j--) { // 从后往前,把最小(大)的挪动到目标位置
                if (arr[j] < arr[j - 1]) { // 后面的大于前面
                    swap(arr, j, j - 1);//如果没有发送交互则表示排序已经完成,但会多n次判断
                }
            }
        }
    }

    private static void selectSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放
            int min = i;

            for (int j = i + 1; j < len; j++) {
                if (arr[j] < arr[min]) { // 后面的大于前面
                    min = j;
                }
            }

            swap(arr, i, min);
        }
    }

    private static void insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {// 第一个不需要插入排序
            int temp = arr[i];
            int j = i - 1;
            while (j >= 0 && temp < arr[j]) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = temp;
        }
    }

    /*** quick ***/
    private static void quickSort(int[] arr, int left, int right) {
        if (left >= right) return;
        int pivotIndex = partition(arr, left, right);
        quickSort(arr, left, pivotIndex - 1);//排序 target 前面的
        quickSort(arr, pivotIndex + 1, right);//排序 target 后面的
    }

    private static int partition(int[] arr, int left, int right) {
        int pivot = arr[right];//堆排序是原地排序,这个额外空间可以省去的,这里为了语义明确在此声明
        int target = left;
        for (int i = left; i < right; i++) {
            if (arr[i] < pivot) {
                swap(arr, target++, i);
            }
        }
        swap(arr, target, right);// target 已经处在正确的位置
        return target;
    }

    /*** merge:递归实现 从外向里 ***/

    private static void mergeSort(int[] arr, int left, int right) {
        if (left == right) return;//待排序列长度为1
        int middle = (left + right) / 2;
        mergeSort(arr, left, middle);
        mergeSort(arr, middle + 1, right);
        merge(arr, left, middle, right);
    }

    /*** merge:迭代实现 从里向外 ***/
    private static void mergeSort(int[] arr) {
        int len = arr.length;
        int left;//需要归并的左坐标
        int middle;//需要归并的中坐标(定义为左侧的结束端坐标),也就是步长的最后一个
        int right;//需要归并的右坐标
        for (int mergeLen = 1; mergeLen < len; mergeLen *= 2) {
            left = 0;
            while (left + mergeLen < len) { // 有后面的数组需要归并
                middle = left + mergeLen - 1;
                right = middle + mergeLen < len ? middle + mergeLen : len - 1;
                merge(arr, left, middle, right);
                left = right + 1;
            }
        }
    }

    private static void merge(int[] arr, int left, int leftEnd, int right) {
        int len = right - left + 1;
        int[] temp = new int[len];//辅助空间
        int tempIndex = 0;//辅助空间指针
        int i = left;//左侧指针
        int j = leftEnd + 1;//右侧指针
        while (i <= leftEnd && j <= right) {
            if (arr[i] <= arr[j]) {// 带等号保证归并排序的稳定性
                temp[tempIndex++] = arr[i++];
            } else {
                temp[tempIndex++] = arr[j++];
            }
        }
        while (i <= leftEnd) {
            temp[tempIndex++] = arr[i++];//左侧数组未
        }
        while (j <= right) {
            temp[tempIndex++] = arr[j++];
        }
        for (int k = 0; k < len; k++) {
            arr[left + k] = temp[k];//将辅助空间内容替换至真实数组的 left-right 空间
        }
    }

    /*** heap ***/
    private static void heapSort(int[] arr) {
        buildHeap(arr);//初始化大顶堆
        int maxHeapIndex = arr.length - 1;
        while (maxHeapIndex > 0) {// 堆(无序区)元素个数大于1,未完成排序
            swap(arr, 0, maxHeapIndex--);// 此处交换操作很有可能把后面元素的稳定性打乱,所以堆排序是不稳定的排序算法
            adjustHeap(arr, 0, maxHeapIndex);// 从新的堆顶元素开始向下进行堆调整,时间复杂度O(logn)
        }
    }

    private static void buildHeap(int[] arr) { // 建堆,时间复杂度O(n)
        int len = arr.length;
        for (int i = len / 2 - 1; i >= 0; i--) {//从最后一个非叶子节点开始,向上调堆,当i==0时,所有堆成为最大堆
            adjustHeap(arr, i, len - 1);
        }
    }

    private static void adjustHeap(int[] arr, int i, int maxIndex) {
        int leftChild = i * 2 + 1;
        int rightChild = i * 2 + 2;
        int max = i;
        if (leftChild <= maxIndex && (arr[leftChild] > arr[max])) {
            max = leftChild;
        }
        if (rightChild <= maxIndex && (arr[rightChild] > arr[max])) {
            max = rightChild;
        }
        if (max != i) {
            swap(arr, i, max);//把最大的换到当前堆顶,然后继续调剂被破坏的子堆
            adjustHeap(arr, max, maxIndex);// 保证被破坏的子堆继续维持大顶堆性质
        }
    }
}

Java ArrayList实现的快排,归并排序,堆排序 用ArrayList实现的排序算法,希望对有需要的同学有帮助,如有错误请指出。JDK版本为1.7 立即下载

相关推荐

告别Failed to start错误!保姆级教程:用Ubuntu20.04安装盘搞定GRUB与系统服务修复

本文提供Ubuntu20.04系统启动失败的专业修复指南,详细讲解如何利用安装盘解决GRUB与系统服务问题,避免重装系统导致的数据丢失。涵盖分区挂载、chroot环境操作、服务诊断与修复等实用技巧,帮助用户高效恢复系统正常运行。

weixin_32578161的博客 331

java实现选择、插入、归并、快速排序以及优化

选择排序 一共n-1轮循环,第一轮将第一个数与它后面所有数比较,若它大于后面某个数则交换,然后继续拿这个新的索引为0的数与后面的数继续比较,直到这一轮循环结束。第二轮循环则拿索引为1的数与它后面的数继续比较(重复上一轮的操作)。 public static void selectsort(int[] arr){ for(int i=0;i<arr.length-1;i++){

qq_33535433的博客 672

MODIS 遥感数据批量下载(使用Cygwin)

MODIS 遥感数据批量下载(使用Cygwin)包含Cygwin的下载教程

weixin_45913084的博客 916

九大排序算法总结(转)

原文链接https://blog.youkuaiyun.com/foreverling/article/details/43798223, 感谢原文作者 楚兴大牛的分享,转载只为了能方便阅读,如有侵权还请联系,我将马上对文章进行删除 转 九大排序算法总结 排序算法可以分为内部排序和外部排序,...

1076

静态时序分析(STA)_深入解析Data to Data Checks的零周期挑战

本文深入解析了静态时序分析(STA)中Data to Data Checks的核心概念与零周期挑战。重点探讨了当Setup要求值超过时钟周期时,工具如何调整发射沿,并导致Hold检查的发射与捕获沿“分裂”这一反直觉现象。文章通过案例详细解读了时序报告,并提供了通过调整约束或接受多周期保持两种策略来应对这一挑战,帮助工程师正确理解和处理此类复杂时序检查。

weixin_29204205的博客 349

openEuler 20.03 LTS面向RK3399移植系列(3)—openEuler 20.03 LTS面向Firefly RK3399的第一个版本(Linux kernel 4.4)

任务动机:完成openEuler面向RK3399开发板的移植。 任务描述:按照固件烧写准备,固件获取,固件打包和烧写的步骤实现openEuler面向RK3399开发板的移植,整理过程和相关命令记录到文档。 1. 制作openEuler的rootfs.img 1.1 开发环境 树莓派--openEuler系统 openEuler 20.03 LTS 的内测版本镜像,下载。 1.2 具体操作 1.2.1 ssh远程连接树莓派 确定树莓派IP ssh连接 1.2.2 制作rootfs.img

火种源码的机器人技术专栏 2366

快速排序与归并排序Java实现版

快速排序 快速排序(Quicksort) 是一种排序算法,平均时间复杂度为:O(n log n),最坏需要 O(n²),但很少见,快速排序之所以叫快速排序,就是因为它比一般的排序算法要快。 快速排序使用了分而治之的思想,步骤如下: 选择基准值(pivot) 将数组分成两个子数组:小于基准值的元素和大于基准值的元素 对这两个子数组进行快速排序 不同的选取基数值策略对排序性能都有很大的影响。 递归...

张可的博客 1112

深度可分离卷积(DepthwiseSeparableConvolution):Depthwise卷积与Pointwise卷积

深度可分离卷积不用多说,在轻量级网络架构方面是一个绕不开的话题,只要接触深度学习多多少少会接触。深度可分离卷积即DepthwiseSeparableConvolution,该卷积将一个常规卷积过程划分成两个完成Depthwise卷积和Pointwise卷积,在保证输出一样时,计算量大大降低。首先来看,一个常规卷积是怎么实现的。其示意图如果我们从通道数变换的角度来看,卷积就是将3通道的tensor变为了4通道的tensor,我们来看看深度可分离卷积是怎么实现通道的变化的。...

xu.hyj 1万+

Java排序之快排、归并、及冒泡排序

1、快排 import java.util.Arrays; public class QuickRem { public static void main(String[] args) { int[] data = {9, -16, 21, 23, -30, -23, 22, 24, 22, 44, 45}; System.out.println(&quot;...

123 286

SpringBoot + MyBatis-Plus 高效实现数据变更记录:从注解到通用审计方案(附源码)

*** 数据变更审计插件* 拦截增删改操作,自动记录变更日志*/@Component@Resource/*** 拦截SQL执行*/@Override/*** 数据变更审计插件* 拦截增删改操作,自动记录变更日志/*** 拦截SQL执行。

2601_94871597的博客 557

基于YOLOv11的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理系统

基于YOLOv11的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理系统

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1218

七大排序算法(Java实现)——冒泡、快排、插入、希尔、选择、堆排、归并

*** 交换排序:稳定,O(n^2)* 1. 冒泡排序:* 相邻两个元素两两比较,若逆序则交换* 每一轮会确定一个最大值到它最后的位置上,只需n-1轮排序* 优化:如果某一轮排序从头至尾没有发生交换,说明已经有序,结束* @param array 待排序列*/i < n - 1;i++) { // n-1轮排序j++) { // 每轮会确定一个最值if(array[j] > array[j + 1]) { // 逆序则交换// 本轮发生了交换。

weixin_46356448的博客 945

使用自制的NTC测量模块测试Plecs的热仿真效果

可以测试:您完全可以用这个模型来测试热仿真。NTC 模型是连接电气域和热域的关键桥梁。实现闭环:通过这种方式,您创建了一个高度真实的正反馈闭环系统:负载增加 -> 损耗增加 -> 温度升高 -> NTC 阻值变化 -> 控制电路可能因此调整(如降低频率或电流)-> 损耗变化 -> 温度变化。应用场景:这对于设计过温保护 (OTP) 电路风扇控制系统以及分析热失控条件非常有用。单位:确保热域中使用的单位( Kelvin 或 Celsius )与您的 C-Script 模型输入期望的单位一致。

311

Java 实现常见六大排序算法(快排、堆排、归并、选择、冒泡、插入)

package sort; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main{ //1.快排 + 两种优化 public static void quickSort(List<Integer> arr,int l,int r) { if(r-l <= 10){ //优化一:当数据量较小时改为插入排序

Mr_Lewis的博客 910

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

七大常见排序

本文介绍了七种常见排序算法及其实现。主要内容包括:1) 插入排序(直接插入排序和希尔排序),希尔排序通过分组插入优化效率;2) 选择排序(直接选择排序和堆排序),堆排序利用堆结构提高效率;3) 交换排序(冒泡排序和快速排序),快速排序采用分治策略,提供hoare、挖坑法和双指针三种实现方式;4) 归并排序,通过分解和合并实现排序。每种算法都给出了C语言实现代码,并分析了时间复杂度和空间复杂度。其中快速排序和归并排序的时间复杂度最优,为O(nlogn)。文章通过图示和代码详细说明了各算法的实现原理和优化方法。

2302_81072215的博客 958

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

【Java】——基础算法Java代码

算法基础笔记,随学随更

qq_50497708的博客 1453

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

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

Java排序算法全解析:从冒泡到TimSort的工程实践

排序算法是数据结构与算法的基础,也是Java面试中高频考察点。理解时间复杂度、空间复杂度和稳定性等评价维度,能帮助你从本质上区分冒泡、选择、插入、归并、快排和堆排序的适用场景。快速排序凭借原地分区和缓存友好性成为工程首选,而归并排序以稳定性见长,堆排序则在Top K问题中发挥价值。JDK的Arrays.sort根据数据类型和数组长度动态选择双轴快排或TimSort,充分体现了算法设计中的工程取舍。本文结合实际代码与踩坑经验,梳理了常见排序算法的原理、实现细节及性能对比,助力开发者夯实内功并从容应对面试。

weixin_29913663的博客 263

Java排序算法全解析:从冒泡到快排的工程实践与面试考点

在Java开发与数据结构学习中,排序算法是连接基础操作与复杂工程问题的关键环节。理解时间复杂度和空间复杂度的权衡,是评估算法效率的起点。通过剖析冒泡、插入、选择等基础排序的优化思路,再到归并、快排、堆排序的工程级实现,能够帮助开发者针对不同的数据规模、稳定性需求和内存限制做出合理选型。排序算法的价值不止于理论,它广泛应用于海量数据Top K提取、有序序列合并及保持多维字段的业务排序场景。Java中Arrays.sort等内置方法的底层机制也值得深入探究。本文从算法原理出发,结合代码与面试高频考察点,梳理从复

weixin_31412781的博客 289

Java排序算法全解析:从手写实现到JDK内置排序

排序算法是计算机程序设计的基石,也是Java开发者面试绕不开的核心考点。从冒泡、插入等基础排序的O(n²)复杂度,到快速排序、归并排序等O(n log n)进阶方案,再到计数排序这类线性时间复杂度算法,不同排序在稳定性、时间与空间复杂度上各有权衡。实际工程中,JDK的Arrays.sort针对基本类型与对象类型分别采用双基准快排与TimSort,体现了算法在真实场景下的优化策略。本文围绕经典排序算法的手写实现与复杂度分析,深入探讨快排优化、堆排序应用、非比较排序适用场景,并解析面试中关于稳定性、最坏情况退化

weixin_29216353的博客 235

Java排序算法详解:从基础到进阶,复杂度与稳定性分析

排序算法是数据结构学习中的核心环节,它不仅串联了数组、树、递归等基础知识,更是衡量工程实现与算法效率的关键。在计算机科学中,时间复杂度与稳定性是评估排序算法优劣的两大关键指标,前者决定了算法在大数据量下的执行效率,后者则关乎相同元素在排序后是否保持原有相对顺序。快速排序、归并排序、堆排序等高级算法通过分治思想将时间复杂度优化至O(n log n),但在实际工程选型中,还需结合数据规模、内存占用等场景综合权衡。本文以Java语言为依托,系统梳理冒泡、插入、选择等基础排序,以及快排、归并、堆排等进阶算法的实现原

weixin_31710909的博客 61

Java九大排序算法详解:原理、复杂度与面试实战

排序算法是数据结构与算法体系中最基础也最关键的部分,它不仅决定了数据处理的效率,更体现了工程师对问题拆解与资源权衡的思考方式。从比较排序的时间复杂度下界O(n log n),到非比较排序借助数据特征实现的线性时间复杂度,不同算法在稳定性、空间占用和适用场景上各有取舍。冒泡、选择、插入等简单排序奠定了边界控制与交换逻辑的基本功;快排、归并、堆排序则展示了分治思想和堆结构的工程价值;计数、桶、基数排序更是在特定数据分布下实现了降维打击。实际开发中,Arrays.sort的底层实现、TopK问题求解、多字段稳定排

weixin_26757925的博客 96

Java之美[从菜鸟到高手演变]之常见的几种排序算法-插入、选择、冒泡、快排、堆排等

解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。设置两个指针:i和j,分别指向第一个和最后一个,i像后移动,j向前移动,选第一个数为标准(一般这样做,当然快排的关键就是这个“标准”的选取),从后面开始,找到第一个比标准小的数,互换位置,然后再从前面,找到第一个比标准大的数,互换位置,第一趟的结果就是标准左边的都小于标准,右边的都大于标准(但不一定有序),分成两拨后,继续递归的使用上述方法,最终有序!

智慧演绎,无处不在 2万+

【排序算法】插入、选择、堆排、快排、归并、计数

排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 平时的上下文中,如果提到排序,通常指的是排升序(非降序)。 通常意义上的排序,都是指的原地排序(in place sort) 。 - **稳定性(重要)** 两个相等的数据,如果经过排序后,排序算法能保证其**相对位置不发生变化**,则我们称该算法是具备稳定性的排序算法。 一个稳定的排序,可以实现为不稳定的排序 但是一个本身就不稳定的排序,是不可以变成稳定的排序

1226 4973

排序算法(冒泡、插入、选择、快排、归并)原理动画及Python、Java实现

目前就总结这了,其它的后面看到了再弄。

niexinyu0026的博客 1609

数据结构-排序(冒泡,选择,插入,希尔,快排,归并,堆排)

假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;当到达=1时,所有记录在统一组内排好序。,与下一个数进行比较,直到找到最大的数,放在n的位置,这是一趟,下一趟还是同样的思路,找到第二大的数,放在n-1的位置,依次下去,总共要走。的区间上找最小的数,在进行交换,也就是有序区间不动,对于无序区间进行比较,依次下去,直至全部有序。

2302_80455544的博客 1459

常见的几种排序算法-插入、选择、冒泡、快排、堆排等

Java面试宝典系列之基础排序算法 博客:http://blog.youkuaiyun.com/zhangerqing(转载请说明出处) 本文就是介绍一些常见的排序算法。排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序、选择排序、冒泡排序、快速排序(重点)、堆排序、归并排序等等。看

lijiajun_blog的博客 2374
上一篇: 统计英文文章中出现的单词数量(基于字节实现)
下一篇: 线程按次序执行队列任务
conquer0715
博客等级 码龄18年 73粉丝 147原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值