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

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

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

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

前言

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

核心思路:手动模拟栈

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 是快指针
  {
     keyi = left; 
     prev = left;
     cur = left + ;
     (cur <= right) {
        
        
         (a[cur] < a[keyi] && ++prev != cur) {
            (a[prev], a[cur]);
        }
        cur++;
    }
    
    (a[keyi], a[prev]);
     prev; 
}


{
    stack<> st;
    
    
    
     (left < right) {
        st.(right);
        st.(left);
    }

     (!st.()) {
        
         begin = st.();
        st.();
         end = st.();
        st.();

        
         keyi = (a, begin, end);
        

        
        

        
         left2 = keyi + ;
         right2 = end;
        
         (right2 - left2 >= ) {
            st.(right2);
            st.(left2);
        }

        
         left1 = begin;
         right1 = keyi - ;
         (right1 - left1 >= ) {
            st.(right1);
            st.(left1);
        }
    }
}
int
PartitionSlowFast
(int* a, int left, int right)
int
// 选取最左边为 key 的下标
int
int
1
while
// 如果快指针指向的值小于 key,且 prev 下一步不是 cur 自己
// prev 前进一步,并交换 prev 和 cur 的值
if
swap
// 最后将 key 放到 prev 的位置
swap
return
// 返回 key 最终的位置
// 2. 非递归快速排序主函数
void QuickSortNonR(int* a, int left, int right)
int
// 初始状态入栈:注意栈是后进先出
// 我们希望出来的时候先拿 begin,再拿 end
// 所以先压入 right (end),再压入 left (begin)
if
push
push
while
empty
// 取栈顶元素
int
top
pop
int
top
pop
// 使用快慢指针法进行一趟分割
int
PartitionSlowFast
// [begin, keyi-1] keyi [keyi+1, end]
// 核心逻辑保持不变:先处理右边,再处理左边(为了模拟递归顺序)
// 也就是先压入右区间,再压入左区间
// 处理右区间 [keyi+1, end]
int
1
int
// 区间只有一个元素不入栈,区间不存在也不入栈
if
1
push
push
// 处理左区间 [begin, keyi-1]
int
int
1
if
1
push
push

非递归实现的优势

1. 防止栈溢出

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

2. 性能优化

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

目录

  1. 前言
  2. 核心思路:手动模拟栈
  3. 1. 原理对比
  4. 2. 操作逻辑
  5. 流程解析
  6. 代码实现
  7. 非递归实现的优势
  8. 1. 防止栈溢出
  9. 2. 性能优化

更多推荐文章

查看全部
  • Windows 下安装 OpenClaw 并接入飞书机器人指南
  • 基于 Web 架构知识将 PHP 企业网站重构为 Java 系统
  • 生产环境 Nginx 双机热备部署 - Keepalived 多模式配置
  • Java 利用 Spire.XLS 精确控制 Excel 打印页边距
  • Java 多线程:线程池原理与 ThreadPoolExecutor 详解
  • 基于 LangChain 与 CAMEL 框架开发智能 Agent 实战
  • 2026 年高校 AIGC 检测升级下的论文降重工具选型指南
  • Vue 3 核心面试题与实战解析
  • Linux 45 个高效命令技巧集锦
  • FPGA 摄像头采集处理显示指南:OV5640 至 HDMI 实时显示
  • 算法技巧:前缀和一维与二维应用解析
  • Agent Skills:构建可扩展 AI 代理能力的模块化架构
  • 云开发 Copilot:AI 驱动的低代码开发实战
  • PDFShuffler:简单高效的 PDF 页面管理工具
  • Spring AI Agent Skills 接入指南与原理剖析
  • K-means 聚类算法原理与实现详解
  • MySQL DQL 全面解析
  • 基于 Rokid 灵珠平台搭建旅游 AR 智能体实战指南
  • Webots 导入 STL 模型及尺寸颜色调整指南
  • Android 快递物流信息布局实现详解

相关免费在线工具

  • 加密/解密文本

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