快速排序(二)

接着上面的文章:https://blog.csdn.net/szlg510027010/article/details/83106798

(代码后面探讨的是优化这段代码的问题)

以下是总代码:

/**
 * 划分
 * @author Administrator
 *
 */
public class reQuicSort {
	
	private int[] theArray;
	private int nElems;
	
	public reQuicSort(int maxSize) {
		theArray = new int[maxSize];
		nElems = 0;
	}
	
	public void insert(int number) {
		theArray[nElems++] = number;
	}
	
	public void display() {
		for(int i=0;i<nElems;i++) 
			System.out.print(theArray[i]+" ");
		System.out.println();
	}
	
	public void QuickSort() {
		reQuickSort(0,nElems-1);
	}
	
	public void reQuickSort(int left,int right) {
		if(left>=right)
	        return;
		int pivot = theArray[right];
		int partition = partition(left,right,pivot);
		reQuickSort(left,partition-1);
		reQuickSort(partition+1,right);
	}
	
	public int partition(int left,int right,int pivot) {
		int leftArrow = left-1;
		int rightArrow = right;
		while(true) {
			while(theArray[++leftArrow]<pivot);
			while(rightArrow>0 && theArray[--rightArrow]>pivot);
			
			if(leftArrow>=rightArrow)
				break;
			else
				swap(leftArrow,rightArrow);
		}
		swap(leftArrow,right);
		return leftArrow;//返回相遇的下标
	}
	
	//交换(swap方法)
	public void swap(int leftPtr,int rightPtr) {
		int change = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = change; 
	}
	
}
/**
 * 测试快速排序
 * @author Administrator
 *
 */
public class QuickSortApp {
	public static void main(String[] args) {
		int maxSize = 10;
		reQuicSort arr = new reQuicSort(maxSize);
		for(int i=0;i<maxSize;i++) {
			int n =(int)(java.lang.Math.random()*99);
			arr.insert(n);
		}
		arr.display();
		arr.QuickSort();
		arr.display();
	}
}

发现当数组是由大到小的时候,我们要想将其从小到大排序,就会效使时间复杂度将为O(N ^ 2),这不是我们想要的结果,为了解决这个问题,通过不断的推演,分析,人类最终发明了折中的方法 - “三数据项取中”,即取最左,最右,中间,将三者进行排序采用“三数据项取中”,还可以将一个内部循环的条件向右键>左省去,使得比前面的算法略微快一点。

另一个好处:

这种方法对左端,中间以及右端的数据项排序之后,划分过程就不需要再考虑这三个数据项了划分可以从左边+ 1和右+ 1开始,因为; eftheright已经被有效地划分了。因为留在左边并且小于枢纽,所以它已经在正确的划分中了,对在右边且大于枢纽,所以它也在正确的划分中。

这样,三数据项取中的划分方法不但避免了对已有序数据项排序的执行效率为O(N ^ 2),而且它也提高了划分算法内部循环的执行速度,并稍稍减少了必须要划分的数据项数目。

仍然用图像来说明:

将三者进行排序:

代码如下:

/**
 * 划分
 * @author Administrator
 *
 */
public class reQuicSort {
	
	private int[] theArray;
	private int nElems;
	
	public reQuicSort(int maxSize) {
		theArray = new int[maxSize];
		nElems = 0;
	}
	
	public void insert(int number) {
		theArray[nElems++] = number;
	}
	
	public void display() {
		for(int i=0;i<nElems;i++) 
			System.out.print(theArray[i]+" ");
		System.out.println();
	}
	
	public void QuickSort() {
		reQuickSort(0,nElems-1);
	}
	
	public void reQuickSort(int left,int right) {
		int size = right-left+1;
		if(size<=3)
			manualSort(left,right);//手动排序
		
		else {
			int pivot = Sort3(left,right);
			if(left>=right)
				return;
			int partition = partition(left,right,pivot);
			reQuickSort(left,partition-1);
			reQuickSort(partition+1,right);
		}
	}
	
	public int partition(int left,int right,int pivot) {
		int leftArrow = left;
		int rightArrow = right-1;
		while(true) {
			while(theArray[++leftArrow]<pivot);
			while(theArray[--rightArrow]>pivot);
			
			if(leftArrow>=rightArrow)
				break;
			else
				swap(leftArrow,rightArrow);
		}
		swap(leftArrow,right-1);
		return leftArrow;//返回相遇的下标
	}
	
	public void manualSort(int left,int right) {
		int size = right-left+1;
		if(size==1)
			return;
		if(size==2) {
			if(theArray[left]>theArray[right])
				swap(left,right);
		}
		if(size==3) {
			if(theArray[left]>theArray[right-1])
				swap(left,right-1);
			if(theArray[left]>theArray[right])
				swap(left,right);
			if(theArray[right-1]>theArray[right])
				swap(right-1,right);
		}
	}
	
	public int Sort3(int left,int right) {
		int center = (left+right)/2;
		if(theArray[left]>theArray[center])
			swap(left,center);
		if(theArray[left]>theArray[right])
			swap(left,right);
		if(theArray[center]>theArray[right])
			swap(center,right);
		swap(center,right-1);
		return theArray[right-1];
	}
	
	//交换(swap方法)
	public void swap(int leftPtr,int rightPtr) {
		int change = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = change; 
	}
	
}
/**
 * 
 * @author Administrator
 *
 */
public class QuickSortApp {
	public static void main(String[] args) {
		int maxSize = 13;
		reQuicSort arr = new reQuicSort(maxSize);
		for(int i=0;i<maxSize;i++) {
			int n =(int)(java.lang.Math.random()*99);
			arr.insert(n);
		}
		arr.display();
		arr.QuickSort();
		arr.display();
	}
}

我们还可以继续改进这个算法,我们发现当size<=3的时候,我们是手动去排序的,其实我们可以对这些小划分进行插入排序。

	public void insertSort() {
		int i,j,temp;
		for(i=1;i<nElems;i++) {
			j=i;
			temp = theArray[i];
			while(j>0 && temp<theArray[j-1]) {
				theArray[j] = theArray[j-1];
				--j;
			}
			theArray[j] = temp;
		}
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值