算法与数据体系课笔记之-5. 快速排序

思维导图链接

算法与数据结构思维导图

参考左程云算法课程

4.归并排序和几个经典题目分析 总览

在这里插入图片描述

题1:颜色分类

颜色分类题目链接
题目描述:
  • 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,
    使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
    输入:nums = [2,0,2,1,1,0]
    输出:[0,0,1,1,2,2]

代码实现
package class05;
public class Code01_SortColors {
	 public void sortColors(int[] nums) {
		 // 1.先定义好指针,划分好三个区间
		 int pL = -1; // 左区间指针,[0,pL]<1
		 int i = 0;   // 中间区指针,[pL + 1,pR - 1]=1
		 int pR = nums.length; // 右区间指针[pR,n-1]>1
		 
		 // 2.i依次遍历,将元素放到指定区间内
		 while(i < pR) {
			 if(nums[i] < 1) { // 化到左区间
				 swap(nums, i ++, ++pL); // 左区间先扩容,再交换,i遍历下个元素
			 } else if(nums[i] > 1) { // 化到右区间
				 swap(nums, i, --pR); // 右区间先扩容,再交换
			 }  else {                // 注意此时i放的是从右边换的元素,没有判断过,要不动,再判断一次
				 i ++; // 相等,就放到中间区域
			 }
		 }
	 }

	private void swap(int[] nums, int i, int j) {
		int t = nums[i];
		nums[i] = nums[j];
		nums[j] = t;	
	}
}

题2:实现快排

单路快排
// 1. 单路排序法,划分两个区间
	public static <E extends Comparable<E>> void sort1Way(E[] arr) {
		if(arr == null || arr.length < 2) return;
		
		Random rad = new Random();
		sort1Way(arr, 0, arr.length - 1, rad);
	}

	private static <E extends Comparable<E>>void sort1Way(E[] arr, int left, int right, Random rad) {
		if(left >= right) return; // 注意不能是left==right,有可能直接L>R
		
		// 划分好左右区间,返回分界点指针位置
		int pM = partition(arr, left, right, rad);
		// 继续左右划分,确定大小的相等位置,区间最终化完了,也排好序了
		sort1Way(arr, left, pM -1, rad);
		sort1Way(arr, pM + 1, right, rad);
	}

	private static <E extends Comparable<E>>int partition(E[] arr, int left, int right, Random rad) {
		// 1. 先随机确定要划分的元素
		int radIndex = left + rad.nextInt(right - left + 1);
		swap(arr, left, radIndex);
		E v = arr[left];
		
		// 2.定义好指针,划分好左右区间
		//  [left + 1, pL]<v,[pL + 1,right]>=v,pL与left交换后,pL=v返回,left位置<V
		int pL = left;
		int i = left + 1;
		while(i <= right) {
			if(arr[i].compareTo(v) < 0) {
				swap(arr, i ++, ++pL);
			} else {
				i ++;
			}
		}
		
		// 3. 将pL与left交换,此时pL即分界点位置
		swap(arr, left, pL);
		return pL;
	}

	private static<E> void swap(E[] arr, int i, int j) {
		E t = arr[i];
		arr[i] = arr[j];
		arr[j] = t;		
	}

双路快排
// 2. 双路排序法,划分两个区间,从两边向中间遍历
	public static <E extends Comparable<E>> void sort2Way(E[] arr) {
		if(arr == null || arr.length < 2) return;
		
		Random rad = new Random();
		sort2Way(arr, 0, arr.length - 1, rad);
	}

	private static <E extends Comparable<E>>void sort2Way(E[] arr, int left, int right, Random rad) {
		if(left >= right) return;
		int p = partition2(arr, left, right, rad);
		sort2Way(arr, left, p - 1, rad);
		sort2Way(arr, p + 1, right, rad);
	}
	private static <E extends Comparable<E>>int partition2(E[] arr, int left, int right, Random rad) {
		// 1. 先随机确定要划分的元素
		swap(arr, left, left + rad.nextInt(right - left + 1));
		E v = arr[left];
		
		// 2.定义好指针,划分好左右区间,两指针即化分区间,也要遍历所有元素
		//  交换前,[left + 1, pL -1]<=v,[pR + 1,right]>=v,
		//  pL>pR结束,即pR跑到左区间-->pR=pL-1,pL=pR+1-->[left + 1, pR]<=v,[pL,right]>=v
		int pL = left + 1; // 从左往右遍历所有要比较的元素
		int pR = right;    // 从右往左遍历所有要比较的元素
		while(true) {
			while(pL <= pR && arr[pL].compareTo(v) < 0) pL ++;  // pl<v,一直推进,直到pL>=v,停下处理
			while(pL <= pR && arr[pR].compareTo(v) > 0) pR --;  // pR>v,一直推进,直到pR<=v,停下处理

			if(pL >= pR) break;	// 大循环里,=时,指的是都指向v,可以结束
			if(arr[pL].compareTo(arr[pR]) != 0) {  // 相等时都为v,无需交换
				swap(arr, pL, pR);
			}
			// 处理完后继续推进。直到pL>pR结束。=不结束,不知是哪个区间,错过一个后,才能确定pR跑到了左区间
			pL ++;
			pR --;  
		}
		swap(arr, left, pR);
		return pR;
	}
