实现 Hoare 分区方案的快速排序算法详解

实现 Hoare 分区方案的快速排序算法详解

本文深入探讨了基于 Hoare 分区方案的快速排序算法的 Java 实现。我们将详细解析快速排序的核心思想——分治策略,并重点讲解 Hoare 分区过程,包括枢轴选择、双指针移动及元素交换逻辑。通过完整的代码示例和逐步解释,帮助读者理解并掌握这种高效的排序算法,同时提供性能考量和实践建议,确保算法的正确性和效率。

快速排序概述

快速排序(quicksort)是一种高效的、基于比较的排序算法,其核心思想是“分而治之”(divide and conquer)。它通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据要小,然后按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,最终使整个数据序列有序。

快速排序的关键在于“分区”操作。常见的分区方案有两种:Lomuto 分区和 Hoare 分区。本教程将重点介绍 Hoare 分区方案的实现。

Hoare 分区方案详解

Hoare 分区方案是快速排序的原始设计,它通常比 Lomuto 分区更高效,因为它执行的交换次数更少。Hoare 分区的基本思想是:

选择枢轴(Pivot):从待排序的数组中选择一个元素作为枢轴。在本实现中,我们选择子数组的第一个元素作为枢轴。双指针移动:使用两个指针 i 和 j。i 从子数组的起始位置开始向右移动,j 从子数组的结束位置开始向左移动。比较与交换:指针 j 从右向左移动,直到找到一个小于或等于枢轴的元素。指针 i 从左向右移动,直到找到一个大于或等于枢轴的元素。如果 i < j,则交换 arr[i] 和 arr[j]。枢轴归位:当 i >= j 时,循环结束。此时,指针 j 所在的元素就是枢轴最终的正确位置。所有 j 左边的元素都小于或等于枢轴,所有 j 右边的元素都大于或等于枢轴。

这种分区方式将数组分为两部分,枢轴本身可能不在最终的 j 位置,但 j 位置是枢轴值最终应该放置的位置,且 j 将数组有效分割。

Java 实现

我们将通过一个完整的 Java 代码示例来演示如何实现基于 Hoare 分区方案的快速排序。

1. quickSort 方法

这是快速排序的递归主函数。它接收一个整数数组、起始索引和结束索引(不包含)。

