• 【算法】快速排序


    在这里插入图片描述

    一、单边循环快排(lomuto洛穆托分区方案)

    原理说明:

    1. 选择最右元素作为基准点元素
    2. j指针负责找到比基准点小的元素,一旦找到则与i进行交换
    3. i指针维护小于基准点元素的边界,也是每次交换的目标索引
    4. 最后基准点与i交换,i即为分区位置

    代码实现:

    public class QuickSort1 {
    	public static void main(String[] args) {
    		int[] a = {5, 3, 7, 2, 9, 8, 1, 4};
    		partition(a, 0, a.length - 1);
    	}
    	
    	public static void quick(int[] a, int l, int h) {
    		if (l >= h) {
    			return;
    		}
    		int p = partition(a, l, h); // p 索引值
    		quick(a, l, p - 1); // 左边分区的范围确定
    		quick(a, p + 1, h); // 右边分区的范围确定
    	}
    	
    	private static int partition(int[] a, int l, int h) {
    		int pv = a[h]; // 基准点元素
    		int i = l;
    		for (int j = l; j < h; j++) {
    			if (a[j] < pv) {
    				swap(a, i, j); // 自定义的交换方法,将i、j互换
    				i++;
    			}
    		}
    		swap(a, h, i);
    		System.out.println(Arrays.toString + "i = " + i);
    		// 返回值代表了基准点元素所在的正确索引,用它确定下一轮分区的边界
    		return i;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    运行结果:
    在这里插入图片描述

    二、双边循环快排(并不完全等价于hoare霍尔分区方案)

    原理说明:

    1. 选择最左元素作为基准点元素
    2. j指针负责从右向左找比基准点小的元素,i指针负责从左向右找比基准点大的元素,一旦找到二者交换,直至i,j相交
    3. 最后基准点与i(此时i与j相等)交换,i即为分区位置

    代码实现:

    public class QuickSort1 {
    	public static void main(String[] args) {
    		int[] a = {5, 3, 7, 2, 9, 8, 1, 4};
    		partition(a, 0, a.length - 1);
    	}
    	
    	public static void quick(int[] a, int l, int h) {
    		if (l >= h) {
    			return;
    		}
    		int p = partition(a, l, h); // p 索引值
    		quick(a, l, p - 1); // 左边分区的范围确定
    		quick(a, p + 1, h); // 右边分区的范围确定
    	}
    	
    	private static int partition(int[] a, int l, int h) {
    		int pv = a[l]; // 基准点元素
    		int i = l;
    		int j = h;
    		while (i < j) {
    			// j 从右找小的
    			while (i < j && a[j] > pv) {
    				j--;
    			}
    			// i 从左找大的
    			while (i < j && a[i] <= pv) {
    				i++;
    			}
    			swap(a, i, j);
    		}
    		swap(a, l, j);
    		System.out.println(Arrays.toString + "j = " + j);
    		// 返回值代表了基准点元素所在的正确索引,用它确定下一轮分区的边界
    		return j;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    注意要点:

    1. 基准点在左边,并且要先 j 后 i
    2. while (i < j && a[j] > pv) j–
    3. while (i < j && a[i] <= pv) i++
      运行结果:
      在这里插入图片描述
  • 相关阅读:
    OKR助理源代码说明
    ArcGIS中ArcMap栅格遥感影像的监督分类
    vi使用方法详细介绍
    电脑文件数据恢复有哪些方法?电脑怎么恢复已删除的文件数据?
    Mathorcup数学建模竞赛第三届-【妈妈杯】A题:火车票购票网站优化(附带赛题解析&获奖论文和MATLAB、C++代码)(三)
    吃鸡攻略大揭秘!提升战斗力,分享干货!
    Pytorch实现MNIST字符识别
    C++ Reference: Standard C++ Library reference: C Library: cwctype: iswupper
    LLM 时代,如何优雅地训练大模型?
    外观 ( Facade ) 模式
  • 原文地址:https://blog.csdn.net/qq_30999361/article/details/126129074