快速排序(算法导论)java实现

     快速排序(QuickSort)是对冒泡排序(BubbleSort)的一种改进。排序效率在同为O(N*logN)的几种排序方法中效率较高,且快速排序算法是 分治策略的典型应用。时间复杂度: O(N*logN)。

版本一:

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

/**
 * 快速排序一,算法导论P95
 * @author Administrator
 *
 */
public class QuickSort {
	
	public void quickSort(Integer[] array, int left, int right) {
		if(left < right) {
			int p = partition(array, left, right);   //设置递归边界
			quickSort(array, left, p-1);             //递归处理左序列
			quickSort(array, p+1, right);            //递归处理右序列
		}
	}
	
	/**
	 * 关键部分, 实现对子数组 array[p...r] 的原址重排
	 * @param array
	 * @param p
	 * @param r
	 * @return
	 */
	public int partition(Integer[] array, int left, int right) {
		Integer x = array[right];    //x为主元,在序列中为最后一个元素
		int p = left-1;
		
		//从第一个循环到倒数第二个(r-1)元素,和主元进行比较
		for(int j = left; j < right; j++) {
			if(array[j] <= x) { // <= 表示由小到大排列
				p++;
				this.exchange(array, p, j);  //把array[p]右边的元素和当前元素交换
			}
		}
		//直到循环结束,整个序列就变成了三部分
        //从array[left..p]是比主元小的元素,array[p+1..right-1]是比主元大的元素,array[right]则是主元
		
		//划分的目的是将主元放在这两个序列的中间,此时p在小序列的最后一位,p+1则是大序列的第一位
		//所以把主元(最后一位)和大序列的第一个元素交换
		this.exchange(array, p+1, right);
		return p+1;
	}
	
	/**
	 * 实现 array[a] 和 array[b] 两个元素的交换
	 * @param array
	 * @param a
	 * @param b
	 */
	public void exchange(Integer[] array, int a, int b) {
		Integer temp = array[a];
		array[a] = array[b];
		array[b] = temp;
	}
}

图解:

版本二(随机化):

版本二是版本一的加强。版本一在选取主元的时候,每次都选取最右边的元素。当序列为有序时,会发现划分出来的两个子序列一个里面没有元素,而另一个则只比原来少一个元素。为了避免这种情况,引入一个随机化量来破坏这种有序状态。

在随机化的版本二中,选取 a[left..right] 中的随机一个元素作为主元,然后再进行划分,就可以得到一个平衡的划分。

import java.util.Random;

/**
 * 随机化的快速排序,并为100万的随机数测试
 * @author Administrator
 *
 */

public class RandomizedQuickSort {
	
	public void randomizedQuickSort(Integer[] array, int left, int right) {
		if(left < right){
			int p = randomizedPartition(array, left, right);  //设置递归边界
			this.randomizedQuickSort(array, left, p-1);       //递归处理左序列
			this.randomizedQuickSort(array, p+1, right);      //递归处理右序列
		}
	}
	
	/**
	 * 随机化分组
	 * @param array
	 * @param left
	 * @param right
	 * @return
	 */
	public int randomizedPartition(Integer[] array, int left, int right) {
		int random = this.randomNum(left, right);  //生成一个随机数,即是主元所在位置
		this.exchange(array, random, right);  //将主元与最右边元素互换位置,这样就变成了之前快排的形式
		Integer x = array[right]; // 现在最后一位又变成主元了,所有以下部分和版本一的partition()方法一样
		int i = left-1;
		for(int j = left; j < right; j++) {
			if(array[j] <= x) {
				i++;
				this.exchange(array, i, j);
			}
		}
		this.exchange(array, i+1,right);
		return i+1;
	}
	
	/**
	 * 实现 array[a] 和 array[b] 两个元素的交换
	 * @param array
	 * @param a
	 * @param b
	 */
	public void exchange(Integer[] array, int a, int b) {
		Integer temp = array[a];
		array[a] = array[b];
		array[b] = temp;
	}
	
	/**
	 * 在i到j的区间内随机生成一个数,其中i和j为序列的下标
	 * 该方法是为了随机找到一个元素作为主元
	 * @param i
	 * @param j
	 * @return
	 */
	public int randomNum(int i, int j) {
		Random random = new Random();  // 使用Random函数产生随机数
		return random.nextInt(j-i) + i;  // random.nextInt(n)为产生的随机数的范围
	}
	
	public static void main(String[] args) {
		Integer[] testArray = new Integer[1000000];  //建立待测试的数组,数组容量为100万
		int len = testArray.length;
		Random random = new Random();
		for(int i=0; i<len; i++) {
			testArray[i] = random.nextInt(1000000);
		}
		
		/**
		for(int i=0; i<len; i++) {
			System.out.println(testArray[i] + "");
		}
		*/
		
		long start = System.currentTimeMillis();
		RandomizedQuickSort qs = new RandomizedQuickSort();
		qs.randomizedQuickSort(testArray, 0, testArray.length-1);
		long end = System.currentTimeMillis();
		
		/**
		System.out.println("排序结果");
		for(Integer i : testArray) {
			System.err.print(i + "<");
		}
		*/
		
		long time = end - start;
		System.out.println("排序耗时:" + String.valueOf(time));
	}

}

实验结果:

100w数字:

算法第1次耗时第2次耗时第3次耗时第4次耗时第5次耗时平均耗时
普通快排663ms728ms775ms701ms744ms722ms
随机化版本快排946ms978ms804ms1014ms886ms925ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值