接着上面的文章: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;
}
}