Java 中常用的排序算法

news2024/9/22 10:01:34

Java 中常用的排序算法有很多,每种算法的时间复杂度和适用场景都不同。以下是几种常见的排序算法及其 Java 实现和讲解:

1. 冒泡排序 (Bubble Sort)

算法思路

  • 重复地遍历数组,每次比较相邻两个元素。如果前一个比后一个大,则交换它们。
  • 每一轮遍历结束后,当前最大值会移动到最后。重复这个过程,直到整个数组有序。

时间复杂度:O(n²)

代码实现

public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        boolean swapped;
        for (int i = 0; i < n - 1; i++) {
            swapped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            // 如果没有发生交换,说明数组已经有序
            if (!swapped) break;
        }
    }
}

2. 选择排序 (Selection Sort)

算法思路

  • 每次遍历数组,找到当前未排序部分的最小元素,将其与未排序部分的第一个元素交换。
  • 这样每次遍历结束后,最小值就放到了正确的位置,逐步缩小未排序部分。

时间复杂度:O(n²)

代码实现

 
public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            // 找到最小元素
            int minIdx = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIdx]) {
                    minIdx = j;
                }
            }
            // 交换
            int temp = arr[minIdx];
            arr[minIdx] = arr[i];
            arr[i] = temp;
        }
    }
}

3. 插入排序 (Insertion Sort)

算法思路

  • 将数组分为已排序和未排序两部分。每次从未排序部分取出一个元素,将其插入到已排序部分的适当位置。
  • 类似于打扑克牌时整理手中的牌。

时间复杂度:O(n²)

代码实现

 
public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {
            int key = arr[i];
            int j = i - 1;
            // 将比 key 大的元素向右移动
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
    }
}

4. 快速排序 (Quick Sort)

算法思路

  • 选择一个"基准"元素,通常选择数组中的最后一个元素。
  • 将数组划分为两部分,一部分比基准小,另一部分比基准大。然后对两部分分别递归进行排序。

时间复杂度

  • 平均:O(n log n)
  • 最坏:O(n²)

代码实现

public class QuickSort {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 找到分区点
            int pivotIndex = partition(arr, low, high);
            // 递归排序左右部分
            quickSort(arr, low, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high]; // 选择最后一个元素为基准
        int i = low - 1;  // i 指向小于 pivot 的最后一个元素
        for (int j = low; j < high; j++) {
            if (arr[j] < pivot) {
                i++;
                // 交换 arr[i] 和 arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        // 交换 pivot 到正确的位置
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return i + 1;
    }
}

5. 归并排序 (Merge Sort)

算法思路

  • 将数组递归地分成两部分,直到每部分只剩一个元素。
  • 然后合并这些小数组,使它们有序。

时间复杂度:O(n log n)

代码实现

public class MergeSort {
    public static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;
            // 递归分割左边部分
            mergeSort(arr, left, mid);
            // 递归分割右边部分
            mergeSort(arr, mid + 1, right);
            // 合并两个有序部分
            merge(arr, left, mid, right);
        }
    }

    private static void merge(int[] arr, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;
        int[] L = new int[n1];
        int[] R = new int[n2];

        // 复制数据到临时数组
        for (int i = 0; i < n1; i++)
            L[i] = arr[left + i];
        for (int j = 0; j < n2; j++)
            R[j] = arr[mid + 1 + j];

        int i = 0, j = 0, k = left;

        // 合并 L 和 R 数组
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        // 复制剩余元素
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }
}

6. 堆排序 (Heap Sort)

算法思路

  • 利用堆这种数据结构来实现排序。先将数据构造成一个大顶堆,然后依次将堆顶元素(最大值)与末尾元素交换,逐步缩小堆的范围并调整堆结构,直到排序完成。

时间复杂度:O(n log n)

代码实现

public class HeapSort {
    public static void heapSort(int[] arr) {
        int n = arr.length;

        // 构建大顶堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }

        // 一个个从堆顶取出最大值,放在数组末尾
        for (int i = n - 1; i > 0; i--) {
            // 交换当前堆顶与最后一个元素
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            // 调整剩余堆结构
            heapify(arr, i, 0);
        }
    }

