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

快速排序非递归实现详解:栈模拟与代码实战

综述由AI生成快速排序非递归实现利用显式栈模拟递归过程,避免系统栈溢出风险。通过手动管理子数组区间入栈顺序(先右后左),确保处理逻辑与递归一致。代码采用快慢指针法进行分区,重点展示了如何在不使用函数调用的情况下完成排序任务,适合对内存管理与算法底层有深入需求的开发者参考。

RustyLab发布于 2026/3/16更新于 2026/6/421 浏览
快速排序非递归实现详解:栈模拟与代码实战

前言

本文结合图解与代码,深入剖析快速排序的非递归实现。虽然递归版本在面试中常见,但面试官往往更倾向于考察非递归写法,因为这能体现对栈结构及内存管理的理解深度。

核心思路:手动模拟栈

1. 原理对比

在标准递归快排中,系统会自动分配调用栈来记录 left 和 right 以及返回地址。非递归版本则不再依赖系统,而是显式创建一个 Stack 数据结构来管理待处理的区间。

2. 操作逻辑

  • 入栈:存储每次需要排序的子数组起止下标(begin, end)。
  • 出栈:弹出一组下标进行分区,生成新的左右子区间后,再压回栈中。

由于栈遵循后进先出(LIFO)原则,为了模拟递归的'先左后右'处理顺序,我们在入栈时应先压右区间,再压左区间。这样下一轮循环弹出时,会先处理左区间。

流程解析

假设数组为 [6, 1, 2, 3, 4, 5, 9, 7, 10, 8],我们定义左右区间的边界变量。

初始化阶段只需将完整区间 [0, N-1] 压入栈中。随后进入主循环,只要栈不为空,就持续执行以下操作:

  1. 弹栈:取出一组任务 (begin, end)。
  2. 分区:使用快慢指针法(PartitionSlowFast)分割当前区间,得到基准值位置 keyi。
  3. 划分区间:此时数组被分为 [begin, keyi-1]、keyi、[keyi+1, end] 三部分。
  4. 入栈:若左右子区间有效(长度大于 1),优先压入右区间,再压入左区间。

当栈彻底清空时,意味着所有子区间都已有序,排序完成。

区间分割逻辑如图所示:

文章配图

代码实现

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

// 1. 实现快慢指针法分区 (PartitionSlowFast)
// prev 是慢指针,cur 是快指针
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 自己
        // prev 前进一步,并交换 prev 和 cur 的值
        if (a[cur] < a[keyi] && ++prev != cur) {
            swap(a[prev], a[cur]);
        }
        cur++;
    }
    // 最后将 key 放到 prev 的位置
    swap(a[keyi], a[prev]);
    return prev; // 返回 key 最终的位置
}

// 2. 非递归快速排序主函数
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);
        }
    }
}

非递归实现的优势

1. 防止栈溢出

递归的深度受限于系统栈大小。若数据量极大或处于最坏情况(如倒序),递归层数过深可能导致程序崩溃。非递归版本利用堆内存(Heap)存储栈,空间通常比系统栈大得多,更加安全。

2. 性能优化

在某些极端环境下,函数调用本身存在开销(保存现场、恢复现场)。手动模拟可以省去这些微小的开销,提升运行效率。

目录

  1. 前言
  2. 核心思路:手动模拟栈
  3. 1. 原理对比
  4. 2. 操作逻辑
  5. 流程解析
  6. 代码实现
  7. 非递归实现的优势
  8. 1. 防止栈溢出
  9. 2. 性能优化
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 前端精确数字运算:使用 BigNumber.js 解决 JavaScript 精度问题
  • LLM 存储优化实战:解决大量 QA 与长对话记忆问题
  • C++ 基础数据类型详解与课后练习
  • C++ 视角下的进程、线程与协程:概念、原理及应用场景
  • Coze 平台全解析:100 个落地场景与发布指南
  • Linux 环境下 Git 版本控制工具使用指南
  • AI 大模型开发指南:三本经典书籍深度解析
  • OpenClaw 浏览器控制:利用 Chrome Debug 实现持久化登录与自动化
  • 栈相关算法实战:模板实现与有效括号判定
  • 天工 AI 辅助产品经理工作流程与多模态功能体验
  • 五种精确身份证号匹配算法设计与实现
  • 力扣第 1 题:两数之和(C 语言实现)
  • Qwen3+Qwen Agent 智能体开发实战:接入 MCP 工具
  • 网络安全自学指南:三个阶段与核心学习路线
  • Go 语言快速学习总结
  • 文心一言开源版部署与多维度测评实践
  • Qwen3-VL 基于 Llama-Factory 的 QLoRA 微调与部署全流程实战
  • OpenClaw 配置 GLM-4.7 Flash 与 DuckDuckGo 实现飞书机器人联网问答
  • Java 冷热钱包架构与用户资产安全保护
  • Prompt 提示词编写指南:如何发挥大语言模型最大潜力

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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