排序之快速排序2

一.快速排序最坏情况分析

    上文章分析到快速排序-----排序之快速排序 。最后提到了一个思考题,什么样的情况下快速排序是最坏情况?

    有两种情况:

  1.   数组已经排好序(升序或者逆序)

        这种情况,挑选了第一个元素为主元,那么主元就是数组中最大的或者是最小的,n划分成1和n-1

       时间复杂度T(n)=T(n-1)+T(1)+θ(n)  根据递归公式求得T(n)=O(n^2),和插入排序一样。

  2.   数组所有元素都是重复的

        这种情况和第一种情况一样,也是划分成1和n-1,时间复杂度T(n)=O(n^2)

二.快速排序优化

     那么该如何优化才能让快排时间复杂度不超过O(nlgn)呢?

    (1) 针对第一种情况,有两种方法:① 随机挑选主元;②打乱数组的顺序。我们之前的算法是挑选第一个元素为主元,如果是随机挑选,就避免了最坏情况的第一种。或者在数组划分前,先打乱数组的顺序,也可以达到同样效果

   (2)第二种情况,如果数组有大量的重复元素,那么快速排序效率会大大降低,划分的效果不理想,为什么?可以自己想一下,怎么解决呢?可以用三向切分快速排序

三向切分快速排序示意图:

   171418_spiZ_876257.png

  就是把数组分为三份,小于主元,等于主元,大于主元 三份。

如:把{1,5,7,5,9,3,8,6,4,5}====>{1,3,4,5,5,5,7,9,8},这样的话,等于主元的那一份就不用做递归,如果有大量重复的元素这种算法就比原始快排效率高很多,如果全部元素都是重复的,三向切分快速的时间复杂度为O(n)。

三.三向切分快速算法过程

     如何才能把数组三等份,下面我们通过例子来描述算法  a(n)={1,5,7,5,9,3,8,6,4,5}

                   1   5   7   5    9    3   8   6   4  5 

                    lt   i                                      gt 

  • 设v =a[0]  比较v和a[i] 

  • a[i]<v,交换a[lt]和a[i],lt和i都加1

  • a[i]>v 交换a[gt]和a[i],gt减1

  • a[i]=v  i加1 

  • 循环一直到i>gt,算法结束。

四.三向切分快速算法代码实现   

/**
 * 快速排序
 * */
public class Quicksort {

	public Quicksort() {
		// TODO Auto-generated constructor stub
	}

	// 3向切分快速排序
	public static void sort3way(int[] arry, int low, int hight) {
		if (hight < low)
			return;
		int lt = low, i = low + 1, gt = hight;
		int pivot = arry[low];
		int temp = 0;
		while (i <= gt) {
			if (arry[i] < pivot) {
				// 交换arry[i]和a[lt]
				temp = arry[lt];
				arry[lt] = arry[i];
				arry[i] = temp;
				lt++;
				i++;
			} else if (arry[i] > pivot) {
				// 交换arry[i]和a[gt]
				temp = arry[gt];
				arry[gt] = arry[i];
				arry[i] = temp;
				gt--;
			} else {
				i++;
			}

		}
		sort3way(arry, low, lt - 1);
		sort3way(arry, gt + 1, hight);
	}

	public static void main(String[] args) {
		int[] arry = { 1, 5, 7, 5, 9, 3, 8, 6, 4, 5 };
		sort3way(arry, 0, arry.length - 1);
		for (int n : arry) {
			System.out.println(n);
		}
	}
}

        

                                            

     


转载于:https://my.oschina.net/jianxiao/blog/634703

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值