zoukankan      html  css  js  c++  java
  • 从快速排序开始的代码演化

    note: 本文不讨论快速排序的优化。

    最近在温习算法。正好看到快速排序。

    通过3个版本的改进,慢慢加入了template技能。这应该也算是一个收获。

    第一个版本:测试正确性。

    通过比较int的数组排序。

     1 int doSort(int* collection, int left, int right)
     2 {
     3     int    newRight;
     4 
     5     if (left < right) 
     6     {
     7         newRight = doPartition(collection,  left, right);
     8         doSort(collection, left, newRight);
     9         doSort(collection, newRight + 1, right);
    10     }
    11     return 0;
    12 }
    13 
    14 bool FindMidValue( int& exA, int& exB, int& exC,int& result)
    15 {
    16     if(exA>exB)
    17     {
    18         if(exB>exC)
    19         {
    20             result = exB;
    21             return true;
    22         }
    23         if(exA>exC)
    24         {
    25             result = exC;
    26             return true;
    27         }
    28         result = exA;
    29         return true;
    30     }
    31     return false;
    32 
    33 }
    34 
    35 
    36 
    37 void doQueryMidValue(int* collection,int example1,int example2,int example3,int& result)
    38 {
    39     int& exA = collection[example1];
    40     int& exB = collection[example2];
    41     int& exC = collection[example3];
    42 
    43     if(FindMidValue(exA,exB,exC,result)) return; 
    44     if(FindMidValue(exA,exC,exB,result)) return;
    45     if(FindMidValue(exB,exA,exC,result)) return;
    46     if(FindMidValue(exB,exC,exA,result)) return; 
    47     if(FindMidValue(exC,exA,exB,result)) return;
    48     if(FindMidValue(exC,exB,exA,result)) return;        
    49     result = exA;
    50 }
    51 
    52 
    53 int doPartition(int* collection,int left, int right) 
    54 {
    55     int   cmpValue ;
    56     int example1 = (rand() % (right - left + 1)) + left;
    57     int example2 =(rand() % (right - left + 1)) + left;
    58     int example3 = (rand() % (right - left + 1)) + left;        
    59     doQueryMidValue(collection,example1,example2,example3,cmpValue);
    60 
    61     left--;
    62     right++;
    63     while (1) 
    64     {
    65         do 
    66         {
    67             right--;
    68         } while (collection[right] > cmpValue);           
    69 
    70         do 
    71         {
    72             left++;
    73         }while (collection[left] < cmpValue);           
    74 
    75         if (left >= right)
    76         {      
    77             break;
    78         }
    79         else 
    80         {
    81             int nTemp = collection[left];
    82             collection[left] = collection[right];
    83             collection[right] = nTemp;
    84         }
    85     }    
    86     return right;
    87 }
    View Code

    第二个版本:支持泛型。

    如果我要支持string,不能再写一个版本,所以第二版解决数据类型变化的问题。

    同时使用vector代替原始数组。

      1 #include "stdafx.h"
      2 #include <xstddef>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <stdlib.h>
      6 
      7 namespace BSP
      8 {
      9     template<class T>
     10     class QuickSort
     11     {
     12     
     13         
     14     public:
     15         int Sort(std::vector< T >& collection);
     16     private:
     17         int doSort(std::vector< T >& collection,int left, int right);  
     18         int doPartition(std::vector< T >& collection,int left, int right);        
     19         void doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result);
     20         bool FindMidValue( T& exA, T& exB, T& exC,T& result);    
     21     };
     22 
     23 
     24     template<class T>
     25     int QuickSort<T>::Sort(std::vector<T>& collection)
     26     {    
     27         return doSort(collection,0,collection.size()-1);
     28     }
     29 
     30     template<class T>
     31     int QuickSort<T>::doSort(std::vector<T>& collection,int left, int right)
     32     {
     33         int    newRight;
     34 
     35         if (left < right) 
     36         {
     37             newRight = doPartition(collection,  left, right);
     38             doSort(collection, left, newRight);
     39             doSort(collection, newRight + 1, right);
     40         }
     41         return 0;
     42     }
     43 
     44     template<class T>
     45     bool QuickSort<T>::FindMidValue( T& exA, T& exB, T& exC,T& result)
     46     {
     47         if(exA>exB)
     48         {
     49             if(exB>exC)
     50             {
     51                 result = exB;
     52                 return true;
     53             }
     54             if(exA>exC)
     55             {
     56                 result = exC;
     57                 return true;
     58             }
     59             result = exA;
     60             return true;
     61         }
     62         return false;
     63 
     64     }
     65 
     66     template<class T>
     67     void QuickSort<T>::doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result)
     68     {
     69         T& exA = collection[example1];
     70         T& exB = collection[example2];
     71         T& exC = collection[example3];
     72 
     73         if(FindMidValue(exA,exB,exC,result)) return; 
     74         if(FindMidValue(exA,exC,exB,result)) return;
     75         if(FindMidValue(exB,exA,exC,result)) return;
     76         if(FindMidValue(exB,exC,exA,result)) return; 
     77         if(FindMidValue(exC,exA,exB,result)) return;
     78         if(FindMidValue(exC,exB,exA,result)) return;        
     79         result = exA;
     80     }
     81 
     82     template<class T>
     83     int QuickSort<T>::doPartition(std::vector<T>& collection,int left, int right) 
     84     {
     85         T   cmpValue ;
     86         int example1 = (rand() % (right - left + 1)) + left;
     87         int example2 =(rand() % (right - left + 1)) + left;
     88         int example3 = (rand() % (right - left + 1)) + left;        
     89         doQueryMidValue(collection,example1,example2,example3,cmpValue);
     90 
     91         left--;
     92         right++;
     93         while (1) 
     94         {
     95             do 
     96             {
     97                 right--;
     98             } while (m_pfnGreater(collection[right] , cmpValue));           
     99 
    100             do 
    101             {
    102                 left++;
    103             }while (m_pfnLess(collection[left] , cmpValue));           
    104 
    105             if (left >= right)
    106             {      
    107                 break;
    108             }
    109             else 
    110             {
    111                 std::swap(collection[left],collection[right]);            
    112             }
    113         }    
    114         return right;
    115     }
    116 }
    View Code

    第二个版本b:支持自定义的结构。

    基础类型int,stl的类型string都内建比较函数。所以可以直接比较。

    但自定义的类型,编译器就无法识别了。

    第二个版本不动,自定义的结构需要重载operator 。

     1 typedef struct Student
     2 {
     3     std::string name;
     4     int         year;      
     5 
     6     bool operator > (const struct Student& dst) const
     7     {
     8         printf("ref greater 
    ");
     9         return this->year > dst.year;
    10     }
    11 
    12     bool operator < (const struct Student& dst) const
    13     {
    14         printf("ref less 
    ");
    15         return this->year < dst.year;
    16     }
    17 } Student;
    View Code

    第三个版本:支持shared_Ptr。

    之前的版本需要存放实体,这个对于性能有很大影响。

    于是引入了shared_ptr。但这时比较函数进行的是shared_ptr的比较,并不是实际对象的比较。

    所以需要增加自定义的比较函数。

    首先需要提供默认的比较函数对象。这样默认类型就不用强制设置了。

      1  template<class T
      2         ,class _qsLess = std::less<T>,class _qsGreater = std::greater<T>>
      3      
      4     class QuickSort   
      5     {
      6     public:
      7         explicit QuickSort<T,_qsLess,_qsGreater>()
      8         {
      9             m_pfnLess = _qsLess();
     10             m_pfnGreater = _qsGreater();
     11         }       
     12     public:
     13         int Sort(std::vector< T >& collection);
     14     private:
     15         int doSort(std::vector< T >& collection,int left, int right);  
     16         int doPartition(std::vector< T >& collection,int left, int right);        
     17         void doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result);
     18         bool FindMidValue( T& exA, T& exB, T& exC,T& result);
     19     private:
     20         _qsLess    m_pfnLess;
     21         _qsGreater  m_pfnGreater;
     22     };
     23 
     24 
     25     template<class T,class _qsLess ,class _qsGreater>
     26     int QuickSort<T,_qsLess,_qsGreater>::Sort(std::vector<T>& collection)
     27     {    
     28         return doSort(collection,0,collection.size()-1);
     29     }
     30 
     31     template<class T,class _qsLess ,class _qsGreater>
     32     int QuickSort<T,_qsLess,_qsGreater>::doSort(std::vector<T>& collection,int left, int right)
     33     {
     34         int    newRight;
     35 
     36         if (left < right) 
     37         {
     38             newRight = doPartition(collection,  left, right);
     39             doSort(collection, left, newRight);
     40             doSort(collection, newRight + 1, right);
     41         }
     42         return 0;
     43     }
     44 
     45     template<class T,class _qsLess ,class _qsGreater>
     46     bool QuickSort<T,_qsLess,_qsGreater>::FindMidValue( T& exA, T& exB, T& exC,T& result)
     47     {
     48         if(m_pfnGreater(exA,exB))
     49         {
     50             if(m_pfnGreater(exB,exC))
     51             {
     52                 result = exB;
     53                 return true;
     54             }
     55             if(m_pfnGreater(exA,exC))
     56             {
     57                 result = exC;
     58                 return true;
     59             }
     60             result = exA;
     61             return true;
     62         }
     63         return false;
     64 
     65     }
     66 
     67     template<class T,class _qsLess ,class _qsGreater>
     68     void QuickSort<T,_qsLess,_qsGreater>::doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result)
     69     {
     70         T& exA = collection[example1];
     71         T& exB = collection[example2];
     72         T& exC = collection[example3];
     73 
     74         if(FindMidValue(exA,exB,exC,result)) return; 
     75         if(FindMidValue(exA,exC,exB,result)) return;
     76         if(FindMidValue(exB,exA,exC,result)) return;
     77         if(FindMidValue(exB,exC,exA,result)) return; 
     78         if(FindMidValue(exC,exA,exB,result)) return;
     79         if(FindMidValue(exC,exB,exA,result)) return;        
     80         result = exA;
     81     }
     82 
     83     template<class T,class _qsLess ,class _qsGreater>
     84     int QuickSort<T,_qsLess,_qsGreater>::doPartition(std::vector<T>& collection,int left, int right) 
     85     {
     86         T   cmpValue ;
     87         int example1 = (rand() % (right - left + 1)) + left;
     88         int example2 =(rand() % (right - left + 1)) + left;
     89         int example3 = (rand() % (right - left + 1)) + left;        
     90         doQueryMidValue(collection,example1,example2,example3,cmpValue);
     91         
     92         left--;
     93         right++;
     94         while (1) 
     95         {
     96             do 
     97             {
     98                 right--;
     99             }while (m_pfnGreater(collection[right] , cmpValue));
    100             do 
    101             {
    102                 left++;
    103             }while (m_pfnLess(collection[left] , cmpValue));
    104             if (left >= right) 
    105             { 
    106                break; 
    107             } 
    108             else 
    109             { 
    110                 std::swap(collection[left],collection[right]); 
    111             }
    112         } 
    113         return right; 
    114 }
    View Code

    对于使用者,需要增加比较函数的实现。 

     1 struct StudentPtrLess:public std::binary_function<StudentPtr, StudentPtr, bool>
     2     {
     3         bool operator () (  StudentPtr& src,  StudentPtr& dst) 
     4         {   
     5             if(src == false) return true;
     6             if(dst == false) return false;
     7             return *(src.get()) < *(dst.get());
     8         }
     9     };
    10 
    11     struct StudentPtrGreater:public std::binary_function<StudentPtr, StudentPtr, bool>
    12     {
    13         bool operator () (  StudentPtr& src,  StudentPtr& dst) 
    14         {
    15             if(src == false) return false;
    16             if(dst == false) return true;
    17             return *(src.get()) > *(dst.get());
    18         }
    19     };
    20 
    21     BSP::QuickSort< StudentPtr ,StudentPtrLess , StudentPtrGreater> qsStudentPtr;
    View Code
    
    
  • 相关阅读:
    ORACLE中dba,user,v$等开头的常用表和视图
    CentOS最基本的20个常用命令
    Spring IOC原理解读 面试必读
    Nginx Web服务应用
    Linux系统SSH免密登录
    Zabbix+Grafana打造高逼格监控系统
    Ansible入门
    你应该知道的 5 个 Docker 工具
    关于 Docker Hub 上不能注册 Docker ID 的问题
    Linux下终端录制工具-asciinema
  • 原文地址:https://www.cnblogs.com/febwave/p/4421792.html
Copyright © 2011-2022 走看看