快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据 分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
以上来自百度!
下面是我写的 代码 :
public function quickSortMe(A:Array,left:int,right:int):void{
if(left<right){
var p:int=partitionMe(A,left,right)
quickSortMe(A,left,p-1);
quickSortMe(A,p+1,right);
}
}
private function partitionMe(A:Array,left:int,right:int):int{
//试着把下面两行任意放开一行 测试一下速度的差距!
var p:int=left;
// var p:int=Math.random()*(right-left)+left;
var temp:Number=A[p];
A[p]=A[right];
A[right]=temp;
var store:int=left;
for(var i:int=left;i<right;i++){
if(A[i]<=temp){
var v:Number=A[store];
A[store]=A[i];
A[i]=v;
store++;
}
}
v=A[right];
A[right]=A[store];
A[store]=v;
return store;
}
我这里测试了一下:
n=1000 的情况下
用p=left 需要 100~120毫秒
用p=Math.random()*(right-left)+left; 只需要 4~5 毫秒!
天壤之别啊!
最终优化:
中值的选择,采用 三中值来减少最坏情况的出现。
一下是全部代码:
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓插入排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓插入排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓插入排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
/**
*插入排序
* @param p
* @return
*/
public function insertionSort(p:Array):Array{
return _insertionSort(p,0,p.length-1);
}
/**
* 一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
* 1. 从第一个元素开始,该元素可以认为已经被排序
* 2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
* 3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
* 4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
* 5. 将新元素插入到该位置中
* 6. 重复步骤2
* @param p
* @param left
* @param right
* @return
*/
public function _insertionSort(p:Array,left:int,right:int):Array{
for(var i:int=left+1;i<=right;i++) {
var temp:Number = p[i];
for(var j:int=i ; j>0 && temp<p[j-1];j--) {
p[j]=p[j-1];
}
p[j]=temp;
}
return p
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑插入排序↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑//
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓快速排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓快速排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓快速排序↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
/**
*快速排序
* @param A
* @param cmp
*/
public function quickSortMe(A:Array,left:int,right:int):void{
if(left<right){
var p:int=partitionMe(A,left,right)
if(right-left<7){
_insertionSort(A,left,p);
_insertionSort(A,p,right);
}else{
quickSortMe(A,left,p-1);
quickSortMe(A,p+1,right);
}
}
}
/**
*
* @param A
* @param left
* @param right
* @return
*
*/
private function partitionMe(A:Array,left:int,right:int):int{
var p:int=medianOf3(A,left,right);
// var p:int=Math.random()*(right-left)+left;
var temp:Number=A[p];
A[p]=A[right];
A[right]=temp;
var store:int=left;
for(var i:int=left;i<right;i++){
if(A[i]<=temp){
var v:Number=A[store];
A[store]=A[i];
A[i]=v;
store++;
}
}
v=A[right];
A[right]=A[store];
A[store]=v;
return store;
}
/**
* 三数据选中
* @param left
* @param right
* @return
*/
private function medianOf3(A:Array,left:int,right:int):int{
var center:int = (right-left) / 2+left;
if (A[left] > A[center]) {
swap(A,left, center);
}
if (A[left] > A[right]) {
swap(A,left, right);
}
if (A[center] > A[right]) {
swap(A,center, right);
}
return center;
}
如何优化:
1.切分时的值的选择,如果1~10 需要排序 最理想的中间值是5 因为我们只需要移动赋值一半就OK了对吧?
所以呢先驱们想出了很多办法.....如:
1.k(中间值)=left或者=right;
2.k=A[left,right]中的随机的一个元素
3.在A中 随机取出几个元素 形成|M| 然后再M 中的中值作为 |A|的中值
由于3需要例外的开销!俺放弃了 所以算用随机选择的方法!
2.当问题规模比较小时,我们可以用插入排序!
接下来的时间 俺研究第2个优化方法!
/**
*快速排序
* @param A
* @param cmp
*/
public function quickSortMe(A:Array,left:int,right:int):void{
if(left<right){
var p:int=partitionMe(A,left,right)
if(right-left<20){
_insertionSort(A,left,p);
_insertionSort(A,p,right);
}else{
quickSortMe(A,left,p-1);
quickSortMe(A,p+1,right);
}
}
}
private function partitionMe(A:Array,left:int,right:int):int{
//试着把下面两行任意放开一行 测试一下速度的差距!
// var p:int=left;
var p:int=Math.random()*(right-left)+left;
var temp:Number=A[p];
A[p]=A[right];
A[right]=temp;
var store:int=left;
for(var i:int=left;i<right;i++){
if(A[i]<=temp){
var v:Number=A[store];
A[store]=A[i];
A[i]=v;
store++;
}
}
v=A[right];
A[right]=A[store];
A[store]=v;
return store;
}
public function _insertionSort(p:Array,left:int,right:int):Array{
for(var i:int=left+1;i<=right;i++) {
var temp:Number = p[i];
for(var j:int=i ; j>0 && temp<p[j-1];j--) {
p[j]=p[j-1];
}
p[j]=temp;
}
return p
}
经过优化之后,数据量小的时候看不出来 比如n=1000 任然一样是 4毫秒! 但是如果达到10W 就会有所改善!