(含动图演示)搞懂快速排序,包会

news/2024/5/19 22:17:16 标签: 算法, c语言, 排序算法, 快速排序, c++

目录

快速排序


快速排序

快排属于分治算法

基本思想:当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。

总结下来即三步:

  1. 分成子问题

  2. 递归处理子问题

  3. 子问题合并

快排的具体实现

  1. 确定分界点x,这里取 x = q[l + r >> 1]。

  2. 划分区间:我们将一堆数分为两堆,左边分为<=x的,右边分为>=x。

  3. 递归处理左右两堆。

难点在于第2点,我们如何优雅而又简单的划分区间。这里我们可以使用双指针算法(不需要开辟额外空间)。

下面画图举例:

具体代码实现:

void quick_sort(int q[],int l,int r){
     if(l>=r) return;//递归的结束条件
     
     int i = l - 1,j = r + 1,x = q[l + r >> 1];//这里 i = l - 1,j = r + 1,
     //为什么要这样,是因为下面的 ++i,--j。
     // >> 1 <=> /2
     // << 1 <=> *2 
     //(运算效率:移位 > 赋值 > 大小比较 > 加法 > 减法 > 乘法 > 取模 > 除法。)
     
     while(i<j){
         while(q[++ i]<x);//当前值<x,指针就继续往右走,直到当前值>=x。
         while(q[-- j]>x);//当前值>x,指针就继续往左走,直到当前值<=x。
         
         //交换两个值 => 达到左边都是小于x的值,右边都是大于x的值。
         //异或 ^ 骚操作(不使用额外变量)
         if(i<j){
             q[i] = q[i] ^ q[j];
             q[j] = q[i] ^ q[j];
             q[i] = q[i] ^ q[j];
         }
     }
     
     //递归处理(l,j) (j + 1, r)。
     //边界问题建议背过。
     quick_sort(q,l,j);
     quick_sort(q,j+1,r);
 }
  • 快速排序的额外空间复杂度:最好O(logN),最坏O(N),平均的额外空间复杂度,求一个概率累加:O(logN)

    • 这里额外的空间主要指:递归的时候,我们要记录下每一次的分界点,这样递归完左边部分,才知道右边部分递归哪里。

    • 最好:每次分界点都取到中间值

    • 最坏:每次分界点都取到最大值或者最小值

  • 快速排序的时间复杂度:最好O(N * logN),最坏O(N^2),平均时间复杂度,求一个概率累加:O(N * logN)

    • 最好:每次分界点都取到中间值

    • 最坏:每次分界点都取到最大值或者最小值


http://www.niftyadmin.cn/n/1326967.html

相关文章

(含动画演示)搞懂归并排序 一学就会

归并排序 归并排序与快排一样也属于分治算法&#xff0c;但是分治的方法不一样。 总结下来即三步&#xff1a; 分成子问题递归处理子问题子问题合并 代码的具体实现&#xff1a; void merge_sort(int q[],int l,int r){//1.分成子问题if(l>r) return;//递归结束条件。int m…

快速排序 习题练习

题目 具体代码 #include<stdio.h> #define N 100010int q[N];int quick_sort(int l,int r,int k){if(l>r) return q[l];//递归结束的条件int i l - 1,j r 1,x q[lr >>1];while(i<j){while(q[ i]<x);while(q[ -- j]>x);if(i<j){int t q[i];q[…

归并排序 题目练习

题目 具体代码 import java.util.*;public class Main{static int[] q new int[100010],tmp new int[100010];static long mergeSort(int l,int r){if(l>r) return 0;//递归结束条件。//归并排序在归并的时候&#xff0c;同时就计算了逆序对的数量。int mid l r >&g…

骚操作,如何不使用临时变量,实现交换swap。

一般&#xff0c;为了实现swap函数&#xff0c;我们会创建一个临时变量tmp int tmp a; a b; b tmp; 那么我们如何不使用临时变量来实现交换呢&#xff1f; 下面给出两种方法&#xff1a; a a b;// a a b, b a - b;// b (a b) - b a; a a - b;// a (a b) - a b; …

轻松解决,二进制中1的个数

题目 代码实现 #include<stdio.h>int main(){int n;scanf("%d",&n);while(n--){int count 0;int x;scanf("%d",&x);while(x){x ^ x & -x;//x - x & -x;count ;}printf("%d ",count);}return 0; }分析 lowbit(x)是x的二…

秒啊,最长连续不重复子序列

题目 具体代码实现&#xff1a; import java.util.*;public class Main{static int[] a new int[100010],s new int[100010];public static void main(String[] args){Scanner sc new Scanner(System.in);int n sc.nextInt();for(int i 0;i<n;i ) a[i] sc.nextInt();/…

入门学习的难点:递归

函数递归&#xff1a;程序调用自身的编程技巧称为递归&#xff08; recursion&#xff09;。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法&#xff0c;它通常把一个大型复杂的问题层层转化为一个与原问题相似的规…

含动图,解决单调栈问题

单调栈&#xff1a; 题目 具体代码 #include<stdio.h>int stk[100010],tt;int main(){int n;scanf("%d",&n);for(int i 0;i<n;i){int x;scanf("%d",&x);while(tt && stk[tt] > x) tt --;//栈内是递增的 如果栈顶元素大于当前…