首页 > 编程语言 >快速排序--排序算法

快速排序--排序算法

时间:2023-10-30 17:36:46浏览次数:36  
标签:sort 数列 -- int 算法 quick 排序 指针

快速排序

介绍

快速排序是分治思想的一种体现,通过递归不断将原数列划分为一大一小两部分, 从而实现对数列的排序。

算法时间复杂度为O(nlogn)。特点是数据越混乱,效率越高;数据越有序,效率越低。

值得注意的是快速排序是不稳定的,即相同大小的数据在排序前后的相对位置可能会发生变动。


代码实现

void quick_sort(int a[],int l,int r)//快速排序,从小到大
{
	if (l == r)
		return;//若数列中只有一个数,则必定有序,返回
	int x = a[(l + r) / 2], i = l - 1, j = r + 1;
    //取中项值为标准值x,采用do while,故i,j起始位置在l,r两端
	while(i<j)//当指针相遇且越过,则说明数列已遍历完
    {
		do i++; while (a[i] < x);
		do j--; while (a[j] > x);
        //i,j从两端分别向中间遍历,使i左边值小于x,j右边值大于x,遇到不满足则停止
		if (i < j) swap(a[i], a[j]);
        //当i,j分别移动到不满足项时,交换二者位置,则二者都满足,i,j继续向中间遍历
	}
    //指针相遇,遍历结束,此时j及其左侧值都小于x,j+1及其右侧值都大于x
	quick_sort(a, l, j);
	quick_sort(a, j + 1, r);
    //分别对左右两部分递归处理,知道整个数列都有序
}

思路解析

void quick_sort(int a[],int l,int r)//快速排序,从小到大
{
	if (l == r)
		return;
    //......
}

函数的传入值包括数组和左右端点下标。

显而易见,当l==r时,数列中只有1个数据,必定有序,所以我们直接返回。


int x = a[(l + r) / 2], i = l - 1, j = r + 1;

此时,我们需要将该数列分为一大一小两部分,保证右边的所有数都能大于左边。

所以,我们需要设定一个标准值,来判断某一个数应该放在左边还是右边。

这个标准值可以选择数组中的任何一个数据,可以取第一个值a[l],也可以取中项a[(l+r)/2],甚至可以随机。

但我们这里选择取中项值作为标准值,假如取首项为标准值,当所有数据大小都一样时,算法的时间复杂度会从O(nlogn)退化到O(n²)

同时,我们设立两个指针i和j,分别置于数列两端,用于遍历下标,至于为什么要多偏移一位,我们下面解释。


while(i<j)//当指针相遇且越过,则说明数列已遍历完
    {
		do i++; while (a[i] < x);
		do j--; while (a[j] > x);
        //i,j从两端分别向中间遍历,使i左边值小于x,j右边值大于x,遇到不满足则停止
		if (i < j) swap(a[i], a[j]);
        //当i,j分别移动到不满足项时,交换二者位置,则二者都满足,i,j继续向中间遍历
	}

指针位于数列的两端,同时往中间移动,我们采用do{} while{};语句,每次先移动指针再进行判断,所以我们的起始位置应该置于l和r的外侧一位。

指针向中间移动后,比较当前位置的数据值和标准值x的大小。

以i指针举例,若a[i]<x,则无事发生,指针i继续遍历,将该数据留在i的左边,直到遇到一个不满足的数,停下。

指针j同理。

当两个指针都已停止后,说明a[i]处有一个大于x的值,a[j]处有一个小于x的值,此时只需要将二者调换位置即可有效地调整数列顺序,当然,需要先对i,j是否越过进行判断。

若两个指针相遇且越过,就说明数列已经遍历完了,每个下标都已经经过。

此时,我们就已经将数组划分为左右一大一小两个部分。


quick_sort(a, l, j);
quick_sort(a, j + 1, r);

最后,我们将划分出的两个数组递归处理,再次划分为一大一小,直到划分到只有1个数据,然后开始回溯。