三路快排
// 3. 三路快排,划分三个区间,从左往右遍历
	public static <E extends Comparable<E>> void sort3Way(E[] arr) {
		Random rad = new Random();
		sort3Way(arr, 0, arr.length - 1, rad);
	}

	private static <E extends Comparable<E>> void sort3Way(E[] arr, int left, int right, Random rad) {
		if (left >= right) return;
		
		// 1.找划分元素
		swap(arr, left, left + rad.nextInt(right - left + 1));
		E v = arr[left];
		
		// 2. 化区间,左右初始均为空,是用i指针遍历
		// [left, pL]<v, [pL + 1, pR - 1]=v,[pR,right]>v
		int pL = left;
		int i = left + 1;
		int pR = right + 1;
		
		while(i < pR) {
			if(arr[i].compareTo(v) < 0) {
				swap(arr, i ++, ++pL);
			} else if(arr[i].compareTo(v) > 0) {
				swap(arr, i, --pR);
			} else {
				i ++;
			}
		}
		swap(arr, left, pL);
		// 遍历完交换后,pL指向v,i=pR指向>v
		// [left, pL - 1]<v, [pL, pR - 1]=v,[pR,right]>v
		sort3Way(arr, left, pL - 1, rad);
		sort3Way(arr, pR, right, rad);
	}
代码测试
public static void main(String[] args) {
		int[] nums = {100000, 1000000};
		for(int n : nums) {
			System.out.println("Random Array:");
			Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
			Integer[] arr2 = Arrays.copyOf(arr, arr.length);
			Integer[] arr3 = Arrays.copyOf(arr, arr.length);		
			SortingHelper.sortTime("QuickSort1Way", arr);
			SortingHelper.sortTime("QuickSort2Way", arr2);
			SortingHelper.sortTime("QuickSort3Way", arr3);
			System.out.println();
			
			System.out.println("Order Array:");
			arr = ArrayGenerator.generateOrderedArray(n);
			arr2 = Arrays.copyOf(arr, arr.length);
			arr3 = Arrays.copyOf(arr, arr.length);
			SortingHelper.sortTime("QuickSort1Way", arr);
			SortingHelper.sortTime("QuickSort2Way", arr2);
			SortingHelper.sortTime("QuickSort3Way", arr3);
			System.out.println();
	
			System.out.println("Same Value Array:");
			arr = ArrayGenerator.generateRandomArray(n, 1);
			arr2 = Arrays.copyOf(arr, arr.length);
			arr3 = Arrays.copyOf(arr, arr.length);
			//SortingHelper.sortTime("QuickSort1Way", arr);
			SortingHelper.sortTime("QuickSort2Way", arr2);
			SortingHelper.sortTime("QuickSort3Way", arr3);
			System.out.println();
		}
Random Array:
QuickSort1Way, n = 100000 : 0.029789 s
QuickSort2Way, n = 100000 : 0.025469 s
QuickSort3Way, n = 100000 : 0.039285 s

Order Array:
QuickSort1Way, n = 100000 : 0.008768 s
QuickSort2Way, n = 100000 : 0.005191 s
QuickSort3Way, n = 100000 : 0.013546 s

Same Value Array:
QuickSort2Way, n = 100000 : 0.006793 s
QuickSort3Way, n = 100000 : 0.000164 s

Random Array:
QuickSort1Way, n = 1000000 : 0.257176 s
QuickSort2Way, n = 1000000 : 0.228321 s
QuickSort3Way, n = 1000000 : 0.309179 s

Order Array:
QuickSort1Way, n = 1000000 : 0.107494 s
QuickSort2Way, n = 1000000 : 0.059241 s
QuickSort3Way, n = 1000000 : 0.155168 s

Same Value Array:
QuickSort2Way, n = 1000000 : 0.072794 s
QuickSort3Way, n = 1000000 : 0.002024 s

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值