当前位置: 首页 > news >正文

C语言之快速排序

目录

一 简介

二 代码实现

快速排序基本原理:

C语言实现快速排序的核心函数:

三 时空复杂度

A.时间复杂度

B.空间复杂度

C.总结:


一 简介

快速排序是一种高效的、基于分治策略的比较排序算法,由英国计算机科学家C.A.R. Hoare在1960年提出。

二 代码实现

以下是使用C语言实现快速排序的基本步骤和代码示例:

快速排序基本原理:

  • 选择一个基准元素(pivot),通常选择数组的第一个元素或者最后一个元素。
  • 将所有比基准小的元素移动到基准元素之前,所有比基准大的元素移动到基准之后。这个操作被称为分区操作(partition)。
  • 对基准左右两边的子数组分别递归地进行上述操作。

C语言实现快速排序的核心函数:

#include <stdio.h>// 分区操作,返回基准元素最后的位置
int partition(int arr[], int low, int high) {int pivot = arr[high]; // 基准元素(这里选取了数组的最后一个元素)int i = (low - 1);  // 指针i初始化为low - 1for (int j = low; j <= high - 1; j++) {// 如果当前元素小于或等于基准元素,则与指针i所指向位置的元素交换,并将i后移一位if (arr[j] <= pivot) {i++;// 交换arr[i]和arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 把基准元素放到正确的位置(即所有小于它的元素都在它前面)int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return (i + 1);
}// 快速排序主函数
void quickSort(int arr[], int low, int high) {if (low < high) {// pi是基准元素最后所在的位置int pi = partition(arr, low, high);// 对基准元素左侧子数组进行递归排序quickSort(arr, low, pi - 1);// 对基准元素右侧子数组进行递归排序quickSort(arr, pi + 1, high);}
}// 测试快速排序
int main() {int arr[] = {10, 7, 8, 9, 1, 5};int n = sizeof(arr)/sizeof(arr[0]);quickSort(arr, 0, n-1);printf("Sorted array: \n");for (int i=0; i<n; i++)printf("%d ", arr[i]);return 0;
}

这段代码首先定义了一个partition函数,该函数负责对输入数组进行一次划分操作,然后通过quickSort函数递归地对左右两个子数组执行同样的操作,直到子数组只剩下一个元素为止(因为只有一个元素的数组被认为是有序的)。最终,整个数组会被排序完成。

三 时空复杂度

A.时间复杂度

  • 平均情况:当每次划分都能将数组大致均分为两个子数组时,快速排序的平均时间复杂度为 O(nlog_2n)。这是由于每次递归调用都会将问题规模减半,并且需要对 n 个元素进行 log_2n 层递归。

  • 最好情况:最好的情况即每次选取的基准都能将数组完美地划分为大小相等的两部分,此时时间复杂度也是 O(nlog_2n)

  • 最坏情况:最坏的情况是每次划分后,一个子数组为空或只有一个元素,而另一个子数组包含所有剩余元素。例如,对于已经完全有序的数组,这种情况会导致退化为O(n^2)的时间复杂度。然而,在实际应用中,可以通过随机化选择基准元素(如三数取中法)来避免这种极端情况的发生,从而保证快速排序在期望下的时间复杂度仍为O(nlog_2n)

B.空间复杂度

  • 递归栈空间:快速排序是一种递归算法,其递归深度取决于输入数据的结构。在最坏情况下,递归深度可以达到 n,所以空间复杂度为 O(n)。但大多数情况下,递归深度为log_2n,此时的空间复杂度主要来自于递归调用栈,约为 O(log_2n)

  • 辅助空间:快速排序在原地排序的情况下不需要额外的数据存储空间,除了递归调用栈所占用的空间外,算法本身不使用其他额外空间,因此辅助空间复杂度可认为是 O(1)。

C.总结:

综上所述,快速排序在理想情况下是一个非常高效的排序算法,具有较好的平均性能。不过需要注意的是,为了避免最坏情况下的性能下降,通常会采取一些策略优化基准元素的选择方法。

相关文章:

  • 蓝桥杯之动态规划冲刺
  • matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面
  • ArrayList和LinkedList区别
  • GPT-4引领AI新纪元,Claude3、Gemini、Sora能否跟上步伐?
  • 十四、GPT
  • Spring Security AuthenticatedVoter 错误访问控制漏洞复现(CVE-2024-22257)
  • java基础知识点学习路线整理
  • cesium.js加载模型后,重新设置旋转角度属性值
  • Http的缓存有哪些
  • sadtalker-api/
  • Redisson
  • 前端学习资源整合
  • 使用js去除字符串内所带有空格
  • nodejs pkg打包跨平台执行文件,带.node插件(sharp、sqlite3)
  • 机器学习模型—K means
  • CentOS7简单部署NFS
  • HomeBrew常规使用教程
  • JavaScript的使用你知道几种?(上)
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Java比较器对数组,集合排序
  • JS字符串转数字方法总结
  • Just for fun——迅速写完快速排序
  • Laravel 实践之路: 数据库迁移与数据填充
  • opencv python Meanshift 和 Camshift
  • Python socket服务器端、客户端传送信息
  • SpiderData 2019年2月25日 DApp数据排行榜
  • tab.js分享及浏览器兼容性问题汇总
  • vue总结
  • 编写高质量JavaScript代码之并发
  • 分类模型——Logistics Regression
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 人脸识别最新开发经验demo
  • 如何选择开源的机器学习框架?
  • 入门级的git使用指北
  • 深度学习入门:10门免费线上课程推荐
  • 小试R空间处理新库sf
  • 做一名精致的JavaScripter 01:JavaScript简介
  • 阿里云ACE认证之理解CDN技术
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #NOIP 2014# day.1 T2 联合权值
  • #在 README.md 中生成项目目录结构
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)nginx 配置(nginx.conf)
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (8)STL算法之替换
  • (第一天)包装对象、作用域、创建对象
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)ssm户外用品商城 毕业设计 112346
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET MVC第三章、三种传值方式
  • .NET 跨平台图形库 SkiaSharp 基础应用