最终,就会返回一个有序数列。

值得注意的是,递归的起始位置也可以用i表示,但需要改为

quick_sort(a, l, i - 1);
quick_sort(a, i, r);

并且x的取值也需要从x = a[(l + r) / 2]改为x = a[(l + r) / 2 + 1],即额外加1。

否则会出现边界问题,导致无限递归。


以上便是对快速排序的介绍,本文由凉茶coltea撰写,思路来自AcWing大佬yxc的课

标签:sort,数列,--,int,算法,quick,排序,指针
From: https://www.cnblogs.com/coltea/p/17798364.html

相关文章

  • 【MySQL】基础篇-约束
    1.基础知识1.1为什么需要约束?为了保证数据的完整性!1.2什么叫约束?对表中字段的限制。1.3约束的分类:角度1:约束的字段的个数单列约束vs多列约束角度2:约束的作用范围列级约束:将此约束声明在对应字段的后面表级约束:在表中所有字段都声明完,在所有字段的后面声明的约束角度3:约束的......
  • UE全屏问题
    命令行内:-fullscreen-r.SetRes=800x600w游戏内命令行fullscreenr.setres800x600f蓝图命令r.setres800x600蓝图节点SetFullScreenMode不知为啥不好使UE设置全屏的插件1.下载商城的免费插件2.在开始时调用,我这里是在gamemode中插件中GetPrimaryMonitorResolut......
  • 【CV】图像分割详解!
    图像分割是计算机视觉研究中的一个经典难题,已经成为图像理解领域关注的一个热点,图像分割是图像分析的第一步,是计算机视觉的基础,是图像理解的重要组成部分,同时也是图像处理中最困难的问题之一。所谓图像分割是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分成若干个互不相交......
  • Java 新手如何使用Spring MVC 中的查询字符串和查询参数?
    文章目录什么是查询字符串和查询参数?步骤1:步骤2:步骤3:步骤4:结论......
  • 实验3
    task1.c实现功能:延迟打印,以实现游戏运行的效果1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN8067voidprint_text(intline,intcol,chartext[]);//函数声明8voidprint_spaces(intn);......
  • 大数据实验
       ......
  • 【Java 进阶篇】深入了解 Bootstrap 组件
    Bootstrap是一个流行的前端框架,提供了丰富的组件,用于创建各种网页元素和交互效果。这些组件可以帮助开发者轻松构建漂亮、响应式的网页,而无需深入的前端开发知识。在本文中,我们将深入探讨Bootstrap中一些常用的组件,适合初学者,帮助他们更好地理解和应用这些元素。什么是Bootstra......
  • [WUSTCTF2020]alison_likes_jojo
    boki图片中有隐藏文件压缩包需要密码暴力破解出密码888866解压得到信息经过三次base64解码后得到信息得到密码,这是另一张图片outguess隐写的密码,之后到虚拟机中进行破解得到flagflag{pretty_girl_alison_likes_jojo}......
  • 【Java 进阶篇】深入浅出:Bootstrap 轮播图
    在现代网页设计中,轮播图是一个常见的元素。它们可以用于展示图片、广告、新闻、产品或任何您希望吸引用户注意力的内容。要实现一个轮播图,您通常需要一些复杂的HTML、CSS和JavaScript代码,这对于初学者来说可能会感到困难。但幸运的是,有一些强大的工具可以帮助我们轻松创建漂亮的轮......
  • 1
    “你割了自己的腕?”加洛林走进房间,闻见了她无比熟悉的味道——血液,来自她眼前的这位金发萝莉,后者手腕上的纱布还在渗血。拿起桌上镀银的匕首,"你为什么要这么做,菲奥娜·德·弗朗索瓦小姐?"加洛林眼睛在银光闪烁的刀面上扫过,在确认银质没有磨损,菲奥娜不会得破伤风后松了一口气,......