从快速排序开始的代码演化

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

原文地址:https://www.cnblogs.com/febwave/p/4421792.html