快速排序(quick_sort)
快速排序大体分为三个步骤:
1.确定分界点 q[(l+r) >> 1] 或者 q[(l+r+1) >> 1] ,两者得看情况而定,不能用 q[l] 或者 q[r] 了 因为会超时。
2.调整区间范围,让小于等于x的放在左边,大于等于x的数放在右边。
3.递归处理左右两端。
模板代码:
void quick_sort(int q[], int l, int r)
{
    if(l >= r) return;
    int x = q[(l+r) >> 1], i = l-1, j = r+1; //i为左边指针 j为右边指针 确定分界点
    while(i < j) //调整区间
    {
        do i++; while(q[i] < x);
        do j--; while(q[j] > x);
        if(i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j);
    quick_sort(q, j+1, r);
}
另外一种
void quick_sort(int q[], int l, int r)
{
    if(l >= r) return;
    int x = q[l+r+1 >> 1], i = l-1, j = r+1;  //下面i左指针这里就不能用(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]);
    }
    quick_sort(q, l, i-1);
    quick_sort(q, i, r);
}
总的来说就是如果x取得是中间两个数得下界 (l+r) >> 1 ,那么下边递归得时候就得是用右指针即 j与j+1 ,如果x取得是中间两个数得上界 (l+r+1) >> 1 ,那么下边递归得时候就得用左指针即 i-1与i ,不然会MLE,即超内存,就是进入了死循环。
错误代码
void quick_sort(int q[], int l, int r)
{
    if(l >= r) return;
    int x = q[l+r >> 1], i = l-1, j = r+1;  //下面i左指针这里就不能用(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]);
    }
    quick_sort(q, l, i-1);
    quick_sort(q, i, r);
}
用一个样例来说:假如 n=2 ,样例为 1 2 ,最初 i = -1 ,  j = 2 ,  x = 1  ,然后进行完 while 循环后, i与j都等于0 ,知识左边区间递归的是0--1,然后根据if(l >= r) return;直接返回结束,然后递归右边区间0--1,这是问题就来了,x仍然是1,继续重复上一个过程,就进入了死循环,所以导致MLE,所以把程序改写成q[(l+r+1) >> 1]即可通过。
代码
#include<iostream>
using namespace std;
const int N = 100010;
int n;
int q[N];
void quick_sort(int q[], int l, int r)
{
    if(l >= r) return;
    int x = q[(l+r) >> 1], i = l-1, j = 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]);
    }
    quick_sort(q, l, j);
    quick_sort(q, j+1, r);
}
int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%d", &q[i]);
    quick_sort(q, 0, n-1);
    for(int i = 0; i < n; i++) printf("%d ", q[i]);
    system("pause");
    return 0;
}
快速排序(quick_sort)的更多相关文章
- 快速排序quick_sort(python的两种实现方式)
		排序算法有很多,目前最好的是quick_sort:unstable,spatial complexity is nlogN. 快速排序原理 python实现 严蔚敏的 datastruct书中有伪代码 ... 
- 快速排序Quick_Sort
		快排——排序中的明星算法,也几乎是必须掌握的算法,这次我们来领略以下快排为何魅力如此之大. 快排主要有两种思路,分别是挖坑法和交换法,这里我们以挖坑法为例来进行介绍,交换法可以参考这篇博文.值得一提的 ... 
- python数据结构与算法第十二天【快速排序】
		1. 原理如图所示: 2.代码实现 def quick_sort(alist, start, end): """快速排序""" # 递归的退 ... 