static void quickSort(int[] arg, int startIndex, int endIndex) {    // 基本情况:如果子数组的长度小于2,则无法再分区,直接返回    if (endIndex - startIndex < 2) {        return;    }    // 调用 getPivotIndex 方法进行分区,并获取枢轴最终的索引    int pivotIndex = getPivotIndex(arg, startIndex, endIndex);    // 对枢轴左侧的子数组进行递归排序    quickSort(arg, startIndex, pivotIndex);    // 对枢轴右侧的子数组进行递归排序    quickSort(arg, pivotIndex + 1, endIndex);}

2. getPivotIndex 方法(分区逻辑)

这个方法实现了 Hoare 分区方案的核心逻辑。

private static int getPivotIndex(int[] arg, int startIndex, int endIndex) {    // 选择子数组的第一个元素作为枢轴值    int pivotVal = arg[startIndex];    // 初始化左指针和右指针    int i = startIndex;    int j = endIndex;    // 当左指针小于右指针时,继续进行分区    while (i < j) {        // 右指针从右向左移动,直到找到一个小于或等于枢轴的元素        // 注意:这里使用 --j 是因为 endIndex 是不包含的,所以 j 初始值是 endIndex,        // 第一次使用时会变为 endIndex - 1        while (i = pivotVal));        // 如果左指针仍小于右指针,说明找到了一个需要移动到左侧的元素        if (i < j) {            arg[i] = arg[j]; // 将右侧找到的小于枢轴的元素移动到左指针当前位置        }        // 左指针从左向右移动,直到找到一个大于或等于枢轴的元素        // 注意:这里使用 ++i        while (i < j && (arg[++i] <= pivotVal));        // 如果左指针仍小于右指针,说明找到了一个需要移动到右侧的元素        if (i < j) {            arg[j] = arg[i]; // 将左侧找到的大于枢轴的元素移动到右指针当前位置        }    } // 循环结束时,i 和 j 相遇,此时 j 的位置就是枢轴值应该放置的位置    // 将枢轴值放到其最终的正确位置    arg[j] = pivotVal;    // 返回枢轴的最终索引    return j;}

3. 完整代码示例

public class QuickSortHoare {    public static void main(String[] args) {        int[] unsortedArray = {12, 3, 45, 23, 6, -4, -6, 10, 1, 8};        System.out.println("原始数组:");        for (int i : unsortedArray) {            System.out.print(i + " ");        }        System.out.println();        // 调用快速排序算法        quickSort(unsortedArray, 0, unsortedArray.length);        System.out.println("排序后的数组:");        // 打印排序后的数组        for (int i : unsortedArray) {            System.out.print(i + " ");        }        System.out.println();    }    /**     * 快速排序主函数,采用 Hoare 分区方案。     *     * @param arg        待排序的数组     * @param startIndex 子数组的起始索引(包含)     * @param endIndex   子数组的结束索引(不包含)     */    static void quickSort(int[] arg, int startIndex, int endIndex) {        // 基本情况:如果子数组的长度小于2,则无法再分区,直接返回        if (endIndex - startIndex < 2) {            return;        }        // 调用 getPivotIndex 方法进行分区,并获取枢轴最终的索引        int pivotIndex = getPivotIndex(arg, startIndex, endIndex);        // 对枢轴左侧的子数组进行递归排序        quickSort(arg, startIndex, pivotIndex);        // 对枢轴右侧的子数组进行递归排序        quickSort(arg, pivotIndex + 1, endIndex);    }    /**     * 实现 Hoare 分区方案,将数组分为两部分并返回枢轴的最终索引。     *     * @param arg        待排序的数组     * @param startIndex 子数组的起始索引(包含)     * @param endIndex   子数组的结束索引(不包含)     * @return 枢轴的最终索引     */    private static int getPivotIndex(int[] arg, int startIndex, int endIndex) {        // 选择子数组的第一个元素作为枢轴值        int pivotVal = arg[startIndex];        // 初始化左指针和右指针        int i = startIndex;        int j = endIndex;        // 当左指针小于右指针时,继续进行分区        while (i < j) {            // 右指针从右向左移动,直到找到一个小于或等于枢轴的元素            // 注意:这里使用 --j 是因为 endIndex 是不包含的,所以 j 初始值是 endIndex,            // 第一次使用时会变为 endIndex - 1            while (i = pivotVal));            // 如果左指针仍小于右指针,说明找到了一个需要移动到左侧的元素            if (i < j) {                arg[i] = arg[j]; // 将右侧找到的小于枢轴的元素移动到左指针当前位置            }            // 左指针从左向右移动,直到找到一个大于或等于枢轴的元素            // 注意:这里使用 ++i            while (i < j && (arg[++i] <= pivotVal));            // 如果左指针仍小于右指针,说明找到了一个需要移动到右侧的元素            if (i < j) {                arg[j] = arg[i]; // 将左侧找到的大于枢轴的元素移动到右指针当前位置            }        } // 循环结束时,i 和 j 相遇,此时 j 的位置就是枢轴值应该放置的位置        // 将枢轴值放到其最终的正确位置        arg[j] = pivotVal;        // 返回枢轴的最终索引        return j;    }}

运行与测试

要运行上述代码,您可以将其保存为 QuickSortHoare.java 文件,然后使用 Java 编译器编译并运行:

javac QuickSortHoare.javajava QuickSortHoare

预期输出:

原始数组:12 3 45 23 6 -4 -6 10 1 8 排序后的数组:-6 -4 1 3 6 8 10 12 23 45 

注意事项与性能分析

枢轴选择:本实现选择子数组的第一个元素作为枢轴。虽然简单,但如果输入数组已经部分有序或完全有序,这种选择可能导致最坏情况,即每次分区都将数组分为一个空子数组和一个 n-1 大小的子数组,使得时间复杂度退化到 O(n²)。更优的枢轴选择策略包括:随机选择枢轴:从子数组中随机选择一个元素作为枢轴。三数取中法:选择子数组的第一个、中间和最后一个元素,取它们的中位数作为枢轴。时间复杂度平均情况:O(n log n)。在大多数情况下,快速排序表现优秀。最坏情况:O(n²)。当枢轴选择不当,导致每次分区都产生极度不平衡的子数组时发生(例如,选择最大或最小元素作为枢轴)。空间复杂度:O(log n)(平均情况),主要由递归调用的深度决定。最坏情况下,递归深度可能达到 O(n)。稳定性:快速排序是一种不稳定的排序算法,因为它在分区过程中可能会交换相等元素的相对顺序。Hoare 分区与 Lomuto 分区Hoare 分区:通常执行更少的交换操作,因此在实际应用中可能更快。它将数组分为两个子数组,枢轴最终的位置在 j 处,但 arg[j] 不一定是原始的枢轴值。Lomuto 分区:保证枢轴最终会放置在其排序后的最终位置,并且其左侧所有元素都小于它,右侧所有元素都大于它。Lomuto 分区通常需要更多的交换操作。

总结

本教程详细介绍了使用 Hoare 分区方案实现快速排序算法的 Java 代码。通过理解分治思想、枢轴选择以及双指针移动和交换的分区逻辑,您可以有效地实现并应用快速排序。虽然快速排序在最坏情况下可能表现不佳,但通过优化枢轴选择策略,它在平均情况下的性能非常出色,是实际应用中最常用的排序算法之一。

以上就是实现 Hoare 分区方案的快速排序算法详解的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月6日 19:31:23
下一篇 2025年11月6日 19:33:16

相关推荐

  • 币圈散户注意 下轮牛市前必须布局的百倍潜力币

    币圈投资者,特别是散户,普遍希望在下一轮牛市到来之前,找到具有爆发潜力的加密货币,实现资产的快速增长。市场中关于“百倍币名单”的讨论层出不穷,但识别潜在百倍币并非易事,更没有所谓的确定性“泄露名单”。本文旨在探讨如何根据一些常用的分析维度,帮助您构建自己的潜在名单研究框架,而不是直接提供一个固定的列…

    2025年12月8日
    000
  • 币圈散户速进!最新空投教程 零成本撸羊毛指南,已有玩家日入5000U

    币圈空投是许多散户寻找零成本获取数字资产机会的一种方式。它们通常由区块链项目发起,旨在推广代币并吸引用户。本文将为您提供一份详细的空投参与指南,解释如何以较低的门槛参与,并探讨标题中提到的潜在高收益是如何产生的,以及散户应该如何理性看待和操作。 2025主流空投软件官网注册地址推荐: MetaMas…

    2025年12月8日
    000
  • 警惕!币圈散户正在被AI取代 学会这4种量化交易策略,你也能成为”智能散户”

    随着人工智能技术的飞速发展,它在金融领域的应用也日益深入,特别是在加密货币交易市场。传统上依赖个人分析和主观判断的散户,正面临着被AI强大的数据处理和策略执行能力所取代的挑战。本文旨在探讨这一现象,并针对标题中提出的问题,提供一个可行的解决方案:学习量化交易策略。我们将讲解如何理解并掌握四种基础的量…

    2025年12月8日 好文分享
    000
  • labubu币有哪些分类_labubu怎么选

    【权威推荐】2025主流数字货币交易平台合集 Binance币安 官网直达: 安卓安装包下载: 欧易OKX ️ 官网直达: 安卓安装包下载: Huobi火币️ 官网直达: 安卓安装包下载: Labubu币有哪些分类?如何选择适合自己的Labubu版本? Labubu币是一类社区发起的Meme代币,以…

    2025年12月8日
    000
  • labubu币有哪些链_labubu属于什么链

    【权威推荐】2025主流数字货币交易平台合集 Binance币安 官网直达: 安卓安装包下载: 欧易OKX ️ 官网直达: 安卓安装包下载: Huobi火币️ 官网直达: 安卓安装包下载: Labubu 币在哪些区块链发行?Labubu 属于什么链? Labubu 币作为近期颇具关注度的 Meme …

    2025年12月8日
    000
  • 紧急通知!这些DeFi软件正在空投 手慢无 下一个百倍币就在这里

    本篇文章将解释DeFi空投是什么,为何会出现空投,以及用户如何寻找潜在的空投机会并参与其中,帮助读者了解空投参与的一般流程,抓住可能的市场机遇。虽然标题中提到“下一个百倍币”,但投资存在风险,空投的价值也具有不确定性,本文将侧重于介绍参与空投的过程和需要注意的事项。 2025主流空投软件官网注册地址…

    2025年12月8日
    000
  • 以太坊ETH最全历史价格2010-2025明细回顾(2025年最新版)

    以太坊价格从2015年的0.70美元涨至2025年的3,050美元,经历了多个关键阶段。1)2015-2016年,ETH从0.70美元上涨至2016年中的20.64美元;2)2017-2018年受ICO热潮推动,2018年初达到1,417美元,随后因监管担忧跌至80美元;3)2019-2020年稳定…

    2025年12月8日
    000
  • 稳定币是什么 稳定币什么意思

    稳定币作为加密货币领域的重要创新,旨在解决传统数字货币价格剧烈波动的问题,为市场提供稳定的价值媒介和存储工具。下面将从定义、机制、作用等方面详细介绍稳定币: 稳定币,顾名思义,是一种价格相对稳定的加密数字货币。与比特币、以太坊等价格波动剧烈的传统加密货币不同,稳定币通过与特定资产(如法定货币、商品或…

    2025年12月8日
    000
  • 稳定币是什么 怎么购买

    稳定币是一种特殊的加密货币。通俗意义上讲,它是一种锚定真实资产的数字货币,价值通常与某种法定流通货币、商品或其他资产挂钩,旨在解决比特币等传统加密货币价格波动剧烈的问题,从而成为更实用的交易媒介和价值存储手段。 稳定币购买平台: 欧易OKX: Binance币安: 火币Huobi: Gateio芝麻…

    2025年12月8日
    000
  • 稳定币是什么 与比特币有什么区别

    稳定币是一种基于区块链技术的加密货币,它通过锚定特定的资产,如法定货币(通常是美元)、大宗商品或其他加密资产,采用资产抵押、担保或算法稳定机制等,来维持币值的相对稳定。其核心设计目标是在价格剧烈波动的加密市场中充当价值尺度和交易媒介。常见的稳定币有 usdt、usdc、dai 等。 稳定币交易所: …

    2025年12月8日
    000
  • 2025年最值得关注的5大加密货币

    加密货币市场瞬息万变,充满了机遇与挑战。展望2025年,哪些数字资产可能脱颖而出,值得我们持续关注?本文旨在基于当前的行业发展趋势、技术创新以及市场叙事,为您梳理出5个在未来一年可能展现出潜力的加密货币项目,作为您了解和研究的方向。请注意,本文提供的信息仅供参考,不构成任何投资建议,数字资产投资具有…

    2025年12月8日 好文分享
    000
  • 2025年稳定币投资新手教程 如何选择安全的稳定币平台

    2025年,随着数字资产的逐步规范化和加密货币市场的成熟,稳定币成为越来越多新手用户的首选投资工具。本文将帮助新手用户了解如何选择安全可靠的稳定币平台,并列出当前主流平台排行榜和对比分析,助力用户做出明智决策。 Top 10稳定币平台推荐(2025年最新) Binance(币安) 全球用户最多的加密…

    2025年12月8日 好文分享
    000
  • 货币交易app十大排行榜 2025官方最新版

    数字货币市场交易平台众多,本文介绍了币安、OKX、gate.io等多个知名应用。它们提供多样化的现货、合约等交易产品及服务,各有特色,用户可根据需求选择。 货币交易app十大排行榜 1. Binance 作为全球交易量领先的数字货币交易所,提供极其广泛的加密货币选择,涵盖了几乎所有主流和大量的山寨币…

    2025年12月8日 好文分享
    000
  • 2025年最值得投资的5大数字货币 从选币到买卖手把手教学

    本文将围绕2025年数字货币的投资趋势展开,探讨几个具备潜力的前沿领域,并提供一套从筛选项目到完成交易的实践操作指南。同时,文章还将解析如何发现并参与最新的空投活动,帮助您更好地把握市场机遇。通过本文的讲解,您将学习到一套系统性的投资分析方法和具体的操作步骤。 2025主流加密货币交易所官网注册地址…

    2025年12月8日
    000
  • 【量化交易】如何用AI自动炒币年化300%? 程序员都在用的网格交易策略公开

    本文将围绕“如何通过AI实现高年化收益”这一问题,详细拆解在量化交易中广受欢迎的网格交易策略。文章将阐述网格交易的基本原理、AI在其中扮演的角色,并提供一个清晰的操作步骤指引,帮助你理解这一自动化交易工具的运作机制。需要明确的是,300%的年化收益是一个非常理想化的目标,实际收益受市场波动、参数设置…

    2025年12月8日
    000
  • 什么是稳定币?入门必懂锚定机制与核心作用

    稳定币是加密货币市场中的关键工具,它通过与法定货币等资产锚定,保持币值稳定,成为连接传统金融与区块链世界的重要桥梁。了解稳定币的锚定机制与核心作用,有助于用户规避价格波动带来的风险,更安全、便捷地参与加密货币投资或跨境支付。 主流稳定币交易所官网 币安Binance: ( )欧易OKX: ( )火币…

    2025年12月8日
    000
  • 易欧oex正版安装包v6.127.1 易欧oex官方安卓客户端更新

    易欧OEX安卓客户端v6.127.1版本上线,优化交互性能、提升稳定性并新增热门项目交易入口。1.下载推荐通过官网扫码获取正版;2.更新亮点包括界面响应提速、安全增强及主流项目支持;3.对比排名中OEX位列第一,优势突出;4.对比维度显示其性能流畅、界面友好、功能丰富、安全保障强且评分高;5.新功能…

    2025年12月8日
    000
  • 恐惧贪婪指数飙升! “贪婪区域”如何布局?3大暴涨币种提前埋伏名单

    当市场情绪指标“恐惧贪婪指数”进入贪婪甚至极度贪婪区域时,往往预示着市场情绪高涨,但也伴随着潜在的回调风险。本文将围绕这一现象,探讨在“贪婪区域”中如何进行合理的投资布局,并对布局过程中的关键策略进行讲解。同时,将分析当前市场环境下值得关注的几类加密资产,为投资者提供参考思路,帮助其在波动的市场中寻…

    2025年12月8日
    000
  • 恐惧贪婪指数连续5日上升 这7个山寨币或成最大赢家 提前布局指南

    本文将围绕“恐惧贪婪指数”这一市场情绪指标的连续上升现象进行分析,并阐述这一变化可能对特定类型的数字资产带来的影响。文章不会直接推荐具体的投资标的,而是旨在提供一套系统性的分析框架和布局指南,讲解如何根据市场情绪的变化,去发现和筛选那些可能在市场回暖中表现突出的山寨币,帮助用户理解背后的逻辑和操作过…

    2025年12月8日
    000
  • Web3如何重塑互联网格局 揭秘2025年最值得布局的区块链风口

    本文将深入探讨Web3如何通过其去中心化、用户所有权的核心理念,颠覆现有的互联网结构。同时,我们将为您揭示并分析至2025年最具有发展潜力的几大区块链技术风口,通过讲解这些前沿领域的核心逻辑与应用前景,帮助您理解未来互联网的演进方向。 2025主流加密货币交易所官网注册地址推荐: 欧易OKX: Bi…

    2025年12月8日
    000

发表回复

登录后才能评论
关注微信