数据结构的快速排序(c语言版)
一.快速排序的概念
1.快排的基本概念
快速排序是一种常用的排序算法,它是基于分治策略的一种高效排序算法。它的基本思想如下:
- 从数列中挑出一个元素作为基准(pivot)。
- 将所有小于基准值的元素放在基准前面,所有大于基准值的元素放在基准后面。这个过程称为分区(partition)操作。
- 递归地应用上述步骤到左右两个子数列上,直到各个子数列只有一个元素为止。
这样通过不断的分割和排序,就可以实现整个数列的排序。快速排序的时间复杂度平均情况下为O(nlogn),虽然在最坏情况下会退化为O(n^2),但在实际应用中往往是一种高效的排序算法。
2.快排的适用场景
-
大规模数据排序:快速排序的平均时间复杂度为O(nlogn),在处理大规模数据时比其他算法如冒泡排序、插入排序更加高效。
-
内存受限的环境:快速排序是一种就地排序算法,不需要额外的存储空间,这在内存受限的环境(如嵌入式系统)中更有优势。
-
数据较为随机分布:快速排序的性能最佳情况发生在数据较为随机分布的情况下。如果数据已经基本有序或完全逆序,则会退化为O(n^2)的时间复杂度。
-
需要频繁排序的场景:由于快速排序的实现相对简单,且不需要额外空间,因此在需要频繁进行排序的场景中更有优势,如动态维护一个有序集合。
-
并行计算环境:快速排序可以很好地并行化,利用多核处理器可以大幅提高排序效率,在并行计算环境中表现出色。
总的来说,对于大规模、内存受限、数据较为随机分布且需要频繁排序的场景,快速排序通常是一个很好的选择。但对于小规模数据集或数据已经基本有序的情况,其他简单排序算法可能会更加高效。
3.快排的优点
优点:
- 时间复杂度平均情况下为O(nlogn),是比较高效的排序算法。
- 算法简单,且可以就地排序,不需要额外的存储空间。
- 相比于归并排序,快速排序的递归调用次数较少。
- 在硬件条件受限的情况下(如嵌入式系统),快速排序的空间复杂度优势更加明显。
4.快排的缺点
缺点:
- 最坏情况下的时间复杂度为O(n^2),发生在输入数据已经有序或完全逆序的情况。
- 对于小规模数据集,其他简单排序算法如插入排序、冒泡排序效率可能会更高。
- 快速排序是不稳定的排序算法,即相等元素的相对位置可能会改变。
- 算法实现的难度略高于一些其他排序算法,需要掌握分区操作等技巧
二.快速排序的功能
-
就地排序:快速排序是一种原地排序算法,它不需要额外的存储空间来保存中间结果。这使它在空间利用率方面具有优势,特别适用于内存受限的环境。
-
时间复杂度:快速排序的平均时间复杂度为O(nlogn),这使它成为高效的排序算法之一。但在最坏情况下,如输入数据已经完全有序或逆序,时间复杂度会退化到O(n^2)。
-
分治策略:快速排序采用分治的思想,通过不断将数组划分为较小的子数组,然后对子数组进行排序,最终达到整个数组有序的目标。这种递归的方式使算法实现相对简单。
-
分区操作:快速排序的核心是分区操作。它会选择一个基准元素,将数组划分为两个子数组,一个包含小于基准的元素,另一个包含大于等于基准的元素。这个过程是快速排序的关键。
-
随机化:为了避免最坏情况下的时间复杂度,快速排序通常会随机选择基准元素。这样可以保证平均情况下的高效性。
-
并行化:快速排序可以很好地并行化。在分区操作时,左右两个子数组是相互独立的,可以同时进行排序。这在多核处理器环境中可以大幅提高排序效率。
-
适用范围广泛:快速排序可以排序各种数据类型,如整数、浮点数、字符串等。并且可以根据实际需求定制比较函数,满足不同场景的排序需求。
-
稳定性:快速排序是一种不稳定的排序算法,即相等元素的相对位置可能会改变。如果需要保持相等元素的相对顺序,可以考虑使用其他稳定的排序算法,如归并排序。
三.快速排序的代码实现
1.变量的交换
swap(int *a, int *b)
函数的实现非常简单,它使用一个临时变量 temp
来交换 a
和 b
的值。这是一种常见的交换两个变量值的方式。
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}
2.划分元素
partition(int arr[], int low, int high)
函数的核心思想是选择最后一个元素作为基准(pivot),然后将数组划分为两部分:小于基准的元素在左边,大于等于基准的元素在右边。它使用一个指针 i
来记录小于基准的子数组的最后一个位置,然后遍历数组,将小于基准的元素交换到左边。最后,它将基准元素交换到正确的位置,并返回该位置。
int partition(int arr[], int low, int high) {int pivot = arr[high]; // 选择最后一个元素作为基准int i = (low - 1); // 小于基准的子数组的最后一个位置for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);
}
3.快排的递归实现
quickSort(int arr[], int low, int high)
函数实现了快速排序的递归过程。它首先检查数组长度是否大于 1,如果是,则调用 partition()
函数来划分数组。然后,它递归地对左右两个子数组进行排序。这个过程会一直持续,直到每个子数组的长度为 1 或 0,此时排序完成。
void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}
4.main函数
main()
函数展示了如何使用快速排序算法对一个整数数组进行排序。它首先创建一个示例数组,然后调用 quickSort()
函数对数组进行排序。最后,它打印出排序后的数组。
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: ");for (int i = 0; i < n; i++)printf("%d ", arr[i]);printf("\n");return 0;
}
四.快速排序的源代码
-
swap(int *a, int *b)
函数用于交换两个整数的值。 -
partition(int arr[], int low, int high)
函数用于将数组划分为两个子数组。它选择最后一个元素作为基准,然后将小于基准的元素放在左边,大于等于基准的元素放在右边。该函数返回基准元素的最终位置。 -
quickSort(int arr[], int low, int high)
函数是快速排序的主要实现。它首先检查数组长度是否大于 1,如果是,则调用partition()
函数来划分数组。然后递归地对左右两个子数组进行排序。 -
main()
函数展示了如何使用快速排序算法对一个整数数组进行排序。它首先创建一个示例数组,然后调用quickSort()
函数对数组进行排序。最后,它打印出排序后的数组。
这个实现使用了最后一个元素作为基准,并采用原地排序的方式。你可以根据需要修改基准的选择方式,或者添加随机化来避免最坏情况下的时间复杂度。
#include <stdio.h>
#include <stdlib.h>void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int partition(int arr[], int low, int high) {int pivot = arr[high]; // 选择最后一个元素作为基准int i = (low - 1); // 小于基准的子数组的最后一个位置for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);
}void quickSort(int arr[], int low, int high) {if (low < high) {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: ");for (int i = 0; i < n; i++)printf("%d ", arr[i]);printf("\n");return 0;
}
相关文章:

数据结构的快速排序(c语言版)
一.快速排序的概念 1.快排的基本概念 快速排序是一种常用的排序算法,它是基于分治策略的一种高效排序算法。它的基本思想如下: 从数列中挑出一个元素作为基准(pivot)。将所有小于基准值的元素放在基准前面,所有大于基准值的元素放在基准后面。这个过程称为分区(partition)操作…...

数据结构基础篇(4)
十六.循环链表 概念 循环链表是一种头尾相接的链表(最后一个结点的指针域指向头结点,整个链表形成一个环)优点 从表任一结点出发均可找到表中其他结点判断终止 由于循环链表中没有NULL指针,所以涉及遍历操作时,终止条…...

使用cad绘制一个螺旋输送机
1、第一步,绘制一个矩形 2、使用绘图中的样条线拟合曲线,绘制螺旋线。 绘制时使用上下辅助线、阵列工具绘制多个竖线保证样条线顶点在同一高度。 3、调整矩形右侧的两个顶点,使其变形。 矩形1和矩形2连接时,使用blend命令&#…...

迭代器模式(行为型)
目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern)是一种行为型设计模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为,抽象出…...

