快速排序(方式一)
2017-01-17 00:00
127 查看
快速排序
毫无疑问,快速排序是最流行的排序算法,因为有充足的理由,在大多数情况下,快速排序都是最快的,执行时间为O(N*logN)级,(这只是对内部排序或者说随机存储器内的排序而言,对于磁盘文件中的数据进行的排序,其他的排序算法可能更好)。快速排序算法本质上通过把一个数组划分为两个子数组,然后递归的调用自身为每个子数组进行快速排序实现的。但是对这个基本的设计还需要进一步加工,算法还必须要选择枢纽以及对小的划分区域进行排序。
快速排序算法基本有三个步骤:
1、把数组或者子数组划分成左边(较小的关键字)的一组和右边(较大的关键字)的一组。
2、调用自身对左边的一组进行划分排序。
3、再次调用自身对右边的一组进行划分排序。
经过一次划分以后,所有左边子数组的数据项都小雨右边子数组的数据项,只要对左边子数组和右边数组分辨进行排序,整个数组就是有序的了,对子数组进行排序用递归调用排序算法自身即可。
在本例中选择最右边的数作为枢纽基值。
以下是实现代码(方式一):
// quickSort1.java // demonstrates simple version of quick sort // to run this program: C>java QuickSort1App //////////////////////////////////////////////////////////////// class ArrayIns { private long[] theArray; // ref to array theArray private int nElems; // number of data items //-------------------------------------------------------------- public ArrayIns(int max) // constructor { theArray = new long[max]; // create the array nElems = 0; // no items yet } //-------------------------------------------------------------- public void insert(long value) // put element into array { theArray[nElems] = value; // insert it nElems++; // increment size } //-------------------------------------------------------------- public void display() // displays array contents { System.out.print("A="); for(int j=0; j<nElems; j++) // for each element, System.out.print(theArray[j] + " "); // display it System.out.println(""); } //-------------------------------------------------------------- public void quickSort() { recQuickSort(0, nElems-1); } //-------------------------------------------------------------- public void recQuickSort(int left, int right) { if(right-left <= 0) // if size <= 1, return; // already sorted else // size is 2 or larger { long pivot = theArray[right]; // rightmost item // partition range int partition = partitionIt(left, right, pivot); recQuickSort(left, partition-1); // sort left side recQuickSort(partition+1, right); // sort right side } } // end recQuickSort() //-------------------------------------------------------------- public int partitionIt(int left, int right, long pivot) { int leftPtr = left-1; // left (after ++) int rightPtr = right; // right-1 (after --) while(true) { // find bigger item while( theArray[+ 3ff0 +leftPtr] < pivot ) ; // (nop) // find smaller item while(rightPtr > 0 && theArray[--rightPtr] > pivot) ; // (nop) if(leftPtr >= rightPtr) // if pointers cross, break; // partition done else // not crossed, so swap(leftPtr, rightPtr); // swap elements } // end while(true) swap(leftPtr, right); // restore pivot return leftPtr; // return pivot location } // end partitionIt() //-------------------------------------------------------------- public void swap(int dex1, int dex2) // swap two elements { long temp = theArray[dex1]; // A into temp theArray[dex1] = theArray[dex2]; // B into A theArray[dex2] = temp; // temp into B } // end swap( //-------------------------------------------------------------- } // end class ArrayIns //////////////////////////////////////////////////////////////// class QuickSort1App { public static void main(String[] args) { int maxSize = 16; // array size ArrayIns arr; arr = new ArrayIns(maxSize); // create array for(int j=0; j<maxSize; j++) // fill array with { // random numbers long n = (int)(java.lang.Math.random()*99); arr.insert(n); } arr.display(); // display items arr.quickSort(); // quicksort them arr.display(); // display them again } // end main() } // end class QuickSort1App
选择枢纽的第二种方法(左中右三数据项取中):
以下是实现代码:
// quickSort2.java // demonstrates quick sort with median-of-three partitioning // to run this program: C>java QuickSort2App //////////////////////////////////////////////////////////////// class ArrayIns { private long[] theArray; // ref to array theArray private int nElems; // number of data items //-------------------------------------------------------------- public ArrayIns(int max) // constructor { theArray = new long[max]; // create the array nElems = 0; // no items yet } //-------------------------------------------------------------- public void insert(long value) // put element into array { theArray[nElems] = value; // insert it nElems++; // increment size } //-------------------------------------------------------------- public void display() // displays array contents { System.out.print("A="); for(int j=0; j<nElems; j++) // for each element, System.out.print(theArray[j] + " "); // display it System.out.println(""); } //-------------------------------------------------------------- public void quickSort() { recQuickSort(0, nElems-1); } //-------------------------------------------------------------- public void recQuickSort(int left, int right) { int size = right-left+1; if(size <= 3) // manual sort if small manualSort(left, right); else // quicksort if large { long median = medianOf3(left, right); int partition = partitionIt(left, right, median); recQuickSort(left, partition-1); recQuickSort(partition+1, right); } } // end recQuickSort() //-------------------------------------------------------------- public long medianOf3(int left, int right) { int center = (left+right)/2; // order left & center if( theArray[left] > theArray[center] ) swap(left, center); // order left & right if( theArray[left] > theArray[right] ) swap(left, right); // order center & right if( theArray[center] > theArray[right] ) swap(center, right); swap(center, right-1); // put pivot on right return theArray[right-1]; // return median value } // end medianOf3() //-------------------------------------------------------------- public void swap(int dex1, int dex2) // swap two elements { long temp = theArray[dex1]; // A into temp theArray[dex1] = theArray[dex2]; // B into A theArray[dex2] = temp; // temp into B } // end swap( //-------------------------------------------------------------- public int partitionIt(int left, int right, long pivot) { int leftPtr = left; // right of first elem int rightPtr = right - 1; // left of pivot while(true) { while( theArray[++leftPtr] < pivot ) // find bigger ; // (nop) while( theArray[--rightPtr] > pivot ) // find smaller ; // (nop) if(leftPtr >= rightPtr) // if pointers cross, break; // partition done else // not crossed, so swap(leftPtr, rightPtr); // swap elements } // end while(true) swap(leftPtr, right-1); // restore pivot return leftPtr; // return pivot location } // end partitionIt() //-------------------------------------------------------------- public void manualSort(int left, int right) { int size = right-left+1; if(size <= 1) return; // no sort necessary if(size == 2) { // 2-sort left and right if( theArray[left] > theArray[right] ) swap(left, right); return; } else // size is 3 { // 3-sort left, center, & right if( theArray[left] > theArray[right-1] ) swap(left, right-1); // left, center if( theArray[left] > theArray[right] ) swap(left, right); // left, right if( theArray[right-1] > theArray[right] ) swap(right-1, right); // center, right } } // end manualSort() //-------------------------------------------------------------- } // end class ArrayIns //////////////////////////////////////////////////////////////// class QuickSort2App { public static void main(String[] args) { int maxSize = 16; // array size ArrayIns arr; // reference to array arr = new ArrayIns(maxSize); // create the array for(int j=0; j<maxSize; j++) // fill array with { // random numbers long n = (int)(java.lang.Math.random()*99); arr.insert(n); } arr.display(); // display items arr.quickSort(); // quicksort them arr.display(); // display them again } // end main() } // end class QuickSort2App
以上算法是以3为界限划分的,如果是三个数时就不用快速排序了,否则用快速排序,以下又是一种如果数少的话用插入排序,如果数多的话用快速排序算法,是两种排序算法的组合使用。
下面是java代码:
// quickSort3.java // demonstrates quick sort; uses insertion sort for cleanup // to run this program: C>java QuickSort3App //////////////////////////////////////////////////////////////// class ArrayIns { private long[] theArray; // ref to array theArray private int nElems; // number of data items //-------------------------------------------------------------- public ArrayIns(int max) // constructor { theArray = new long[max]; // create the array nElems = 0; // no items yet } //-------------------------------------------------------------- public void insert(long value) // put element into array { theArray[nElems] = value; // insert it nElems++; // increment size } //-------------------------------------------------------------- public void display() // displays array contents { System.out.print("A="); for(int j=0; j<nElems; j++) // for each element, System.out.print(theArray[j] + " "); // display it System.out.println(""); } //-------------------------------------------------------------- public void quickSort() { recQuickSort(0, nElems-1); // insertionSort(0, nElems-1); // the other option } //-------------------------------------------------------------- public void recQuickSort(int left, int right) { int size = right-left+1; if(size < 10) // insertion sort if small insertionSort(left, right); else // quicksort if large { long median = medianOf3(left, right); int partition = partitionIt(left, right, median); recQuickSort(left, partition-1); recQuickSort(partition+1, right); } } // end recQuickSort() //-------------------------------------------------------------- public long medianOf3(int left, int right) { int center = (left+right)/2; // order left & center if( theArray[left] > theArray[center] ) swap(left, center); // order left & right if( theArray[left] > theArray[right] ) swap(left, right); // order center & right if( theArray[center] > theArray[right] ) swap(center, right); swap(center, right-1); // put pivot on right return theArray[right-1]; // return median value } // end medianOf3() //-------------------------------------------------------------- public void swap(int dex1, int dex2) // swap two elements { long temp = theArray[dex1]; // A into temp theArray[dex1] = theArray[dex2]; // B into A theArray[dex2] = temp; // temp into B } // end swap( //-------------------------------------------------------------- public int partitionIt(int left, int right, long pivot) { int leftPtr = left; // right of first elem int rightPtr = right - 1; // left of pivot while(true) { while( theArray[++leftPtr] < pivot ) // find bigger ; // (nop) while( theArray[--rightPtr] > pivot ) // find smaller ; // (nop) if(leftPtr >= rightPtr) // if pointers cross, break; // partition done else // not crossed, so swap(leftPtr, rightPtr); // swap elements } // end while(true) swap(leftPtr, right-1); // restore pivot return leftPtr; // return pivot location } // end partitionIt() //-------------------------------------------------------------- // insertion sort public void insertionSort(int left, int right) { int in, out; // sorted on left of out for(out=left+1; out<=right; out++) { long temp = theArray[out]; // remove marked item in = out; // start shifts at out // until one is smaller, while(in>left && theArray[in-1] >= temp) { theArray[in] = theArray[in-1]; // shift item to right --in; // go left one position } theArray[in] = temp; // insert marked item } // end for } // end insertionSort() //-------------------------------------------------------------- } // end class ArrayIns //////////////////////////////////////////////////////////////// class QuickSort3App { public static void main(String[] args) { int maxSize = 16; // array size ArrayIns arr; // reference to array arr = new ArrayIns(maxSize); // create the array for(int j=0; j<maxSize; j++) // fill array with { // random numbers long n = (int)(java.lang.Math.random()*99); arr.insert(n); } arr.display(); // display items arr.quickSort(); // quicksort them arr.display(); // display them again } // end main() } // end class QuickSort3App
消除递归:对于现在的系统来说,消除递归所带来的改进并不是很明显,因为现在的系统可以更为有效的处理方法调用。
快速排序的效率
快速排序的时间复杂度为O(N*logN),对于分治算法来说都是这样的,在分治算法中用递归的方法把一列数据项分为两组,然后调用自身来分别处理每一组数据项,在这种情况下,算法实际上是以2为底的,运行时间和N*log2N成正比。以上所述快速排序是用递归实现的,根据排序代码的思路来说,排序方法是:选择数组最右端的数位枢纽基数,然后从最左边开始用第一个数和枢纽相比,若比枢纽数小则继续向右走,用第二个数和枢纽比较,直到有一个数比枢纽数大时停下来,记住此时概数的下标为m,然后用倒数第二个数(倒数第一个数是枢纽)和枢纽比较,若比枢纽大则继续向左,用倒数第三个数和枢纽比较,直到有一个数比枢纽数小则停下来,记住该数的下标为n,假设数组名为array,此时用array[m]和array
交换,然后再继续刚才的比较步骤,左边的指针(此处指针并不是C++中的指针,次数只是标记的意思)继续向右,右边的指针继续向左,直至两个指针相碰或者相交,就停止,然后把左边的指针的指向的值(这个值总是比枢纽值大的第一个数)跟枢纽值交换,枢纽值就归位了,此时一趟排序完成,枢纽的左边和右边在按照刚才的步骤进行排序。
相关文章推荐
- 选择,插入,希尔,快速,堆,归并排序六种排序方式的Java 实现和性能对比(付代码)
- 算法整理(二)---快速排序的两种实现方式:双边扫描和单边扫描
- 快速排序的三种不同的实现方式。
- 快速排序的递归方式和非递归方式
- 快速排序的两种实现方式(Java)
- 快速排序的两种实现方式,主要是Partition函数的实现原理不一样
- 快速排序一种易于理解的方式实现
- 快速排序两种实现方式
- 快速排序的几种实现方式
- Java程序员从笨鸟到菜鸟(二)Java实现冒泡排序、快速排序、插入排序、选择排序等基本排序方式
- Java中的数组排序方式(快速排序、冒泡排序、选择排序)
- 归并排序、快速排序---时间复杂度为O(nlog n)的排序方式
- 快速排序两种方式实现及优化总结
- 快速排序的三种实现方式以及非递归版本
- 必须快速进入具体的编程方式的学习过程中
- 快速排序!
- 快速排序方法Java实现与分析
- 设定维度属性的排序方式
- 快速排序
- OPENH323中呼叫建立过程的跟踪与分析(八)----非快速隧道方式之被叫端