快速排序(Java描述)

快速排序的原理:对于一个给定的数组,从中选取一个元素(理论上说可以随意选取一个元素,暂且把这个元素称为中间元素),以这个元素为界,将所有的元素分成两个子集,一个子集中的所有元素都小于中间元素,另一个子集中的所有元素都大于中间元素,此时中间元素就在他最终所在的位置上;对这两个子集分别按照同样的规则再划分成两个子集,直到每一个子集中的元素只有一个或没有为止,这样每次选取的中间元素在每次划分结束之后都处在他最终所在的位置上。所有的划分结束后,所有的元素就都在他最终所在的位置上了。由此可见这个过程是一个递归的过程。

快速排序的关键在于划分,下面介绍三种种划分方法,将数组a[p...r]进行划分。(假定都选取最后一个元素作为中间元素)

从前向后遍历:

partition(a, p, r)

    x = p-1;

    for i = p to r-1

        if a[i] <= a[r]

            exchange a[++x] with a[i];

    exchange a[i+1] with a[r];

    return i + 1;


从后向前遍历

partition(a, p, r)

    x = r;

    for i = r-1 to p

        if a[i] > a[r]

            exchange a[i] with a[--x];

    exchange a[i+1] with a[r];

    return i + 1;


还有一种更容易理解的方式,从数组的两边同时向中间寻找

partition(a, p, r)

    i = p - 1;

    j = r + 1;

    while true

        repeat j--;

        until a[j] < a[r];

        repeat i++;

        until a[i] > a[r];

        if i < j

            exchange a[i] with a[j];

        else return j;


具体实现代码如下(partition和quicksort给出了两种实现方式):

<span style="font-size:14px;">package com.hubu.quicksort;

public class QuickSort {

	public int partition(int a[], int p, int r) {
		int x = (p - 1);
		for (int i = p; i < r; i++) {
			if (a[i] <= a[r]) {
				x += 1;
				int temp = a[x];
				a[x] = a[i];
				a[i] = temp;
			}
		}

		x += 1;
		int temp = a[x];
		a[x] = a[r];
		a[r] = temp;

		return x;
	}

	public int partition_(int a[], int p, int r) {
		int x = a[p];
		int i = p - 1;
		int j = r + 1;

		while (true) {
			do
				j--;
			while (a[j] < x);

			do
				i++;
			while (a[i] > x);

			if (i < j) {
				int temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			} else
				return j;
		}
	}

	public void quick_sort(int a[], int p, int r) {
		if (p < r) {
			int q = partition_(a, p, r);
			quick_sort(a, p, q - 1);
			quick_sort(a, q + 1, r);
		}
	}
	
    public void quick_sort_(int a[], int p, int r) {
    	while (p < r) {
    		int q = partition(a, p, r);
    		quick_sort_(a, p, q - 1);
    		p = q + 1;
    	}
    }

	public static void main(String[] args) {
		int a[] = { 5, 6, 3, 6, 14, 1, 2, 4, 2, 4, 7 };
		QuickSort qs = new QuickSort();
		qs.quick_sort_(a, 0, a.length - 1);

		for (int i = 0; i < a.length; i++)
			System.out.print(a[i] + " ");
	}
}</span>


复杂度和稳定性分析。由于在排序过程中涉及到了元素的交换,所以快速排序不稳定。从上面的排序过程可以看出快速排序的时间复杂度强烈依赖于中间元素的选取,当每次选取的中间元素都是最大或者最小的元素时(最差情况),数组被划分成长度为(n-1)和0的两个子数组,此时T(n) = T(n-1) + T(0) + Θ(n),Θ(n)是一次划分操作的时间复杂度,得到T(n) = Θ(n^2);当每次选取的中间元素刚好是值居中的元素时(最优情况),数组被划分成两个长度相等(或相差1)的两个子数组,此时T(n) = 2T(n/2) + Θ(n),得到T(n) = Θ(nlgn)。实际上若认为选取每个元素作为中间元素的概率是相等的(平均情况),则快速排序的复杂度跟最优情况一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值