C语言实现快速排序算法

1. 什么是快速排序算法

快速排序的核心思想是通过分治法(Divide and Conquer)来实现排序。

算法的基本步骤是:

1. 选择一个基准值(通常是数组中的某个元素),将数组分成两部分,使得左边的部分所有元素都小于基准值,右边的部分所有元素都大于基准值。

2. 对这两部分分别进行递归排序,直到整个数组有序。

那么,该算法为什么叫做快速排序算法呢?

快速排序算法之所以被称为“快速”,是因为它在大多数情况下都能够快速地完成排序。在平均情况下,其时间复杂度为O(nlogn),其中n为数组的大小。

此外,快速排序还具有原地排序的特点,即不需要额外的辅助空间,只需对原始数组进行原地操作。这些优点使得快速排序成为了排序问题中的一种首选算法。


2. 单趟排序

单趟排序指的就是将数组分为两部分的算法。

对于实现这一步,我们有三种思路。

2.1 霍尔法

霍尔并无什么特殊含义,只是因为最早发现快速排序算法的人叫霍尔,这是他的实现方法。

思路:

1. 先选定一个基准值key(一般选择首元素)。

2. 定义两个指针left和right,分别指向数组的左右两端。

3. left从左往右遍历,寻找大于基准值的元素,right从右往左遍历,寻找小于基准值的元素。

4. 如果left与right未相遇,那么就交换两指针指向的元素。

5. 如果left与right相遇,那么就让key指向的元素与right指向的元素交换。

代码

//霍尔法
int ParSort_1(int* arr, int left, int right)
{int key = left;while (left < right){while (left < right && arr[right] >= arr[key]) { right--; }while (left < right && arr[left] <= arr[key]) { left++; }if (left < right)swap(&arr[left], &arr[right]);}swap(&arr[key], &arr[left]);return left;
}

注意事项(如何保证right和left共同指向的元素与key指向的元素交换是合理的)

1. 如果选取的基准值为首元素,那么在外层循环的一次循环中,一定要让right先进行移动,这样可以确保共同指向的元素是小于或等于基准值的。

2. 如果选取的基准值为最后一个元素,则与上面相反。

2.2 挖坑法

核心思想与霍尔法相同,但是表现形式有所差异。

思路

顾名思义,我们将基准值单独用变量进行存放,而将基准值原本所在的位置空出来成为一个坑(我们将其称作hole)。

1. right先进行遍历,如果发现有小于基准值的元素,则将该元素填入hole中,然后right指向的位置成为新的hole。(假设F小于key)

2. 然后left再进行遍历,如果发现有大于基准值的元素,则将该元素填入hole中,然后left指向的位置成为新的hole。(假设B大于key)

 3. 以此类推,当left与right相遇时,将key填入hole中即可。

代码

//挖坑法
int ParSort_2(int* arr, int left, int right)
{int key = arr[left];int hole = left;while (left < right){while (left < right && arr[right] >= key) { right--; }arr[hole] = arr[right];hole = right;while (left < right && arr[left] <= key) { left++; }arr[hole] = arr[left];hole = left;}arr[hole] = key;return hole;
}

注意事项

对于这个方法来说,洞在谁那边,谁就先开始遍历。

2.3 前后指针法

思路

1. 定义两个指针,prev和cur,prev所指向的以及之前的元素就是小于基准值的元素,cur用于遍历数组。

2. 如果cur找到小于基准值的元素,让prev++,然后交换prev指向的元素和cur指向的元素。

3. 让基准值与prev指向的元素进行交换。

代码

