首页 > 其他分享 >快速排序

快速排序

时间:2023-07-19 21:57:36浏览次数:32  
标签:geq int quicksort leq 数组 排序 快速

快速排序

主要思想

快速排序所采用的思想是分治的思想。所谓分治,就是指以一个数为基准,将序列中的其他数往它两边“扔”。以从小到大排序为例,比它小的都“扔”到它的左边,比它大的都“扔”到它的右边,然后左右两边再分别重复这个操作,不停地分,直至分到每一个分区的基准数的左边或者右边都只剩一个数为止。这时排序也就完成了。

流程

  • 确定基准值\(x\),选择的方式一般有三种:左端点 右端点 中间点

    基准值的选择不同也会导致代码的运行时长不同,一般来说都取中间点

  • 调整区间,使左半边全部 \(\leq x\),右半边全部 \(\geq x\)

  • 按照以上两个步骤递归处理两端,直到区间里只剩下一个元素

具体实现

朴素做法

  • 开两个数组,\(a\)和\(b\),再开一个数组\(q\)用来存储答案
  • 定义一个函数用来处理数组,需要两个参数\(l\)和\(r\),表示左端点和右端点,从\(l\)遍历到\(r\)
  • 分情况处理:
    • \(q_i\leq x\) 将\(q_i\)放到\(a\)数组中
    • \(q_i\geq x\) 将\(q_i\)放到\(b\)数组中
  • 重复2 3 两步操作,直到区间里只剩下一个元素,即 \(l\geq r\)
  • 最后合并两个数组

优化思路

按照以上方法,我们将会浪费很多空间,那么如何在不另外开辟空间的情况下完成任务呢?

我们可以借鉴双指针的思路,为了好听我们将两个指针命名为 “哨兵”

我们先来回顾一下,双指针的主要用途是什么? 主要是用来维护一段区间

于是我们可以用 \(i\) 来维护左区间,使得 \(i\) 左边的数都 \(\leq x\),用 \(j\) 来维护右区间,使得 \(j\) 右边的数都 \(\geq x\)

优化做法

  • 定义两个“哨兵” \(i\) 和 \(j\),开始时指向区间的左右两端
  • 当 \(i\) 指向的数 \(<x\) 时,就往右移动,直到指向的数 \(\geq x\)
  • 当 \(j\) 指向的数 \(> x\) 时,就往左移动,直到指向的数 \(\leq x\)
  • 当 \(i\) 和 \(j\) 的移动停止时,交换 \(i\) 和 \(j\) 指向的数,\(i\) 往右移动一个,\(j\) 往左移动一个

一直重复以上的步骤,直到两个哨兵相遇为止,即当 \(i\geq j\) 时

样例模拟



注意点

快排与二分的注意点是一样的,都是边界问题

在递归分别处理时容易出现这个问题

  • 当分界点取 \(i-1\) 和 \(i\) 时,分界点不能取 \(l\),要取 \((l+r+1)/2\),注意上取整
  • 当分界点取 \(j\) 和 \(j+1\) 时,分界点不能取 \(r\),要取 \((l+r)/2\),区别于上一种

算法分析

时间复杂度 \(O(nlogn)\)

快速排序是不稳定的

何为稳定性?

当排序时如果遇到两个数值相同,一般来说把靠前的那个往后移

换句话来说就是排完序后,两个相同的数的相对位置不发生变化

而快速排序无法保证这一点,所以不稳定

如何解决?
我们可以用stl里的map保存下标,使得每一个数具有唯一性

代码模板

#include <iostream>
using namespace std;
int q[100000] = { 0 };
int n;
void quicksort(int q[], int l, int r)
{
	if (l >= r)return;
	int i = l - 1, j = r + 1, x = q[l + r >> 1];
	while (i < j)
	{
		do i++; while (q[i] < x);
		do j--; while (q[j] > x);
		if (i < j)swap(q[i], q[j]);
	}
	quicksort(q, l, j), quicksort(q, j + 1, r);
}

int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &q[i]);
	}
	quicksort(q, 0, n-1);
	for (int i = 0; i < n; i++)
	{
		printf("%d ", q[i]);
	}
	return 0;
}

