• 快速排序算法学习笔记


    快速排序是一种比较实用的排序算法,平均时间复杂度为O(nlogn),最坏情况为O(n*n),最好情况也是O(nlogn)。该算法基于分治处理思想,在数列中选取一个主元,根据这个主元把整个数列分为两部分:一部分比这个主元小,一部分比这个主元大。然后对这两部分分别再选取主元划分,以此递归下去。

    针对一个A[p....r]的数组,其执行步骤可以描述为:

    1、分组:A[p..r]被划分为两个可能为空的子数组A[p..q-1]和A[q+1..r],使得A[p..q-1] <= A[q] <= A[q+1..r];

    2、解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序。

    3、合并。

    快速排序的关键是实现分组(partion),此过程有多种实现方法。主元可以分别选取首、尾,或者使用三数取中法。数组扫描方向又可以单向扫描和双向扫描。另外,借助栈结构,还有非递归版本的实现。

    目前,自己分析实现了的版本如下:

    1、尾数作为主元,从前往后单向扫描

    貌似此版本是《算法导论》里的实现版本,具体我也没看过,好多博客里都这样说。伪代码如下:

    QUICKSORT(A, p, r)
     if p < r
        then q ← PARTITION(A, p, r)  
             QUICKSORT(A, p, q - 1)
             QUICKSORT(A, q + 1, r)
    关键的分组过程:

    PARTITION(A, p, r)
      x ← A[r]
      i ← p - 1
      for j ← p to r - 1
           do if A[j] ≤ x
                 then i ← i + 1
                      exchange A[i] <-> A[j]
      exchange A[i + 1] <-> A[r]
      return i + 1
    具体实现:

     int partionLast(int arr[], int p, int r){
         int x = arr[r];
         int i = p - 1;
          int j, tmp;
          for(j = p; j < r ; j++){
              if(arr[j] <= x){
                  i++;
                  tmp = arr[i];
                  arr[i] = arr[j];
                  arr[j] = tmp;
              }
          }   
          tmp = arr[i+1];
          arr[i+1] = arr[j];
          arr[j] = tmp;
          return i+1;
     }
    <pre name="code" class="cpp">  void quicksort(int arr[], int p, int r){
          if(p<r){
              int q = partionLast(arr,p,r);
              quicksort(arr,p,q-1);
              quicksort(arr,q+1,r);
          }    
     }

    
    2、第一个数作为主元,从前往后单向扫描
      int partionFirst(int arr[], int p, int r){
           int x = arr[p];
           int i = p;
           int j,tmp;
           for(j = p+1; j <= r; j++){
               if(arr[j] <= x){
                   i++;
                  tmp = arr[i];
                  arr[i] = arr[j];
                  arr[j] = tmp;
              }                                                                                                         
          }    
          tmp = arr[i];
          arr[i] = arr[p];
          arr[p] = tmp;
          return i;
     }  
    3、尾数作主元,双向扫描

     int partionDoubleEnded(int arr[], int p, int r){
         int x = arr[r];
         int i = p;
         int j = r - 1;
         int tmp;
         do{  
             if(arr[i] <= x){
                 i++;
             }else{
                 if(arr[j] >= x){
                     j--;
                 }else{
                     tmp = arr[i];
                     arr[i] = arr[j];
                     arr[j] = tmp;
                     i++;
                 }
             }
         }while(i <= j&&j >= p);
         tmp = arr[i];
         arr[i] = arr[r];
         arr[r] = tmp;
         return i;
     } 

    还有一种非递归的实现,网上搜了许多,似乎只有一种实现方式,摘抄如下:

    template<typename Comparable>
    void quicksort2(vector<Comparable> &vec,int low,int high){
        stack<int> st;
        if(low<high){
            int mid=partition(vec,low,high);
            if(low<mid-1){
                st.push(low);
                st.push(mid-1);
            }
            if(mid+1<high){
                st.push(mid+1);
                st.push(high);
            }
            //其实就是用栈保存每一个待排序子串的首尾元素下标,下一次while循环时取出这个范围,对这段子序列进行partition操作
            while(!st.empty()){
                int q=st.top();
                st.pop();
                int p=st.top();
                st.pop();
                mid=partition(vec,p,q);
                if(p<mid-1){
                    st.push(p);
                    st.push(mid-1);
                }
                if(mid+1<q){
                    st.push(mid+1);
                    st.push(q);
                }       
     }
    


    最后,附上三篇分析快速排序非常棒的文章:

    http://blog.csdn.net/v_july_v/article/details/6116297

    http://blog.csdn.net/v_JULY_v/article/details/6211155

    http://blog.csdn.net/v_JULY_v/article/details/6262915









  • 相关阅读:
    Phalcon资源文件管理(Assets Management)
    LintCode 二叉树的层次遍历 II
    atitit.修复xp 操作系统--重装系统--保留原来文件不丢失
    Matlab图像处理系列2———空间域平滑滤波器
    碰撞回避算法(一) Velocity Obstacle
    APNS 那些事!
    Cordys BOP 4平台开发入门实战演练——Webservices开发(0基础)
    python 下载整个站点
    Nginx+Tomcat+memcached负载均衡实现session共享
    linux系统下安装两个或多个tomcat
  • 原文地址:https://www.cnblogs.com/Harry-Lord/p/4002848.html
Copyright © 2020-2023  润新知