算法熟记-排序系列-快速排序

1. 简述

    假设待排序数组为 int array[], 数组长度为n。快速排序是一个递归得方法。
    当n==1的时候,停止排序。
    当n>1的时候,首先选择数组中得一个元素作为基准,然后,把小于这个基准得元素放到这个基准的左边,把大于这个基准得元素放到这个元素得右边。
    具体实现下面进行简单得说明,假设array[0]作为基准:
    首先,存储基准得值,int tmp=array[0];
    然后,两个指针,int left=0; int right = n-1;
    bool flag_left = false; // 初始从右边开始                                
    while(left < right) {
        if(flag_left == true) {
            如果当前值小于基准,则left++;
            否则,array[right]=array[left]; right--; flag_left = false;
        }       
        else {
             如果当前值大于基准,则right--;
             否则,array[left]=array[right]; left++; flag_left = true;

        }

    } 
    array[left] = tmp;
    上面这段代码中,当轮到left指针执行时,right指针向的位置是可以使用的。当轮到right指针执行时,left指针指向的位置是可以使用的。
    初始时,备份了array[0],left指针指向的位置是可以使用 得,因此从右边开始。
    最后,递归排序array[0]-array[left-1]和array[left+1]-array[n-1]两个部分的数组。
2. 复杂度

    平均时间复杂度是O(N*logN)。当数组本身已经有序得情况下,需要比较得次数是N*N次。为了解决这样的问题,可以使用乱数快速排序,即每次基准是随即选择的。
    稳定性属于非稳定排序。因为在与基准的比较过程中的交换很可能打破已有的顺序。

3. 代码    

void  quick_sort( int  array[],  int  n) {
  
if (n  <=   1 )
    
return ;
  
int  tmp  =  array[ 0 ];
  
int  left  =   0 int  right  =  n - 1 ;
  
bool  left_flag  =   false ;
  
while (left  <  right) {
    
if (left_flag  ==   true ) {  //  当前left指针
       if (array[left]  <  tmp) {
        left
++ ;
      }
      
else  {
        array[right] 
=  array[left];
        right
-- ;
        left_flag 
=   false ;
      }
    }
    
else  {  //  当前right指针
       if (array[right]  >  tmp) {
        right
-- ;
      }
      
else  {
        array[left] 
=  array[right];
        left
++ ;
        left_flag 
=   true ;
      }
    }
  } 
  array[left] 
=  tmp;
  quick_sort(array, left); 
//  array[0]-array[left-1]
  quick_sort(array + left + 1 , n - left - 1 );  //  array[left+1], array[n-1]
}

    实际上,快速排序是作为冒泡排序的改进提出来的,很多实现都是通过元素交换实现的,上面的代码是改进后的,更加有效率,把元素交换变成了元素的赋值。
    一般来说,交换排序包括:冒泡排序和快速排序。
    下面贴一个快速排序使用交换元素的实现:
   

void  quicksort( int  arr[], int  beg, int  end) {
  if  (end   >=  beg  +   1 ) {
    
int  piv  =  arr[beg], k  =  beg  +   1 , r  =  end;
    // 从基准(array[0])右边的元素开始扫描,对于小于基准的元素跳过,对于大于基准的元素,交换到右边的位置上去,缩减右边的位置。
    // 当右边可以交换的位置与当前元素重叠了,结束循环
    
while  (k  <  r) {
       if  (arr[k]  <  piv) 
        k
++ ;
      
else
        swap(
& arr[k],  & arr[r -- ]);
    }
    // 交换基准
    
if  (arr[k]  <  piv){
      swap( & arr[k], & arr[beg]);
      quicksort(arr, beg, k);
      quicksort(arr, r, end);                    
    }
    else  {
      
if  (end  -  beg  ==   1 )
      
return ;
      swap(
& arr[ -- k], & arr[beg]);
      quicksort(arr, beg, k);
      quicksort(arr, r,   end);                  
    }
  }
}

4. 参考资料

    维基百科-快速排序    http://en.wikipedia.org/wiki/Quicksort

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值