Django——Admin站点(Python)
#前言: 该博客为小编Django基础知识操作博客的最后一篇,主要讲解了关于Admin站点的一些基本操作,小编会继续尽力更新一些优质文章,同时欢迎大家点赞和收藏,也欢迎大家关注等待后续文章。 一、简介: Djan…...

React 组件通信
1.从父组件向子组件传递参数: 父组件可以通过props将数据传递给子组件。子组件通过接收props来获取这些数据。 // 父组件 const ParentComponent () > {const data Hello, Child!;return <ChildComponent childData{data} />; }; // 子组件 const ChildCompone…...

【再探】设计模式—访问者模式、策略模式及状态模式
访问者模式是用于访问复杂数据结构的元素,对不同的元素执行不同的操作。策略模式是对于具有多种实现的算法,在运行过程中可动态选择使用哪种具体的实现。状态模式是用于具有不同状态的对象,状态之间可以转换,且不同状态下对象的行…...

新人硬件工程师,工作中遇到的问题list
新人硬件工程师能够通过面试,已经证明是能够胜任硬件工程师职责,当然胜任的时间会延迟,而不是当下,为什么呢?因为学校学习和公司做产品,两者之间有差异,会需要适应期。今天来看看新人硬件工程师…...

如何在Linux系统中搭建Zookeeper集群
一、概述 ZooKeeper是一个开源的且支持分布式部署的应用程序,是Google的Chubby一个开源的实现;它为分布式应用提供了一致性服务支持,包括:配置维护、域名服务、分布式同步、组服务等。 官网:https://zookeeper.apach…...

