经典快排和随机快排

/**
 * 经典快排、随机快排
 * 经典快排:利用最后一个数作为分界点,小的放左边,大的放右边,可以使用荷兰国旗问题(文末)的方法优化
 * 随机快排:产生一个随机位置作为分界点
 */

import java.util.Arrays;
public class C04_QuickSort {
	public static void quickSort(int[]arr){
		if(arr==null || arr.length<2){
			return ;
		}
		//经典快排和随机快排:
		//classicSort(arr,0,arr.length-1);
		randomSort(arr,0,arr.length-1);
	}
	//经典快排
	public static void classicSort(int arr[],int left,int right){
		if(left<right){
			//数组,左边界,右边界,partition的条件num
			int par[] = partition(arr, left, right,arr[right]);
			//递归解决(工程上是不允许递归的)
			classicSort(arr, left, par[0]-1);
			classicSort(arr, par[1]+1, right);
		}
	}
	//随机快排
	public static void randomSort(int arr[],int left,int right){
		if(left<right){
			//随机快排就是经典快排的基础上多这一步:产生一个随机位置与最后一个位置的数交换
			//从而使时间复杂度理论的长期 期望值是 :O(N*logN)
			swap(arr, right, left+(int)((right-left+1)*Math.random()) );
			int par[] = partition(arr, left, right, arr[right]);
			randomSort(arr, left, par[0]-1);
			randomSort(arr, par[1]+1, right);
		}
	}
	//荷兰国旗问题的思想(小于放左边,等于放中间,大于放右边)
	public static int[] partition(int arr[] ,int left,int right,int num){
		int index = left;	//当前位置索引
		int less=left-1;	//小于区域
		int more=right;		//大于区域
		while(index<more){	//当前位置一直往右推移,一定会遇到大于区域
			if(arr[index] < num){
				//当前位置的数与小于区域的下一个数交换,然后当前位置下移一位
				swap(arr,index++,++less);
			}else if(arr[index] > num ){
				//当前位置的数与大于区域的前一个数交换,因为刚交换过来的数不知道大小,所以需要继续比较
				swap(arr, index, --more);
			}else {
				//等于的情况只需要当前位置下移一位
				index++;
			}
		}
		swap(arr, more, right);
		//返回一个等于区域的左右边界
		return new int[]{less+1,more};
	}

	//交换
	public static void swap(int arr[],int i,int j){
		int t = arr[i];
		arr[i] = arr[j];
		arr[j] = t; 
	}
	
	//for test/
	/*
	 * 使用对数器进行校验
	 */
	
	//产生测试数据
	public static int[] testData(int len,int val){
		int arr[] = new int[len];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int)(val*Math.random());
		}
		return arr;
	}
	//打印数组
	public static void printArr(int []arr){
		for(int i:arr){
			System.out.print(i+" ");
		}
		System.out.println();
	}
	//判断两个数组是否相等
	public static boolean isEquals(int[] arr1,int[] arr2){
		if(arr1==null || arr2==null || arr1.length!=arr2.length || arr1.length==0){
			return false;
		}
		boolean judge = true;
		for (int i = 0; i < arr2.length; i++) {
			if(arr1[i]!=arr2[i]){
				judge = false;
				break;
			}
		}
		return judge;
	}
	public static void main(String[] args) {
		int len = 10;
		int val=100;
		int times = 500000;
		boolean isTrue = true;
		while(times-->0){
			int arr1[] = testData(len, val);
			int arr2[] = Arrays.copyOf(arr1, arr1.length);
			//自己写的快排进行排序
			quickSort(arr1);
			//系统快排
			Arrays.sort(arr2);
			//进行对比
			if(! isEquals(arr1, arr2)){
				printArr(arr1);
				printArr(arr2);
				isTrue = false;
				break;
			}
		}
		if(isTrue){
			System.out.println("Nice!");
		}else {
			System.out.println("Fucking Wrong!");
		}
	}
}

荷兰国旗问题


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值