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

C 语言快速排序详解:从基础到非递归实现

快速排序是 C 语言中常用的高效排序算法。详细讲解了其核心思想、Hoare 分区实现方式,并针对最坏情况提出了三数取中和小区间优化策略。此外,还探讨了如何通过堆排序辅助小数据量处理,以及利用栈结构将递归算法转换为非递归实现,以避免栈溢出风险。内容涵盖代码逻辑分析与关键步骤说明。

beaabea发布于 2026/2/26更新于 2026/7/2337 浏览
C 语言快速排序详解:从基础到非递归实现

C 语言快速排序详解:从基础到非递归实现

快速排序是 C 语言标准库中采用的一种高效排序算法。本文将深入剖析其核心原理,从基础的 Hoare 分区法入手,逐步讲解三数取中、小区间优化等进阶技巧,最后探讨如何利用栈结构实现非递归版本。

一、快速排序基础

1. 算法思想

快速排序的核心在于'分治'。选取一个基准值(Key),通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

2. 实现思路

我们通常使用两个指针(L 和 R)分别从数组两端向中间扫描。R 指针先向左寻找小于 Key 的元素,L 指针再向右寻找大于 Key 的元素,找到后交换两者位置。重复此过程直到两指针相遇,最后将 Key 与相遇点交换。此时 Key 左侧均小于它,右侧均大于它,完成一次划分。

3. 代码实现

void QuickSort1(int* a, int left, int right) {
    if (left >= right)
        return;
    int key = left;
    int L = left, R = right;
    while (left < right) {
        while (left < right && a[R] >= a[key]) R--;
        while (left < right && a[L] <= a[key]) L++;
        Swap(&a[L], &a[R]);
    }
    Swap(&a[R], &a[key]);
    QuickSort1(a, L, key - 1);
    QuickSort1(a, key + 1, R);
}

二、性能优化

1. 三数取中法

固定选取首元素作为 Key 在最坏情况下(如已排序数组)会导致时间复杂度退化为 O(N^2)。引入三数取中法,比较首、尾、中间三个元素,将中位数作为 Key,能有效避免极端情况。

int FindKey(int* a, int left, int right) {
    int mid = (left + right) / 2;
    if (a[left] > a[right]) {
        if (a[right] > a[mid]) return right;
        else if (a[mid] > a[left]) return left;
        else return mid;
    }  {
         (a[left] > a[mid])  left;
          (a[mid] > a[right])  right;
          mid;
    }
}
else
if
return
else
if
return
else
return

2. 小区间优化

当区间长度较小时(例如小于 10),递归开销可能超过收益。此时可切换至插入排序或堆排序,减少递归层数,提升整体效率。

// 插入排序辅助函数
void InsertSort(int* a, int n) {
    for (int i = 0; i < n - 1; i++) {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0) {
            if (tmp < a[end]) {
                a[end + 1] = a[end];
                --end;
            } else break;
        }
        a[end + 1] = tmp;
    }
}

// 堆排序辅助函数
void AdJustDown(int* a, int parent, int size) {
    int child = 2 * parent + 1;
    while (child <= size - 1) {
        if (child + 1 <= size - 1 && a[child + 1] > a[child]) child++;
        if (a[child] > a[parent]) {
            Swap(&a[child], &a[parent]);
            parent = child;
            child = 2 * parent + 1;
        } else break;
    }
}

void HeapSort(int* a, int sz) {
    int i;
    for (i = (sz - 1 - 1) / 2; i >= 0; i--) AdJustDown(a, i, sz);
    for (i = sz - 1; i > 0; i--) {
        Swap(&a[0], &a[i]);
        AdJustDown(a, 0, i);
    }
}

3. 综合框架

结合上述优化,主排序逻辑如下:

void QuickSort1(int* a, int left, int right) {
    if (left >= right) return;
    int g = right - left + 1;
    if (g < 10) {
        HeapSort(a + left, g);
    } else {
        int key = PartSort1(a, left, right);
        QuickSort1(a, left, key - 1);
        QuickSort1(a, key + 1, right);
    }
}

三、非递归实现

递归深度过大可能导致栈溢出。我们可以使用显式的栈结构来模拟递归调用过程。每次划分后,将左右区间的边界压入栈中,循环处理直到栈为空。

1. 栈结构定义

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef int STDataType;
typedef struct Stack {
    STDataType* a;
    int size;
    int capacity;
} Stack;

void StackInit(Stack* ps);
void StackPush(Stack* ps, STDataType data);
void StackPop(Stack* ps);
STDataType StackTop(Stack* ps);
int StackSize(Stack* ps);
int StackEmpty(Stack* ps);
void StackDestroy(Stack* ps);

2. 主体逻辑

void QuickSortNonR(int* a, int left, int right) {
    Stack S;
    StackInit(&S);
    StackPush(&S, right);
    StackPush(&S, left);
    while (!StackEmpty(&S)) {
        int L = StackTop(&S); StackPop(&S);
        int R = StackTop(&S); StackPop(&S);
        if (L >= R) continue;
        int g = R - L + 1;
        if (g < 10) {
            HeapSort(a + L, g);
        } else {
            int key = PartSort1(a, L, R);
            if (R - key - 1 > 1) {
                StackPush(&S, R);
                StackPush(&S, key + 1);
            }
            if (key - 1 - L > 1) {
                StackPush(&S, key - 1);
                StackPush(&S, L);
            }
        }
    }
    StackDestroy(&S);
}

四、总结

快速排序在实际应用中非常广泛。理解其分区机制及优化手段,对于掌握算法设计思想至关重要。通过上述改进,我们可以在保持平均 O(N log N) 复杂度的同时,增强算法的鲁棒性。

目录

  1. C 语言快速排序详解:从基础到非递归实现
  2. 一、快速排序基础
  3. 1. 算法思想
  4. 2. 实现思路
  5. 3. 代码实现
  6. 二、性能优化
  7. 1. 三数取中法
  8. 2. 小区间优化
  9. 3. 综合框架
  10. 三、非递归实现
  11. 1. 栈结构定义
  12. 2. 主体逻辑
  13. 四、总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 数据结构核心:KMP 算法、Trie 树与并查集实战解析
  • 毕业论文 AI 辅助写作全流程实操指南
  • 把AI当队友用:MonkeyCode的真实项目体验
  • JavaScript 空值判断工具函数
  • MySQL 常用命令速查表
  • 大模型常见面试题汇总与答案解析
  • LLaMA-Factory 详细安装教程
  • RabbitMQ 与 Spring Boot 集成实战:从 Hello World 到生产配置
  • 从多库并存到一库多能:金仓 KingbaseES 融合架构实践
  • Revit 模型 Web 可视化:Revit2GLTF 转换方案详解
  • Sora 模型技术报告:世界模拟器与视频生成能力解析
  • 三维人体姿态估计前沿算法与论文案例
  • NFT 元数据去中心化存储与智能合约集成实战
  • Python 空洞卷积网络架构与 PAMAP2 数据集实验分析
  • DeerFlow 2.0 生产级 AI Agent 框架的 Docker 部署与并行编排
  • C++ 高阶数据结构:二叉搜索树(BST)
  • ZeroClaw 开源:基于 Rust 的轻量级 AI Agent 框架
  • 直流无刷电机 FOC 控制算法
  • Python 爬虫实战:跨境电商数据采集与代理 IP 策略
  • WebGIS、无人机与 AI 融合:构建下一代智能巡检系统

相关免费在线工具

  • 加密/解密文本

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