经典快速排序与随机快速排序

一、经典快速排序

(一)、经典快速排序的实现理论

经典快速排序是用数组的最后一个数(这里记为 x )进行划分。也就是 <x、=x、>x。

  1. 有一个长度为 n 的数组 arr 。此时的数组的最后一个数为 arr[n - 1],我们根据 arr[n-1] 对数组进行排序。
  2. 设置一个变量 less 指向数组的第一个数的前一个位置(这里为 - 1),设置一个变量 more 指向数组的最后一个数 more(这里为 n - 1 )。设置一个变量 cur 指向数组当前数的位置。
  3. 对 arr[cur] 和 arr[n - 1]进行比较:

(1)如果 arr[cur] < arr[n - 1],交换 less 指向的数组的后一个数和arr[cur],然后 less 加 1(因为less划分的其实是 <x 的范围,此时 <x 范围内多个一个数,所以 less 需要加 1);

(2)如果 arr[cur] > arr[n - 1],交换 more 指向的前一个数和 arr[cur],然后 more 减 1 (因为more划分的其实是 >x 的范围,此时 >x 范围多了一个数,所以 more 需要 减 1);

(3)如果 arr[cur] = arr[n-1],less 和 more 不变

  1. 此时 cur 的数已经与 arr[n-1](数组的最后一个数)比较完毕,

(1)如果 arr[cur] < arr[n - 1] 或 arr[cur] = arr[n-1],cur 加 1,继续进行下一轮的比较;

(2)如果 arr[cur] > arr[n-1],cur 不变。(因为交换这两个数后,不知道交换过来的数的属于哪个范围(<x、=x、>x)),所以需要重新判定这个数属于哪个范围,cur 不变);

  1. 重复进行 3、4 步骤,直到 cur = more 结束(此时当前数组中所有的数已经比较完毕)。
(二)、经典快速排序的代码实现(Java)
/*
	经典快速排序:用数组的最后一个数划分
 */
 import java.util.Arrays;
public class JQuickSort {
	public static void jQuickSort(int[] arr) {
		if (arr == null || arr.length < 2)				// arr == null 说明数组不存在,不用比较;
			return;										// 数组长度小于 2,说明数组只有 1 个数或者根本没有数,自然不用比较;

		jQuickSort(arr, 0, arr.length - 1);		// 对整个数组进行经典快速排序
	}

	public static void jQuickSort(int[] arr, int L, int R) {
		// 如果L=R,说明此时数组只有一个数,不需要进行排序了。
		if (L < R) {
			// 获得 = x 的范围,数组 p 是一个长度为 2 的数组,里面存放着两个下标,分别为 =x 的第一个数下标和最后一个数的下标
			int[] p = partition(arr, L, R);
			jQuickSort(arr, L, p[0] - 1);			// 对 < x 部分进行排序
			jQuickSort(arr, p[1] + 1, R);			// 对 > x 部分进行排序
		}

	}

	public static int[] partition(int[] arr, int L, int R) {
		int less = L - 1;					// L 指向数组第一个数,最开始 < x 区域没有数,所以 less 指 L 的前一个位置
		int more = R;						// R 指向数组最后一个数,最开始 > x 区域没有数,所以 more 指向 R

		while (L < more) {
			if (arr[L] < arr[R]) {
				swap(arr, L++, ++less);
			} else if (arr[L] == arr[R])
				L++;
			else
				swap(arr, L, --more);
		}

		// 交换 >x 的第一个数和数组的最后一个数,此时当前数组就是 <x、=x、>x
		swap(arr, more, R);

		return new int[] {less + 1 , more};
	}

	public static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	public static void main(String[] args) {
		int[] a = {1, 2 ,4, 5, 4, 10, 2};
		System.out.println(Arrays.toString(a));
		jQuickSort(a);
		System.out.println(Arrays.toString(a));
	}
}
(三)、经典快速排序的时间复杂度

经典快速排序的时间复杂度为 O(N^2)。

每次都用数组的最后一个数进行划分,一次搞定排好一个数,所以时间复杂度为O(N),

一共有 N 个数,所以时间复杂度为 O(N^2)。

二、随机快速排序

(一)、随机快速排序的实现理论

随机快速排序与经典快速排序的区别就是:在数组中随机选一个数与最后一个数进行交换,对整个数组进行划分。

(二)、随机快速排序的代码实现(Java)
import java.util.Arrays;

public class QuickSort {
	public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2)
			return;

		quickSort(arr, 0, arr.length - 1);
	}

	public static void quickSort(int[] arr, int L, int R) {
		if (L < R) {
			// 数组中随机一个数与最后一个数进行交换,作为数组划分的依据
			swap(arr,L + (int)(Math.random() * (R - L + 1)), R);
			int[] p = partition(arr, L, R);
			quickSort(arr, L, p[0] - 1);
			quickSort(arr, p[1] + 1, R);
		}
	}

	public static int[] partition(int[] arr, int L, int R) {
		int less = L - 1;
		int more = R;

		while (L < more) {
			if (arr[L] < arr[R]) {
				swap(arr, L++, ++less);
			} else if (arr[L] > arr[R]) {
				swap(arr, L, --more);
			} else {
				L++;
			}
		}

		swap(arr, R, more);

		return new int[] {less + 1, more};
	}

	public static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	public static void main(String[] args) {
		int[] a = {1, 2 ,4, 5, 4, 10, 2};
		System.out.println(Arrays.toString(a));
		quickSort(a);
		System.out.println(Arrays.toString(a));
	}
}
(三)、随机快速排序的时间复杂度

随机快速排序由于每次划分的依据是从数组随机选出的,所以数据状况对它的影响减弱,所以时间复杂度为 O(N*logN)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值