标签:geq,int,quicksort,leq,数组,排序,快速
From: https://www.cnblogs.com/xiaozhu0602/p/17566871.html

相关文章

  • c语言 排序算法
    //sort_algorituhm.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>#include<algorithm>usingnamespacestd;#defineelemtypeint//冒泡排序法,组个遍历,大数往后,每次都是"完全遍历",从0开始voidsort_bubbling(elemtype*p,ints......
  • 拓扑排序
    定义:对一个有向图构造拓扑序列,排序类似流程图那样按先干什么后干什么这样排序拿大学教学安排举个例子(图来自oiwiki)先不要考虑操作系统到数据结构那条蓝线。那么我们要先学程序设计才能学习后面的算法语言,离散数学等等。那么在拓扑序列中,程序设计就要在算法语言,离散数学......
  • 对UION结果进行排序 MYSQL
    对UION结果进行排序MYSQL在MySQL中,可以使用UNION操作符将多个SELECT语句的结果合并成一个结果集。但是,UNION操作符的结果默认是按照表达式顺序进行排序的。如果我们想要对UNION的结果进行排序,可以使用子查询或者别名的方式来实现。子查询排序子查询是将一个SELECT语句嵌套在另......
  • 建站新手福利:免费网页模板大合集,快速打造专业网站!
    今天给大家带来的网站模板素材,网站类型丰富,包含户外旅行、餐饮、个人网站等等,可以学习和参考其中的布局排版和配色。 ⬇⬇⬇点击获取更多设计资源https://js.design/community?category=design&source=bky&plan=bbqbky772   1、设计公司&工作室相信大家都希望拥有属......
  • 2023.7.19 周三:冒泡排序
    1importjava.sql.SQLOutput;2importjava.util.Arrays;3importjava.util.Scanner;4//冒泡排序5publicclasstest{6publicstaticvoidmain(String[]args){7int[]a={5,4,6,8,9,1,7,2,3};8intarray[]=sort(a);9S......
  • 数据结构与算法 头歌 图的拓扑排序算法
    数据结构与算法之图的拓扑排序算法导言拓扑排序是对有向无环图(DirectedAcyclicGraph,DAG)进行排序的一种算法。在实际开发中,拓扑排序算法常用于解决任务调度、编译顺序等问题。本文将介绍拓扑排序算法的实现过程,并帮助初学者理解该算法的原理及代码实现。拓扑排序流程以下......
  • 如何把2274587.84如何快速的转换为大写:贰佰贰拾柒万肆仟伍佰捌拾柒元捌角肆分?(番外篇)
    大家好,我是皮皮。一、前言前几天在Python黄金群【莫生气】问了一个Python数据处理的问题,需求如下:大佬们,请教一个问题,2274587.84如何快速的转换为大写:贰佰贰拾柒万肆仟伍佰捌拾柒元捌角肆分?有没有工具或者网页啥的?不一定要Python实现。前面两篇文章已经给大家很多方法了,今天在P......
  • 一维数组之冒泡排序
    从b站上黑马程序员的C++课里学到的冒泡排序 1#include<iostream>2usingnamespacestd;3intmain()4{5intarr[6]={2,4,1,6,7,3};6for(inti=0;i<6;i++)//数组遍历7{8cout<<arr[i]<<"";9}1......
  • list数据实现先分组后排序
    使用jdk8的stream流(基本实现分组靠Collectors.goupingby),list自带的sort()方法排序,话不多说,代码如下: List<User>list=Arrays.asList(newUser("1","小明","2","一年级"), newUser("2","小名","1",&q......
  • ReadyDrive 是什么: ReadyDrive 利用了固态硬盘的快速读取和写入速度,将其作为硬盘缓存
    ReadyDrive是WindowsVista和更高版本中引入的一项技术,它利用闪存驱动器(如固态硬盘)作为硬盘缓存,以提高系统的启动速度和应用程序的加载速度。下面是对ReadyDrive的详细解释:ReadyDrive是什么:ReadyDrive利用了固态硬盘的快速读取和写入速度,将其作为硬盘缓存使用。它可以通......