Java List快速排序实现详解与优化

java list快速排序实现详解与优化

本文深入探讨了如何在Java中为自定义对象列表实现快速排序算法。我们将从理解`Comparable`接口的正确使用开始,逐步构建一个高效且易于理解的快速排序实现,重点讲解分区(partitioning)策略和递归调用,并提供完整的代码示例及性能优化建议,确保读者能够掌握在实际项目中应用快速排序的能力。

1. 理解 Comparable 接口与对象比较

在对自定义对象列表进行排序时,Java要求这些对象能够相互比较。这通常通过实现 java.lang.Comparable 接口来完成。Comparable 接口定义了一个 compareTo(T o) 方法,该方法根据对象的自然顺序进行比较。

compareTo 方法的约定如下:

如果当前对象小于指定对象 o,则返回负整数。如果当前对象等于指定对象 o,则返回零。如果当前对象大于指定对象 o,则返回正整数。

以下是 Location 类的正确 compareTo 方法实现,它根据 zipCode 字段进行升序排序:

立即学习“Java免费学习笔记(深入)”;

public class Location implements Comparable {    private final String zipCode;    private final String city;    private final Double latitude;    private final Double longitude;    private final String state;    public Location(String zipCode, Double latitude, Double longitude, String city, String state) {        this.zipCode = zipCode;        this.city = city;        this.latitude = latitude;        this.longitude = longitude;        this.state = state;    }    // 省略 getter 方法...    @Override    public int compareTo(Location o) {        // 将邮政编码字符串转换为整数进行比较        int thisZip = Integer.parseInt(this.zipCode);        int otherZip = Integer.parseInt(o.getZipCode());        // 使用 Integer.compare 确保符合 Comparable 接口的约定,实现升序排序        return Integer.compare(thisZip, otherZip);    }    @Override    public String toString() {        return "Location{" +               "zipCode='" + zipCode + ''' +               ", city='" + city + ''' +               '}';    }}

注意事项:

原始的 compareTo 实现逻辑有误,它将大于返回 -1,小于返回 1,这实际上会导致降序排序,并且逻辑不完整。Integer.parseInt() 可能会抛出 NumberFormatException,在实际应用中,如果 zipCode 不总是有效的数字字符串,需要进行异常处理或数据校验。Integer.compare(int x, int y) 是 Java 7 引入的静态方法,它比 x > y ? 1 : (x < y ? -1 : 0) 更简洁且不易出错。

2. 快速排序算法概览

快速排序(QuickSort)是一种高效的、基于比较的排序算法,采用分治(Divide and Conquer)策略。其基本思想是:

选择基准(Pivot): 从列表中选择一个元素作为“基准”。分区(Partition): 重新排列列表,将所有小于基准的元素移到基准的左边,所有大于基准的元素移到基准的右边。在这个分区结束之后,该基准就处于其最终的排好序的位置上。递归排序: 递归地对基准左边和右边的子列表进行快速排序。

3. 实现快速排序的核心方法

我们将通过三个辅助方法来实现快速排序:一个用于交换元素,一个用于执行分区操作,以及一个递归排序方法。

九歌 九歌

九歌–人工智能诗歌写作系统

九歌 322 查看详情 九歌

3.1 元素交换辅助方法

这是一个简单的通用方法,用于交换列表中两个指定位置的元素。

public static  void swapElements(List list, int firstIndex, int secondIndex) {    T temp = list.get(firstIndex);    list.set(firstIndex, list.get(secondIndex));    list.set(secondIndex, temp);}

3.2 分区(Partition)方法

分区是快速排序中最关键的一步。它的目标是选择一个基准元素,然后重新排列子数组,使得所有小于基准的元素都位于基准的左侧,所有大于基准的元素都位于基准的右侧。最后,返回基准的最终位置。

这里我们采用一种常见的Lomuto分区方案,选择子数组的第一个元素作为基准。

/** * 执行分区操作,将列表中的元素根据基准值进行划分。 * * @param list 待排序的列表。 * @param startIndex 子数组的起始索引。 * @param endIndex 子数组的结束索引。 * @return 基准元素最终所在的索引。 */private static <T extends Comparable> int partition(List list, int startIndex, int endIndex) {    T pivotValue = list.get(startIndex); // 选择第一个元素作为基准    int smallerElementsBoundary = startIndex; // smallerElementsBoundary 跟踪小于基准的元素的右边界    // 遍历从 startIndex + 1 到 endIndex 的所有元素    for (int current = startIndex + 1; current <= endIndex; current++) {        // 如果当前元素小于基准值        if (list.get(current).compareTo(pivotValue) < 0) {            smallerElementsBoundary++; // 扩展小于基准元素的区域            swapElements(list, smallerElementsBoundary, current); // 将当前元素与 smallerElementsBoundary 处的元素交换        }    }    // 循环结束后,所有小于基准的元素都在 startIndex+1 到 smallerElementsBoundary 之间    // 将基准元素(最初在 startIndex)与 smallerElementsBoundary 处的元素交换    swapElements(list, startIndex, smallerElementsBoundary);    return smallerElementsBoundary; // 返回基准元素的最终位置}

3.3 递归快速排序方法

这是快速排序的递归核心。它根据分区操作返回的基准索引,将列表分为两个子列表,并对它们分别进行递归排序。

/** * 快速排序的递归实现。 * * @param list 待排序的列表。 * @param startIndex 子数组的起始索引。 * @param endIndex 子数组的结束索引。 */private static <T extends Comparable> void quickSortRecursive(List list, int startIndex, int endIndex) {    // 基本情况:如果子数组只有一个或没有元素,则无需排序    if (startIndex >= endIndex) {        return;    }    // 执行分区操作,获取基准元素的最终位置    int pivotIndex = partition(list, startIndex, endIndex);    // 递归地对基准左侧的子数组进行排序    quickSortRecursive(list, startIndex, pivotIndex - 1);    // 递归地对基准右侧的子数组进行排序    quickSortRecursive(list, pivotIndex + 1, endIndex);}

3.4 公共入口方法

为了方便调用,提供一个公共的入口方法来启动快速排序。

/** * 对列表进行快速排序的公共入口方法。 * * @param list 待排序的列表。 */public static <T extends Comparable> void quickSort(List list) {    if (list == null || list.size() <= 1) {        return; // 空列表或单元素列表无需排序    }    quickSortRecursive(list, 0, list.size() - 1);}

4. 完整的快速排序实现示例

将上述所有部分整合到一起,形成一个完整的快速排序工具类。

import java.util.Collections;import java.util.List;import java.util.ArrayList;import java.util.Arrays;public class QuickSortUtil {    /**     * 对列表进行快速排序的公共入口方法。     *     * @param list 待排序的列表。     */    public static <T extends Comparable> void quickSort(List list) {        if (list == null || list.size() <= 1) {            return; // 空列表或单元素列表无需排序        }        quickSortRecursive(list, 0, list.size() - 1);    }    /**     * 快速排序的递归实现。     *     * @param list 待排序的列表。     * @param startIndex 子数组的起始索引。     * @param endIndex 子数组的结束索引。     */    private static <T extends Comparable> void quickSortRecursive(List list, int startIndex, int endIndex) {        // 基本情况:如果子数组只有一个或没有元素,则无需排序        if (startIndex >= endIndex) {            return;        }        // 执行分区操作,获取基准元素的最终位置        int pivotIndex = partition(list, startIndex, endIndex);        // 递归地对基准左侧的子数组进行排序        quickSortRecursive(list, startIndex, pivotIndex - 1);        // 递归地对基准右侧的子数组进行排序        quickSortRecursive(list, pivotIndex + 1, endIndex);    }    /**     * 执行分区操作,将列表中的元素根据基准值进行划分。     * 采用Lomuto分区方案,选择第一个元素作为基准。     *     * @param list 待排序的列表。     * @param startIndex 子数组的起始索引。     * @param endIndex 子数组的结束索引。     * @return 基准元素最终所在的索引。     */    private static <T extends Comparable> int partition(List list, int startIndex, int endIndex) {        T pivotValue = list.get(startIndex); // 选择第一个元素作为基准        int smallerElementsBoundary = startIndex; // smallerElementsBoundary 跟踪小于基准的元素的右边界        // 遍历从 startIndex + 1 到 endIndex 的所有元素        for (int current = startIndex + 1; current <= endIndex; current++) {            // 如果当前元素小于基准值            if (list.get(current).compareTo(pivotValue) < 0) {                smallerElementsBoundary++; // 扩展小于基准元素的区域                swapElements(list, smallerElementsBoundary, current); // 将当前元素与 smallerElementsBoundary 处的元素交换            }        }        // 循环结束后,所有小于基准的元素都在 startIndex+1 到 smallerElementsBoundary 之间        // 将基准元素(

以上就是Java List快速排序实现详解与优化的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1035674.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 02:59:39
下一篇 2025年12月2日 03:00:00

相关推荐

  • python需要的软件环境

    运行Python需要满足以下软件环境要求:操作系统:Windows、macOS、LinuxPython解释器:从官方网站下载并安装IDE或文本编辑器:用于代码开发包管理器(例如pip):用于安装和管理第三方库附加工具(可选):版本控制系统、测试框架、代码格式化工具、虚拟环境 Python所需的软件环…

    2025年12月13日
    000
  • python需要哪些软件

    Python开发所需软件:文本编辑器或集成开发环境 (IDE)Python解释器开发工具包 (SDK)数据库访问库(如果需要)可选工具:版本控制系统、单元测试框架、包管理工具、调试器 Python开发所需的软件 要进行Python开发,需要以下软件: 文本编辑器或集成开发环境 (IDE) 文本编辑器…

    2025年12月13日
    000
  • python需要电脑配置

    学习Python所需的电脑配置包括:操作系统:Windows 10或以上、macOS 10.15或以上、Linux Ubuntu 18.04或以上处理器:多核处理器(建议2核以上)处理器速度:2.0 GHz以上内存(RAM):4GB以上,建议8GB或以上硬盘空间:10GB以上显卡:一般开发无需专用,…

    2025年12月13日
    000
  • python需要钱吗

    python 需要花钱吗? Python 作为一门开源编程语言,本身是免费的。这意味着您可以免费下载、使用和修改 Python 源代码。 但是,使用 Python 可能会产生一些费用: 1. 订阅服务: 某些高级工具和服务,例如云服务、IDE(集成开发环境)和持续集成平台,可能需要订阅费。 立即学习…

    好文分享 2025年12月13日
    000
  • 使用 Python 构建 CLI 刽子手游戏

    大家好!我叫 Tyler Edlin,今天我很高兴与大家分享我一直在做的一个小项目——一个用 Python 构建的 CLI 绞刑吏游戏。本文将指导您完成设置项目、理解代码以及克服我所面临的挑战的过程。 项目概况Hangman 游戏是一种简单的猜词游戏,玩家尝试一次猜一个字母。游戏提供有关猜测的反馈并…

    2025年12月13日
    000
  • 如何使用 Python 创建简单的 URL 缩短工具

    url 缩短工具允许用户将长 url 转换为更短、更易于管理的链接。我们可以使用 python 和 flask(一个轻量级 web 框架)构建该工具的简单版本。 先决条件 开始之前,请确保您具备以下条件: 您的系统上已安装python(推荐python 3.6+)。flask 安装完毕。您可以使用 …

    2025年12月13日
    000
  • Python:从初学者到专业人士第 4 部分

    文件处理:学习读取和写入文件 文件处理对于任何程序员来说都是一项至关重要的技能。每个开发人员都应该能够访问外部来源的数据并与之交互,并实现计算和存储。 文件用于在磁盘上存储数据。它们可以包含文本、数字或二进制数据。在 python 中,我们使用内置函数和方法来处理文件。 要打开文件,我们使用 ope…

    2025年12月13日 好文分享
    000
  • 与你交谈系列#2

    介绍 今天我们将开始概述用于解决各种算法问题的概念。对某个概念的理解可能会给你一个直觉,从哪个角度开始思考潜在的解决方案。 有不同但没有太多的概念。今天我将把你的注意力集中在滑动窗口概念上。 滑动窗口 滑动窗口的概念比乍一看要复杂一些。我将通过实际例子来证明这一点。现在,请记住,概念性的想法是我们将…

    2025年12月13日
    000
  • “从概念到代码:使用 Python 构建提醒应用程序”

    大家好!我很高兴向您介绍我的最新项目 Promptly – 一款桌面提醒应用程序,旨在帮助您掌握任务和事件。这个项目结合了我对编码的热情和高效时间管理的实际需求。 项目概况: 在忙碌的生活中,我们很容易忘记重要的任务和事件。及时赶到是为了确保不会发生这种情况。借助 Promptly,您可以为任务设置…

    2025年12月13日
    000
  • CPU模拟器

    最近我开始学习计算机架构,所以利用从中学到的一些东西我开始制作一个cpu模拟器。它从类似汇编结构的文本文件中读取指令,并从主文件中执行它。 它没有很多功能,但我认为它可以通过 CPU 完成某些事情。 回购: 桑蒂亚 / CPU模拟器 CPU模拟器 这个程序试图模拟CPU的行为。 目前开始学习计算机体…

    2025年12月13日
    000
  • 通过单一提示构建和部署 AI 支持的 Web 服务

    在 shuttle,我们一直在开发一种新工具,我们认为它可以改变开发人员处理 ai 集成的方式。我们将其称为 shuttleai,它允许您通过单个提示构建和部署人工智能驱动的 web 服务。 这是 tl;dr: 用通俗易懂的语言描述您的人工智能服务shuttleai 生成项目规范供您查看批准或修改规…

    2025年12月13日
    000
  • 免费编程备忘单集合

    在编程世界中,备忘单是每个开发人员的秘密武器。无论您是初学者还是经验丰富的程序员,这些备忘单都可以帮助您快速找到所需的信息并提高您的工作效率。今天,我们整理了编程备忘单的终极集合,涵盖从 Python 到 Docker 的各种语言和工具。请务必将此页面加入书签! 1.Python Python是一种…

    2025年12月13日
    000
  • OLA Maps Python 包入门

    最近 ola 宣布了他们的新地图平台,并免费赠送一年。如果您打算在项目中使用它,我构建了一个新的 python 包,可以轻松地将 ola maps 功能集成到您的 python 项目中。让我们来探索一下如何使用这个包。 安装 首先,安装软件包: pip install olamaps 验证 在使用o…

    2025年12月13日
    000
  • 使用 PostgresSQL 和 Docker 启动新的 Django 项目

    初始项目设置: $ mkdir 客户端管理$ cd 客户管理$ python3 -m venv .venv$ 源 .venv/bin/activate(.venv) $(.venv) $ python3 -m pip install django~=5.0(.venv) $ django-admin…

    2025年12月13日
    000
  • 语义路由器 – 引导法学硕士

    我想分享我一直在做的一个名为 SemRoute 的项目,我很想得到你的反馈。 SemRoute 是一种语义路由器,它使用向量嵌入根据语义来路由查询。它的设计灵活且易于使用,无需训练分类器或使用大型语言模型。 这是一个简短的概述: 支持多种嵌入模型(OpenAI、MistralAI)支持自定义嵌入模型…

    2025年12月13日
    000
  • 部署 Python FastAPI 应用程序进行渲染

    在 python 框架的世界中,fastapi 是新生事物,也是构建 api 的绝佳选择。同样,对于想要在生产环境中免费快速测试应用程序的开发人员来说,render 是一个不错的选择。 在这篇文章中,我们将介绍如何将 fastapi 应用程序部署到渲染。首先,我们来探讨一下为什么开发者经常选择 fa…

    2025年12月13日 好文分享
    000
  • 使用 Selenium 和视觉比较进行视觉回归测试

    视觉测试对于确保 web 应用程序的外观在更新或更改后保持一致和视觉正确至关重要。本博客将指导您使用 selenium 进行浏览器自动化,并使用自定义图像比较实用程序来执行视觉测试。 简介 视觉测试通过比较不同时间点拍摄的屏幕截图来帮助检测 ui 中的意外变化。在本指南中,我们将使用 seleniu…

    2025年12月13日
    000
  • 使用 Python 构建 Tic-Tac-Toe 终端游戏

    介绍 我叫 Derek,是一名有抱负的软件工程师!最近,我一直在努力通过在线课程学习 Python 和软件开发的基础知识。两年前大学毕业,获得商业计算和信息系统学士学位,对软件开发流程比较熟悉,并具备一定的IT技能;但在编程和解决问题方面,我在技术方面还有很多东西需要学习。因此,我决定参加上述课程,…

    2025年12月13日
    000
  • 征服你的第一个数据库:新手必备的 SQL 查询

    恭喜!您已经踏上了学习 SQL 的激动人心的旅程,这种语言可以解开数据库中隐藏的秘密。无论您是一位崭露头角的数据分析师、好奇的开发人员,还是只是想要运用数据力量的人,了解 SQL 都会改变游戏规则。 这篇博文是您征服第一个数据库的基本指南,为您提供导航数据库所需的基本 SQL 查询。 在此过程中,我…

    2025年12月13日
    000
  • python中出现红色错误怎么办

    python 中红色错误的解决指南 什么是红色错误? 红色错误是 Python 中最严重的错误类型,表示解释器检测到一个无法解析的代码问题。这些错误通常会出现一条开头为 “SyntaxError” 的错误消息。 如何解决红色错误? 解决红色错误的第一步是仔细检查错误消息。错误…

    好文分享 2025年12月13日
    000

发表回复

登录后才能评论
关注微信