C++:vector的模拟实现
hello,各位小伙伴,本篇文章跟大家一起学习《C:vector的模拟实现》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 ! 如果本篇文章对你有帮助,还请各位点点赞!&…...

QT系列教程(5) 模态对话框消息传递
模态对话框接受和拒绝消息 我们创建一个模态对话框,调用exec函数后可以根据其返回值进行不同的处理,exec的返回值有两种,Qt的官方文档记录的为 QDialog::Accepted QDialog::RejectedAccepted 表示接受消息, Rejected表示拒绝消息…...

Linux学习笔记(清晰且清爽)
本文首次发布于个人博客 想要获得最佳的阅读体验(无广告且清爽),请访问本篇笔记 Linux安装 关于安装这里就不过多介绍了,安装版本是CentOS 7,详情安装步骤见下述博客在VMware中安装CentOS7(超详细的图文教…...

2.5Bump Mapping 凹凸映射
一、Bump Mapping 介绍 我们想要在屏幕上绘制物体的细节,从尺度上讲,一个物体的细节分为:宏观、中观、微观宏观尺度中其特征会覆盖多个像素,中观尺度只覆盖几个像素,微观尺度的特征就会小于一个像素宏观尺度是由顶点或…...

数字化前沿:Web3如何引领未来技术演进
在当今数字化时代,随着技术的不断发展和创新,Web3作为一种新兴的互联网范式,正逐渐成为数字化前沿的代表。Web3以其去中心化、加密安全的特性,正在引领着未来技术的演进,为全球范围内的科技创新带来了新的可能性和机遇…...

【kubernetes】探索k8s集群的存储卷、pvc和pv
目录 一、emptyDir存储卷 1.1 特点 1.2 用途 1.3部署 二、hostPath存储卷 2.1部署 2.1.1在 node01 节点上创建挂载目录 2.1.2在 node02 节点上创建挂载目录 2.1.3创建 Pod 资源 2.1.4访问测试 2.2 特点 2.3 用途 三、nfs共享存储卷 3.1特点 3.2用途 3.3部署 …...

UI线程和工作线程
引用:windows程序员面试指南 工作线程 只处理逻辑的线程,例如:启动一个线程,用来做一个复杂的计算,计算完成之后,此线程就自动退出,这种线程称为工作线程 UI线程 Windows应用程序一般由窗口…...

RandLA-Net 训练自定义数据集
https://arxiv.org/abs/1911.11236 搭建训练环境 git clone https://github.com/QingyongHu/RandLA-Net.git搭建 python 环境 , 这里我用的 3.9conda create -n randlanet python3.9 source activate randlanet pip install tensorflow2.15.0 -i https://pypi.tuna.tsinghua.e…...

洛谷 B3642:二叉树的遍历 ← 结构体方法 链式前向星方法
【题目来源】https://www.luogu.com.cn/problem/B3642【题目描述】 有一个 n(n≤10^6) 个结点的二叉树。给出每个结点的两个子结点编号(均不超过 n),建立一棵二叉树(根结点的编号为 1),如果是叶子结点&…...

飞腾+FPGA多U多串全国产工控主机
飞腾多U多串工控主机基于国产化飞腾高性能8核D2000处理器平台的国产自主可控解决方案,搭载国产化固件,支持UOS、银河麒麟等国产操作系统,满足金融系统安全运算需求,实现从硬件、操作系统到应用的完全国产、自主、可控,是国产金融信…...

uni-app实现页面通信EventChannel
uni-app实现页面通信EventChannel 之前使用了EventBus的方法实现不同页面组件之间的一个通信,在uni-app中,我们也可以使用uni-app API —— uni.navigateTo来实现页面间的通信。注:2.8.9 支持页面间事件通信通道。 1. 向被打开页面传送数据…...

等保系列之——网络安全等级保护测评工作流程及工作内容
#等保测评##网络安全# 一、网络安全等级保护测评过程概述 网络安全等级保护测评工作过程包括四个基本测评活动:测评准备活动、方案编制活动、现场测评活动、报告编制活动。而测评相关方之间的沟通与洽谈应贯穿整个测评过程。每一项活动有一定的工作任务。如下表。…...

自然语言处理中的BERT模型深度剖析
自然语言处理(NLP)是人工智能领域的一个重要分支,它致力于让计算机理解和生成人类语言。近年来,BERT(Bidirectional Encoder Representations from Transformers)模型的出现,极大地推动了NLP领域…...

数据结构:希尔排序
文章目录 前言一、排序的概念及其运用二、常见排序算法的实现 1.插入排序2.希尔排序总结 前言 排序在生活中有许多实际的运用。以下是一些例子: 购物清单:当我们去超市购物时,通常会列出一份购物清单。将购物清单按照需要购买的顺序排序&…...

unicloud 云对象
背景和优势 20年前,restful接口开发开始流行,服务器编写接口,客户端调用接口,传输json。 现在,替代restful的新模式来了。 云对象,服务器编写API,客户端调用API,不再开发传输json…...

【车载开发系列】常用专业术语汇总
【车载开发系列】常用专业词汇汇总 英语全称说明详细HILSHardware In the Loop Simulation车硬件仿真模拟器精密仪器,价格昂贵,机能测试时一定要小心使用。使用简易HILS不能模拟电气故障。要模拟电气故障需要外接故障BoxLSBLeast Significant Bit单位精…...

如何实现Docker容器的自动化升级:不再为手动更新烦恼!
要升级 Docker 容器,你可以按照以下步骤操作,这些步骤涵盖了从拉取最新镜像到重启容器的整个过程。 步骤一:拉取最新的镜像 首先,确保你有最新版本的镜像。例如,如果你要升级一个 Spring Boot 应用的镜像,…...

SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼
概览 在之前 SwiftUI 5.0(iOS 17)TipKit 让用户更懂你的 App 这篇博文里,我们已经初步介绍过了 TipKit 的基本知识。 现在,让我们来看看如何进一步利用 SwiftUI 对 TipKit 提供的细粒度外观定制技巧,让 Tip 更加“明眸…...

使用C#实现VS窗体应用——画图板
✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。🍎个人主页:Meteors.的博客💞当前专栏:小项目✨特色专栏: 知识分享🥭…...

flutter 自定义本地化-GlobalMaterialLocalizations(重写本地化日期转换)
1. 创建自定义 GlobalMaterialLocalizations import package:flutter_localizations/flutter_localizations.dart; import package:kittlenapp/utils/base/date_time_util.dart;///[auth] kittlen ///[createTime] 2024-05-31 11:40 ///[description]class MyMaterialLocaliza…...

HTTPS 原理技术
HTTPS原理技术 背景简介原理总结 背景 随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创&am…...