//前后指针
int ParSort_3(int* arr, int left, int right)
{int key = left;int prev = left;int cur = left + 1;while (cur <= right){//arr[cur]小于基准值就交换if (arr[cur] <= arr[key] && ++prev != cur){swap(&arr[prev], &arr[cur]);}cur++;}swap(&arr[key], &arr[prev]);return prev;
}

注意事项

如果选取的基准值为首元素,则在最后让prev指向的元素与基准值交换;如果选区的基准值为最后一个元素,则在最后让prev指向的下一个元素与基准值交换。

3. 快速排序算法的递归实现

按照第一部分的介绍,我们很容易的到下面的代码。

void QuickSort(int* arr, int begin, int end)
{if (begin >= end)return;int key = ParSort_3(arr, begin, end);QuickSort(arr, key + 1, end);//排右边QuickSort(arr, begin, key - 1);//排左边
}

4. 快速排序算法的优化

当数据量十分巨大时,使用递归实现的快速排序算法会由于调用函数次数过多而导致程序效率下降。

由于递归的逻辑结构像是一个树状图,所以在递归的层次较深时,每次进到下一层都会调用上一层两倍数量的函数。

众所周知,2^{n}是一个极其可怕的东西,那么我们能不能在层次较深,所需排序的数组长度较短时,转而使用其他经典的排序算法呢?

于是我们做出了如下的优化:

void QuickSort(int* arr, int begin, int end)
{if (begin >= end)return;if (end - begin <= 8){InsertSort(arr + begin, end - begin + 1);return;}int key = ParSort_3(arr, begin, end);QuickSort(arr, key + 1, end);//排右边QuickSort(arr, begin, key - 1);//排左边
}

当数组长度小于等于9时,我们采用插入排序来进行排序(不止插入排序,其他排序也可)。

//插入排序
void InsertSort(int* arr, int len)
{for (int i = 1; i < len; i++){int j = i;while (j > 0 && arr[j] < arr[j - 1]){swap(&arr[j], &arr[j - 1]);j--;}}
}

5. 结语

快速排序的非递归算法是用栈模拟递归实现的,由于太麻烦我就没写,感兴趣可以自己尝试写写。

单趟排序算法用哪个,快速排序递归还是非递归,层次较深时换用什么排序算法,这些都是可以自由组合的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/795935.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ3.13.x之六_RabbitMQ使用场景

RabbitMQ3.13.x之六_RabbitMQ使用场景 文章目录 RabbitMQ3.13.x之六_RabbitMQ使用场景1. 为什么选择 RabbitMQ&#xff1f;1. 可互操作2. 灵活3. 可靠 2. 常见用户案例1. 服务解耦2. 远程过程调用3. 流处理4. 物联网 1. 为什么选择 RabbitMQ&#xff1f; RabbitMQ 是一个可靠且…

C语言 | Leetcode C语言题解之第8题字符串转换整数atoi

题目&#xff1a; 题解&#xff1a; int myAtoi(char * s){int i0;int out0;int pol1;int lenstrlen(s);if(len0) return 0;while(s[i] ) i; //删除空格if(s[i]-){ //判断正负pol-1;i;}else if(s[i]){pol1;i;}else{pol1;}while(s[i]!\0){if(s[i]<0||s[i]>9){ /…

算法学习(十七)规律

规律 1. 概念 模拟题目过程探索问题规律找出隐含条件 2. 解题技巧&#xff08;我的总结&#xff09; 1> 将 问题中的抽象条件 找出实际意思 题目说明实现649. Dota2 参议院题中每个议员最好表现 禁止后面最近的对方议员 或 禁止前面最远的对方议员我的提交1702. 修改后的…

Python基础教程:从入门到实践

Python&#xff0c;一种解释型、交互式、面向对象的编程语言&#xff0c;因其简洁易懂的语法和强大的功能库而广受欢迎。无论是数据分析、机器学习还是Web开发&#xff0c;Python都发挥着重要作用。本文将带你走进Python的世界&#xff0c;从基础语法开始&#xff0c;逐步深入实…

【智能算法】跳蛛优化算法(AOA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2021年&#xff0c;H Peraza-Vzquez等人受到跳蛛狩猎行为启发&#xff0c;提出了跳蛛优化算法&#xff08;Jumping Spider Optimization Algorithm&#xff0c;JSOA&#xff09;。 2.算法原理 2.1…

【Kaggle】练习赛《鲍鱼年龄预测》(上)

前言 上一篇文章&#xff0c;讲解了《肥胖风险的多类别预测》机器学习方面的文章&#xff0c;主要是多分类算法的运用&#xff0c;本文是一个回归的算法&#xff0c;本期是2024年4月份的题目《Regression with an Abalone Dataset》即《鲍鱼年龄预测》&#xff0c;在此分享高手…

C++数据结构与算法——回溯算法组合问题

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

C++ 引用和指针

C++ 中的引用(Reference)和指针(Pointer)是两种不同的概念,它们在语法上和语义上有很多不同之处,下面是它们的区别: 语法: 引用使用 & 符号声明,并且必须在初始化时绑定到一个对象上。例如:int& ref = obj;指针使用 * 符号声明,并且可以在任何时候指向一个对…

Java入门第6课

1.数据类型的自动转化 java的数据转化是容量小的部分向大的方向转&#xff0c;这个部分很简单&#xff0c;byte->short->int->long&#xff0c;char->int->long;int->double 有一些数据转化虽然是自动的&#xff0c;但是存在数据精度丢失&#xff0c;比如i…

特征增强自蒸馏卷积神经网络

目录 1.1 模型总体架构 1.2 特征增强金字塔模块 1.3 辅助分类器 1.1 模型总体架构 与自然图像相比&#xff0c;遥感场景图像地物较为复杂&#xff0c;具有类间相似度高和类内差异大的特点&#xff0c;这导致常用的网络模型难以有效学习遥感场景图像的表征特征。此外&#xf…

【ARM 嵌入式 C 入门及渐进 21 -- 内存分配相关函数malloc 与 realloc】

请阅读【嵌入式开发学习必备专栏 】 文章目录 malloc 与 reallocmallocrealloc主要差异点 malloc 与 realloc malloc 和 realloc 都是 C 语言标准库中的函数&#xff0c;用于动态内存分配。它们在使用上有明显的区别&#xff1a; malloc malloc&#xff08;Memory Allocatio…

springboot之mybatisPlus多表查询及分页查询

文章目录 一、多表查询二、mybatis-plus条件查询三、分页查询 一、多表查询 可能会用到的注解 这里的场景是&#xff0c;查询每个用户及其所有的订单。就是查询你的id号的同时&#xff0c;把你所有的历史订单信息都拉出来。 表结构这样 CREATE TABLE User ( id INT PRIMARY…

【可靠性】陷阱电荷对TDDB影响的多尺度模拟

【From Accelerated to Operating Conditions: How Trapped Charge Impacts on TDDB in SiO2 and HfO2 Stacks】 文章总结&#xff1a; 本研究深入探讨了在SiO2和HfO2介质堆叠中&#xff0c;陷阱电荷对时间依赖介电击穿&#xff08;TDDB&#xff09;现象的影响。通过引入载流子…

位运算-191. 位1的个数- 136. 只出现一次的数字

位1的个数 已解答 简单 相关标签 相关企业 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中 设置位 的个数&#xff08;也被称为汉明重量&#xff09;。 示例 1&#xff1a; 输入&#xff1a;n 11 输…

Git 术语及中英文对照

完毕&#xff01;&#xff01;感谢您的收看 ----------★★历史博文集合★★---------- 我的零基础Python教程&#xff0c;Python入门篇 进阶篇 视频教程 Py安装py项目 Python模块 Python爬虫 Json Xpath 正则表达式 Selenium Etree CssGui程序开发 Tkinter Pyqt5 列表元组字…

C++从入门到精通——类的定义及类的访问限定符和封装

类的定义及类的访问限定符和封装 前言一、类的定义类的两种定义方式成员变量命名规则的建议示例 二、类的访问限定符和封装访问限定符访问限定符说明C为什么要出现访问限定符例题 封装例题 前言 类的定义是面向对象编程中的基本概念&#xff0c;它描述了一类具有相同属性和方法…

MyBatis-Plus的学习笔记

MyBatis-Plus 一、MyBatis-Plus快速入门 1.1 简介 课程版本&#xff1a;3.5.3.1 https://baomidou.com/ MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&…

基于Vision Transformer的迁移学习在乳腺X光图像分类中的应用

乳房X线摄影(MG)在乳腺癌的早期发现中起着重要作用。MG可以在早期阶段发现乳腺癌&#xff0c;即使是感觉不到肿块的小肿瘤。基于卷积神经网络(CNN)的DL最近吸引了MG的大量关注&#xff0c;因为它有助于克服CAD系统的限制(假阳性、不必要的辐射暴露、无意义的活组织检查、高回调…

使用Python写简单的点云SUSAN关键点检测

一、代码 Python import numpy as np import open3d as o3d from scipy.spatial import cKDTree from joblib import Parallel, delayeddef calculate_response(idx, points, radius, t, kdtree):# 使用KD树找到半径内的所有点neighbor_indices = kdtree.query_ball_point(po…

大模型的Base版本模型、Chat版本模型和4Bit版本模型有什么区别

在最近开源的大部分大语言模型里&#xff0c;我们往往能看到在huggingface上&#xff0c;同一数据量级会有Base版本模型、Chat版本模型和4Bit模型等多个版本的模型&#xff0c;像我一样的新手小白可能会搞不清楚我应该用哪个来使用 下面是一些总结&#xff1a; Base版本模型&a…