跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

快速排序非递归实现详解

快速排序非递归实现方案通过手动维护栈结构来替代系统调用栈,有效解决递归深度过大引发的栈溢出问题。核心流程包括初始化栈、循环弹栈获取区间、执行分区操作并将生成的子区间按特定顺序压栈。该实现保留了递归快排的逻辑一致性,同时利用堆内存提升安全性。文章包含 C++ 代码示例及 Hoare 分区法图解,适用于算法学习及面试实战。

萤火微光发布于 2026/3/24更新于 2026/6/1916 浏览
快速排序非递归实现详解

前言

在实际工程中,递归实现的快速排序虽然简洁,但面对极端数据或超大数组时,系统调用栈的深度限制可能引发栈溢出。非递归版本通过手动管理栈结构,不仅规避了这一风险,也是对数据结构掌握程度的更好体现。

核心思路

手动模拟栈

递归的本质是系统隐式维护调用栈。在非递归实现中,我们需要显式创建一个栈(Stack),用来保存待处理的数组区间 [left, right]。

区间存取策略

由于栈遵循后进先出(LIFO)原则,为了模拟递归'先左后右'的执行顺序,在将子区间压入栈时,必须先压右区间,再压左区间。这样弹出时才能先处理左区间。

模拟过程演示

假设数组为 [6, 1, 2, 3, 4, 5, 9, 7, 10, 8],下标范围 [0, 9]。

  1. 初始化:将整个区间 [0, 9] 压入栈。
  2. 循环处理:
    • 弹栈获取当前区间 [begin, end]。
    • 执行分区操作(Partition),得到基准值位置 keyi。
    • 此时数组被分为 [begin, keyi-1] 和 [keyi+1, end]。
    • 检查左右区间有效性(长度大于 1),按'先右后左'的顺序压入栈。
  3. 结束条件:栈为空时,排序完成。

分区示意图

代码实现

以下是基于 C++ 标准库 std::stack 的实现,采用快慢指针法进行分区。

#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;

// 快慢指针分区法
int PartitionSlowFast(int* a, int left, int right) {
    int keyi = left; // 选取最左边为 key 的下标
    int prev = left;
    int cur = left + 1;
    while (cur <= right) {
        // 如果快指针指向的值小于 key,且 prev 下一步不是 cur 自己
        if (a[cur] < a[keyi] && ++prev != cur) {
            swap(a[prev], a[cur]);
        }
        cur++;
    }
    // 最后将 key 放到 prev 的位置
    swap(a[keyi], a[prev]);
    return prev;
}

// 非递归快速排序主函数
void QuickSortNonR(int* a, int left, int right) {
    stack<int> st;
    // 初始状态入栈:注意栈是后进先出
    // 我们希望出来的时候先拿 begin,再拿 end
    // 所以先压入 right (end),再压入 left (begin)
    if (left < right) {
        st.push(right);
        st.push(left);
    }

    while (!st.empty()) {
        // 取栈顶元素
        int begin = st.top(); st.pop();
        int end = st.top(); st.pop();

        // 使用快慢指针法进行一趟分割
        int keyi = PartitionSlowFast(a, begin, end);

        // [begin, keyi-1] keyi [keyi+1, end]
        // 核心逻辑保持不变:先处理右边,再处理左边(为了模拟递归顺序)
        // 也就是先压入右区间,再压入左区间

        // 处理右区间 [keyi+1, end]
        int left2 = keyi + 1;
        int right2 = end;
        if (right2 - left2 >= 1) {
            st.push(right2);
            st.push(left2);
        }

        // 处理左区间 [begin, keyi-1]
        int left1 = begin;
        int right1 = keyi - 1;
        if (right1 - left1 >= 1) {
            st.push(right1);
            st.push(left1);
        }
    }
}

优势分析

防止栈溢出

递归深度受限于系统栈大小。对于倒序等最坏情况,递归层数过深会导致崩溃。非递归版本使用堆内存(Heap)存储栈,空间通常更大,更加安全。

性能优化

在某些极端环境下,函数调用的现场保存与恢复存在微小开销。手动模拟可以省去这部分开销,尽管在现代编译器优化下差异不大,但在对性能敏感的场景仍有意义。

动画演示

目录

  1. 前言
  2. 核心思路
  3. 手动模拟栈
  4. 区间存取策略
  5. 模拟过程演示
  6. 代码实现
  7. 优势分析
  8. 防止栈溢出
  9. 性能优化
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • VMware 17 Ubuntu 虚拟机与宿主机复制粘贴失效修复
  • 大模型落地实战指南:显卡选型、模型训练与未来展望
  • 网络安全入门指南:掌握五大核心能力构建安全思维
  • 基于 FPGA 的高精度 TDC 设计
  • LLaMA-Factory 大模型微调实战指南
  • 2025 年蓝桥杯省赛 C++大学 A 组试题解析
  • 2026 边缘 AI 视觉白皮书:算法固化与产线工程师转型
  • nvm 安装指定版本 Node.js 失败解决方案
  • Spring AI Agent Skills 功能介绍与实战指南
  • AI 智能客服系统构建方案:选型指南与实战避坑
  • OpenAI Codex 全面上手指南
  • Python act-atmos 大气数据处理工具包介绍
  • 昇腾 CANN 学习路径指南:Python、C++ 与算子开发选型
  • Meta-Llama-3-8B-Instruct 代码能力测试及 HumanEval 45+ 解析
  • Python 字典(dict)数据类型详解
  • JavaScript 错误处理:Uncaught (in promise) 错误分析与解决方案
  • OpenClaw 机器人本地部署与配置实战
  • 告别 MobaXterm:开源终端模拟器 Tabby 深度对比与迁移指南
  • AI 辅助前端页面开发提速 3 倍:生成 HTML+CSS 仅需改细节
  • Python IDLE 中文汉化方法

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online