快排算法及变形

快速排序普遍被认为是平均性能最好的基于比较的排序,平均时间复杂度是O(NlogN),当序列已经有序的时候,复杂度最高为O(N^2)

第一次的代码

/**
 * 快排,第一次的思路,虽然一个函数搞定,但是思路和代码不够清晰简练
 */
public void binSort2(Integer arr[], int s, int e){
	int val = arr[s];
	int idx = s; //明显可以优化掉的。。。
	for(int i=s, j=e;i<=j; ){
		while(i<=j && arr[j]>=val)
			j--;
		if(j>=i){
			arr[idx] = arr[j];
			idx = j;
			j--;
		}else
			break;
		while(i<=j && arr[i]<=val)
			i++;
		if(j>=i){
			arr[idx] = arr[i];
			idx = i;
			i++;
		}else
			break;
	}
	arr[idx] = val;
	if(idx>s+1)
		binSort2(arr, s, idx-1);
	if(idx<e-1)
		binSort2(arr, idx+1, e);
	
}

看书后的代码

public int binSplit(Integer arr[], int s, int e){
	int val = arr[s];
	while(e>s){
		while(e>s && arr[e]>=val)
			e--;
		if(e>s)
			arr[s] = arr[e];
		while(e>s && arr[s]<=val)
			s++;
		if(e>s)
			arr[e] = arr[s];
	}
	arr[s] = val;
	return s;
}
/**
 * 看数据结构书上的思路,其实差不多,关键是其将快排显式地分为两个子过程,增强了代码的可读性和可理解性
 * */
public void binSort(Integer arr[], int s, int e){
	int mid = binSplit(arr, s, e);
	if(mid>s+1)
		binSort(arr, s, mid-1);
	if(mid<e-1)
		binSort(arr, mid+1, e);
}

精简后的代码

/**
 * 精简后的代码
 */
public void binSort0(int A[], int s, int e) {
	if (e <= s)
		return;
	int val = A[s], i = s, j = e;
	while (i < j) {
		while (A[j] >= val && j > i)
			j--;
		A[i] = A[j];
		while (A[i] <= val && i < j)
			i++;
		A[j] = A[i];
	}
	A[i] = val;
	binSort0(A, s, i - 1);
	binSort0(A, i + 1, e);
}

变形1: 找前k个最小值并排序

/**
 * find and sort the first k minimum value in arr
 */
public void binSortKMinimum(Integer arr[], int s, int e, int k){
	int mid = binSplit(arr, s, e);
	if(mid>s+1)
		binSortKMinimum(arr, s, mid-1, k);
	if(mid<k-1 && mid<e-1)
		binSortKMinimum(arr, mid+1, e, k);
}

变形2: 找前k个最小值,不用排序

/**
 * find the first k minimum value in arr(without sorting)
 */
public void binFindKMinimum(Integer arr[], int s, int e, int k){
	int mid = binSplit(arr, s, e);
	if(mid>k-1 && mid>s+1)
		binFindKMinimum(arr, s, mid-1, k);
	if(mid<k-1 && mid<e-1)
		binFindKMinimum(arr, mid+1, e, k);
}

测试代码

/**
 * @param args
 */
public static void main(String[] args) {
	// TODO Auto-generated method stub
	QuickSort qs = new QuickSort();
	Integer[] arr = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
	ArrayList<Integer> list = new ArrayList<Integer>();
	Collections.addAll(list, arr);
	int maxIter = 1000;
	while(maxIter-->0){
		Collections.shuffle(list); //			System.out.println(list);
		list.toArray(arr);
		int s=0, e=arr.length-1, k=e/2; //			qs.binSort(arr, 0, e); //			qs.binSort2(arr, 0, e); //			qs.binFindKMinimum(arr, s, e, k);
		qs.binSortKMinimum(arr, s, e, k);
		if(!isAscend(arr, s, k))
			System.out.println("FAIL");
	}
	System.out.println("Over");
}

public static boolean isAscend(Integer[] arr, int s, int e){
	while(s<e){
		if(arr[s+1]<arr[s])
			return false;
		else
			s++;
	}
	return true;
}
TOP