- Pythonic版冒泡排序和快速排序(附:直接插入排序)
		[本文出自天外归云的博客园] 冒泡排序:就是每次排序选最大元素到数组a的最后,排 len(a)-1 次.也就是两个for循环: 1. 外层是待排数组长度的循环,从待排数组长度(初始待排数组长度等于数组 ... 
- 1、算法介绍,lowB三人组,快速排序
		1.什么是算法 2.递归 # 一直递归,递归完成再打印 def func4(x): if x > 0: func4(x - 1) print(x) func4(5) 3.时间 复杂度 (1)引入 ... 
- python算法之快速排序
		快速排序 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所 ... 
- 快速排序详解(C语言/python)
		快速排序详解 介绍: 快速排序于C. A. R. Hoare在1960年提出,是针对冒泡排序的一种改进.它每一次将需要排序的部分划分为俩个独立的部分,其中一个部分的数比的数都小.然后再按照这个方法对这 ... 
- python算法与数据结构-快速排序算法(36)
		一.快速排序的介绍 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外 ... 
- 冒泡(bubblesort)、选择排序、插入排序、快速排序
		冒泡排序(bubblesort) 特点:通过换位置的方式,一直向上冒泡 package main import "fmt" func bubbleSortAsc(arrayA [] ... 
- Open Data Structure Templates
		数据结构模板 Chen 2016/12/22 前言 本篇博客的模板,全部是我纯手打的,如果有发现错误,请在下方留言指正:).欢迎大家参考. 有一些地方还不是很完善,等过一阵子用C++实现和部分重构下. ... 
随机推荐
- 【工具】-Reverse-DIE(Detect-It-Easy)
			关于 Detect It Easy,或缩写为"DIE"是一个用于确定文件类型的程序.Detect It Easy 是一个多功能的 PE 检测工具,基于 QT 平台编写,主要用于 P ... 
- 记录一次AutoMapper注册报错
			通常,.Net5我们注册服务是这样的. //添加AutoMapper var automapperConfog = new MapperConfiguration(config => { con ... 
- Linux查看磁盘空间,文件系统、挂载
			Linux磁盘空间,文件系统.挂载 概述 在使用以下命令查看磁盘使用情况时 df -h du -sh 目标路径 作为初级开发者,Linux入门级选手,可能不禁要问Linux系统的文件系统跟window ... 
- 聊一聊 Go 的内存对齐
			前言 在一次工作中,需要使用 Go 调用 DLL 文件,其中就涉及到内存对齐的相关知识,如果自定义的结构体内存布局和所调用的 DLL 结构体内存布局不一致,就会无法正确调用.所以,一旦涉及到较为底层的 ... 
- 《Linux基础》09. Shell 编程
			@ 目录 1:Shell 简介 2:Shell 脚本 2.1:规则与语法 2.2:执行方式 2.3:第一个 Shell 脚本 3:变量 3.1:系统变量 3.2:用户自定义变量 3.2.1:规则 3. ... 
- 学习JavaScript的路径
			学习JavaScript的路径可以按照以下步骤进行: 了解基本概念:首先学习JavaScript的基本概念,包括变量.数据类型.运算符.数组.对象.循环和条件语句等.可以通过阅读相关的教材.在线课程或 ... 
- defined('BASEPATH') OR exit('No direct script access allowed'); 的作用
			起到保护.php文件的作用, 如果直接访问此php文件会得到"不允许直接访问脚本"的错误提示 如果你是用ci框架或者其他的什么, 就建议加上, 如果你怕别人恶意攻击你的话 
- .NET C#基础(9):资源释放 - 需要介入的资源管理
			1. 什么是IDisposable? IDisposable接口是一个用于约定可进行释放资源操作的接口,一个类实现该接口则意味着可以使用接口约定的方法Dispose来释放资源.其定义如下: pub ... 
- Solution -「CF 1477A」Nezzar and Board
			Description Link. $ n $ distinct integers $ x_1,x_2,\ldots,x_n $ are written on the board. Nezzar ca ... 
- Ubuntu22.04 编译安装nginx
			1.下载nginx软件包 https://nginx.org/en/download.html 2.压缩包上传服务器并解压缩 tar xf nginx-1.22.1.tar.gz 3.进入解压目录,编 ... 
