快速排序


快速排序最好时间复杂度O(nlgn),平均时间复杂度O(nlgn),最坏的时间复杂度O(n²)(极少出现),辅助空间O(lgn),是不稳定的排序算法。

与归并排序一样,快速排序也使用分治思想,对数组A[ p...r ] 进行快速排序的三步分治过程:

分解:数组A[p...r]被划分为两个(可能为空)的子数组A[p...q-1]和A[q+1...r],使得A[ p ...q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1...r]中的每一个元素

解决:通过递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序。

合并:因为子数组是原址有序的,所以不需要合并操作,数组A[p...r]已经有序。


伪代码实现:

QuickSort (A , p , r )

if  p< r

q = Partition(A , p , r )

QuickSort(A , p , q-1 )

QuickSort(A , q+1 , r)

为排序一个数组A的全部元素,初始调用的是QuickSort(A , 1 , A.length )。

其中,算法的关键部分Partition过程,它实现了对子数组A[p...r]的原址重排。

Partition(A , p , r )

x = A[r]

i = p - 1

for j=p to r-1

if  A[j] ≤ x

i = i+1

exchange A[i] with A[j]

exchange A[i+1] with A[r]

return i+1


快速排序算法Java版:

import java.util.Arrays;

public class QuicklySort {

	private static int N = 10;

	public static void main(String[] args) {
		int[] arr = new int[N];
		for (int i = 0; i < N; i++) {
			arr[i] = ((Double) (Math.random() * 100)).intValue();
		}
		System.out.println("排序前的数组 : " + Arrays.toString(arr));

		quickSort(arr, 0, N - 1);

		System.out.println("排序后的数组 : " + Arrays.toString(arr));
	}

	/**
	 * @param arr 待排序数组
	 * @param left 排序起始下标
	 * @param right 排序终止下标
	 */
	public static void quickSort(int[] arr, int left, int right) {
		if (left < right) { // 递归控制
			int i = left, j = right, x = arr[i];
			while (i < j) {
				while (i < j && x <= arr[j])
					j--;
				if (i < j) {
					arr[i] = arr[j];
					i++;
				}
				while (i < j && arr[i] < x)
					i++;
				if (i < j) {
					arr[j] = arr[i];
					j--;
				}
			}
			arr[i] = x;
			quickSort(arr, 0, i - 1); // 递归排序左边
			quickSort(arr, i + 1, right); // 递归排序右边
		}

	}
}



快速排序的性能

快速排序的性能依赖于划分是否平衡,而平衡与否又依赖于用于划分的元素。如果划分是平衡的,那么快速排序算法的性能与归并排序是一样的。如果划分是不平衡的,那么快速排序的性能就接近于插入排序。

最坏情况:当划分产生的两个子数组分别包含了n-1和0个元素,那么快速排序的最坏情况发生了,实际上也就变成了插入排序,此时的时间复杂度是O(n²)。需要注意的是,最坏情况下,快速排序的运行时间并不比插入排序好,当输入的数组完全有序时,插入排序的时间复杂度是O(n),而快速排序的时间复杂度仍然是O(n²)。

最好情况:在可能的最平衡划分中,划分得到的两个子数组规模都不大于n/2,也就是如果规模为10,那么两个子数组规模一个是4一个是5(如果A的规模是11那么两个子数组的规模都是5),此时的时间复杂度是O(nlgn)。

平均情况:快速排序的平均运行时间接近于其最好的情况,而非最坏的情况,这也是平均复杂度和最好复杂度都是O(nlgn)的原因




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值