    private static void heapify(int[] arr, int n, int i) {
        int largest = i;  // 设定父节点为最大值
        int left = 2 * i + 1;  // 左子节点
        int right = 2 * i + 2;  // 右子节点

        // 如果左子节点比父节点大
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }

        // 如果右子节点比当前最大值大
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }

        // 如果最大值不是父节点,则交换并递归调整子树
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;

            heapify(arr, n, largest);
        }
    }
}

总结

  • 冒泡排序选择排序插入排序 都属于 O(n²) 的简单排序算法,适合小规模数据。
  • 快速排序归并排序 都是 O(n)

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

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

相关文章

Web接入Sonic平台之安装

问题及解决方案 1.安装python的airtest-bdd依赖时报错&#xff0c;显示无法编译psutil note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for psutil Failed to build psutil ERROR: ERROR: Failed to b…

【2025】基于 SpringBoot 的电影购票系统、电影购票系统、智能电影购票系统、电影购票平台、电影购票管理、微服务电影购票系统(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

传输层协议(TCP和UDP)

目录 一、UDP 1、UDPAPI 2、UDPAPI的使用 二、TCP 1、TCPAPI 2、TCP的相关特性 2.1 确认应答 2.2 超时重传 2.3 连接管理&#xff08;三次握手&#xff0c;四次挥手&#xff09; 2.4 滑动窗口 2.5 流量控制 2.6 拥塞控制 2.7 延时应答 2.8 捎带应答 2.9 面向字节…

【赵渝强老师】基于ZooKeeper实现Hadoop HA

由于在HA架构中包含的节点比较多&#xff0c;在进行实际部署的时候需要做好集群的规划。图14.9一共使用了4个节点来部署HDFS HA&#xff0c;它们分别是&#xff1a;bigdata112、bigdata113、bigdata114和bigdata115。由于Hadoop默认包含了HDFS和Yarn&#xff0c;因此在部署HDFS…

构建 LLM 应用程序时经常遇到的高级概念的快速指南

使用案例 数据支持的 LLM 应用程序有无数的用例&#xff0c;但大致可以分为四类&#xff1a; 结构化数据提取 Pydantic 提取器允许您指定要从数据中提取的精确数据结构&#xff0c;并使用 LLM 以类型安全的方式填充缺失的部分。这对于从 PDF、网站等非结构化来源中提取结构化…

阿里国际、eBay、乐天等跨境电商如何搭建测评系统给自己店铺测评

要实现自己养号给自己店铺进行测评&#xff0c;确实需要一系列周密的准备和规划&#xff0c;以确保整个过程既稳定安全又有效。以下是详细补充和强化建议&#xff1a; 1. 稳定的测评环境系统 选择高级防关联技术&#xff1a;除了使用国外的服务器、纯净的国外IP和防关联浏览器…

mysql怎样优化count(*) from 表名 where …… or ……这种慢sql

一 问题描述 线上发现一条类似这样的慢sql&#xff08;查询时长8s&#xff09;&#xff1a; select id,name,(select count(*) from t14 where t14.idt15.id or t14.id2t15.id) as cnt from t15 ; t14的id和id2字段上都有索引&#xff0c;但是因为条件里有or&#xff0c;导致…

Kubernetes调度基础

一、RC 和 RS 1. Replication Controller Replication Controller&#xff0c;简称 RC&#xff0c;复制控制器&#xff0c;可确保Pod 副本数达到期望值&#xff0c;也就是 RC 可确保一个 Pod 总是可用&#xff0c;或一组 Pod 的数量永远处于一个定值。 如果存在的 Pod 大于设…

杭州等保测评揭秘:数据安全如何成为企业的“一道锁”

在数字化时代&#xff0c;数据安全已成为企业和机构面临的重要挑战。杭州作为科技创新的前沿城市&#xff0c;积极推进信息安全建设&#xff0c;其中等保测评&#xff08;等级保护测评&#xff09;成为保障数据安全的重要手段。 等保测评是依据《信息安全等级保护管理办法》对…

代码随想录训练营第36天|二维背包

1049. 最后一块石头的重量 II class Solution { public:int lastStoneWeightII(vector<int>& stones) {int sumaccumulate(stones.begin(),stones.end(),0);int targetsum/2;vector<int> dp(target1,0);for(auto& stone: stones){for(int itarget; i>s…

如何快速学习拼音打字?

拼音打字是很多人学会使用电脑或手机的第一步&#xff0c;尤其是对于需要经常输入中文的人来说&#xff0c;熟练掌握拼音打字可以大大提升效率。下面分享一些快速学习拼音打字的方法和技巧&#xff0c;帮助你尽快掌握这项技能。 1. 了解拼音的基本规则 学习拼音打字之前&…

代码随想录算法训练营第五十八天 | 拓扑排序精讲-软件构建

目录 软件构建 思路 拓扑排序的背景 拓扑排序的思路 模拟过程 判断有环 写代码 方法一&#xff1a; 拓扑排序 软件构建 题目链接&#xff1a;卡码网&#xff1a;117. 软件构建 文章讲解&#xff1a;代码随想录 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文…

Vue|mixin混入

目录 mixin混入什么是mixin代码准备如何混入?全局混合 在 Vue 中&#xff0c;混入&#xff08;Mixins&#xff09;是一种灵活的分发功能&#xff0c;可以将可复用的代码片段和功能注入到多个组件中。简单来说&#xff0c;混入允许你在多个组件之间共享逻辑&#xff0c;而无需重…

QT<24> Qt和windows中获取CPU序列号号以及主板序列号

前言&#xff1a;在qt中获取CPU和主板唯一序列号&#xff0c;可以在程序构造函数中判断是否与windows中一致&#xff0c;不一致可以直接退出程序&#xff0c;防止程序daoyong。 一、获取电脑CPU唯一序列号 QString MainPage::get_cpu() {QString cmd"wmic cpu get proc…

DNS和ICMP

DNS DNS&#xff08;Domain Name System &#xff09; DNS 是一整套从域名映射到 IP 的系统 关于DNS背景 TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序 . 但是 IP 地址不 方便记忆 . 于是人们发明了一种叫主机名的东西 , 是一个字符串 , 并且…

computed计算属性与watch侦听器

1.computed计算属性的写法有两种&#xff0c;一种是只读的&#xff0c;只负责展示&#xff0c;另一种可以进行修改&#xff0c;利用get来获取值&#xff0c;利用set来进行修改 2.watch侦听器的写法也有两种&#xff0c;可以直接写成函数&#xff0c;也可以写成对象&#xff0c;…

浅显易懂的Git教程

Git概述 SVN与Git的对比 SVN&#xff08;Subversion&#xff09; 类型&#xff1a;集中式版本控制系统 工作流程&#xff1a; 从中央服务器下载最新版本到本地。在本地进行开发。提交更改回中央服务器。 优点&#xff1a; 简单易用&#xff0c;适合小型团队。版本历史清…

【源代码+仿真+原理图+技术文档+演示视频+软件】基于物联网的多功能手环设计与实现

摘 要 随着社会进步和生活水平的提高&#xff0c;人们对健康的重视程度不断增加。为了更好地了解自身的身心健康状况&#xff0c;人们对高精密、便携式医疗监控仪器的需求也越来越大。电子信息技术和医学的发展相互促进&#xff0c;二者的结合可以解决人们在健康问题上的困扰…

单通道低压全桥驱动芯片既可应用在电子锁,医疗器械等产品中也能直接Pin to pin贝岭的BL8123

芯片描述 GC8123 是一款低压 5V 全桥驱动芯片&#xff0c;为摄像机、消费类产品、玩具和其他低压或者电池供电的运动控制类应用提供了集成的电机驱动解决方案。GC8123 能提供高达 1.2A 的持续输出电流。可以工作在 1.2~6V 的电源电压上。GC8123 具有 PWM&#xff08;IN/IN&…

Git使用教程-将idea本地文件配置到gitte上的保姆级别教程

&#x1f939;‍♀️潜意识起点&#xff1a;个人主页 &#x1f399;座右铭&#xff1a;得之坦然&#xff0c;失之淡然。 &#x1f48e;擅长领域&#xff1a;前端 是的&#xff0c;我需要您的&#xff1a; &#x1f9e1;点赞❤️关注&#x1f499;收藏&#x1f49b; 是我持…