【思维】快速排序

算法定义 

快速排序是一种排序算法,由C. A. R. Hoare所发展的,以平均效能来说,排序 n 个项目要Θ(n log n)次比较。然而,在最坏的效能下,它需要Θ(n2)次比较。一般来说,快速排序实际上明显地比其他Θ(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性。

算法描述 

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为 "基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 

源码描述

function  QuickSort_Once(_pnArray, _pnLow, _pnHigh) {
    
//  首先将首元素做为枢轴
     var  nPivot  =  _pnArray[_pnLow];
    
var  i  =  _pnLow, j  =  _pnHigh;  //  设置两个指针,分别指向首尾处
     while (i  <  j) {   //  直到两个指针重合
         //  从右向左,寻找首个小于枢轴的元素
         while (_pnArray[j]  >=  nPivot  &&  i  <  j) j -- ;
        _pnArray[i] 
=  _pnArray[j];    //  找到后 执行替换

        
//  从左到右,寻找首个大于枢轴的元素
         while (_pnArray[i]  <=  nPivot  &&  i  <  j) i ++ ;
        _pnArray[j] 
=  _pnArray[i];    //  找到后 执行替换
    }
    
//  至此i,j两指针重合执行同一位置,i即是新的枢轴位置
    _pnArray[i]  =  nPivot;
    
return  i;
}
function  QuickSort(_pnArray, _pnLow, _pnHigh) {
    
if (_pnLow  >=  _pnHigh)  return ;
    
//  获取枢轴
     var  _nPivotIndex  =  QuickSort_Once(_pnArray, _pnLow, _pnHigh);
    
//  然后对被枢轴分开的两侧进行分别递归
    QuickSort(_pnArray, _pnLow, _nPivotIndex  -   1 );
    QuickSort(_pnArray,  _nPivotIndex 
+   1 , _pnHigh);
}

/*  排序测试  */
(
function () {
    
//  10个随机数
     var  arr  =  [];
    
for ( var  i  =   0 ; i  <   10 ; i ++ ) {
        arr[i] 
=  Math.floor(Math.random()  *   60 );
    }
    document.write(
' 初始值:  '   +  arr  +   ' <br/> ' );
    QuickSort(arr, 
0 , arr.length  -   1 );
    document.write(
' 排序值:  '   +  arr);

})();  

另一种实现

function  QuickSort(arr, start, end) {
    
if  (start  <  end) {
        
var  q  =  Partition(arr, start, end);  //  找出分割基准点
        QuickSort(arr, start, q - 1 );
        QuickSort(arr, q
+ 1 , end);
    } 
}

//  元素交换
function  swap(arr, a, b) {
    
if  (a  ==  b)  return
    
var  temp  =  arr[a];
    arr[a] 
=  arr[b];
    arr[b] 
=  temp;
}

//  数组分割
function  Partition(arr, start, end) {
    
var  pivot  =  arr[end];  //  将数组最后一个元素作为主元
     var  i  =  start  -   1 //  指定一个指针
     for  ( var  j  =  start; j  <  end; j ++ ) {
        
if  (arr[j]  <=  pivot)  {  //  如果当前元素小于主元
            i  =  i  +   1 ;
            swap(arr, i, j);
        } 
    }
    swap(arr, i 
+   1 , end);
    
return  (i  +   1 );
}

var  arr  =  [ 2 , 8 , 7 , 1 , 3 , 5 , 6 , 4 ];
QuickSort(arr, 
0 7 );
alert(arr);

因为如果是已经排好序的话。那么用快速选择还需要O(n^2)的时间复杂度。这样是不优的。为了防止这种情况。所以在数据量大的时候可以使用随机化版本。随机化主元就避免最坏情况发生。

随机选择排序

function  QuickSort(arr, start, end) {
    
if  (start  <  end) {
        
var  q  =  RandomPartition(arr, start, end);  //  找出分割基准点
        QuickSort(arr, start, q - 1 );
        QuickSort(arr, q
+ 1 , end);
    } 
}

//  元素交换
function  swap(arr, a, b) {
    
if  (a  ==  b)  return
    
var  temp  =  arr[a];
    arr[a] 
=  arr[b];
    arr[b] 
=  temp;
}

//  数组分割
function  Partition(arr, start, end) {
    
var  pivot  =  arr[end];  //  将数组最后一个元素作为主元
     var  i  =  start  -   1 //  指定一个指针
     for  ( var  j  =  start; j  <  end; j ++ ) {
        
if  (arr[j]  <=  pivot)  {  //  如果当前元素小于主元
            i  =  i  +   1 ;
            swap(arr, i, j);
        } 
    }
    swap(arr, i 
+   1 , end);
    
return  (i  +   1 );
}

//  随机交换主元后再Partition
function  RandomPartition(arr, start, end) {
    
var  i  =  Math.floor(Math.random()  *  (end  -  start  +   1 +  start);
    swap(arr, end, i);
    
return  Partition(arr, start, end);
}

var  arr  =  [ 2 , 8 , 7 , 1 , 3 , 5 , 6 , 4 ];
QuickSort(arr, 
0 7 );

alert(arr); 

其余参考:

c#与算法--快速排序

快速排序

CSDN快速排序

http://www.ruanyifeng.com/blog/2011/04/quicksort_in_javascript.html?20110404221633 

http://jsdo.it/norahiko/oxIy/fullscreen 

转载于:https://www.cnblogs.com/bluedream2009/archive/2011/04/14/2015527.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值