• 数据结构-各种排序算法


    实现:

      1 #ifndef SORT_H
      2 #define SORT_H
      3 
      4 /**
      5  * Several sorting routines.
      6  * Arrays are rearranged with smallest item first.
      7  */
      8 
      9 #include <vector>
     10 #include <functional>
     11 using namespace std;
     12 
     13 /**
     14  * Simple insertion sort.
     15  * O(N^2)
     16  */
     17 template <typename Comparable>
     18 void insertionSort( vector<Comparable> & a )
     19 {
     20     for( int p = 1; p < a.size( ); p++ )
     21     {
     22         Comparable tmp = a[ p ];
     23 
     24         int j;
     25         for( j = p; j > 0 && tmp < a[ j - 1 ]; j-- )
     26             a[ j ] = a[ j - 1 ];
     27         a[ j ] = tmp;
     28     }
     29 }
     30 
     31 /**
     32  * Shellsort, using Shell's (poor) increments.
     33  */
     34 template <typename Comparable>
     35 void shellsort( vector<Comparable> & a )
     36 {
     37     for( int gap = a.size( ) / 2; gap > 0; gap /= 2 )
     38         for( int i = gap; i < a.size( ); i++ )
     39         {
     40             Comparable tmp = a[ i ];
     41             int j = i;
     42 
     43             for( ; j >= gap && tmp < a[ j - gap ]; j -= gap )
     44                 a[ j ] = a[ j - gap ];
     45             a[ j ] = tmp;
     46         }
     47 }
     48 
     49 /**
     50  * Standard heapsort.
     51  */
     52 template <typename Comparable>
     53 void heapsort( vector<Comparable> & a )
     54 {
     55     for( int i = a.size( ) / 2; i >= 0; i-- )  /* buildHeap */
     56         percDown( a, i, a.size( ) );
     57     for( int j = a.size( ) - 1; j > 0; j-- )
     58     {
     59         swap( a[ 0 ], a[ j ] );                  /* deleteMax */
     60         percDown( a, 0, j );
     61     }
     62 }
     63 
     64 /**
     65  * Internal method for heapsort.
     66  * i is the index of an item in the heap.
     67  * Returns the index of the left child.
     68  */
     69 inline int leftChild( int i )
     70 {
     71     return 2 * i + 1;
     72 }
     73 
     74 /**
     75  * Internal method for heapsort that is used in
     76  * deleteMax and buildHeap.
     77  * i is the position from which to percolate down.
     78  * n is the logical size of the binary heap.
     79  */
     80 template <typename Comparable>
     81 void percDown( vector<Comparable> & a, int i, int n )
     82 {
     83     int child;
     84     Comparable tmp;
     85 
     86     for( tmp = a[ i ]; leftChild( i ) < n; i = child )
     87     {
     88         child = leftChild( i );
     89         if( child != n - 1 && a[ child ] < a[ child + 1 ] )
     90             child++;
     91         if( tmp < a[ child ] )
     92             a[ i ] = a[ child ];
     93         else
     94             break;
     95     }
     96     a[ i ] = tmp;
     97 }
     98 
     99 /**
    100  * Mergesort algorithm (driver).
    101  */
    102 template <typename Comparable>
    103 void mergeSort( vector<Comparable> & a )
    104 {
    105     vector<Comparable> tmpArray( a.size( ) );
    106 
    107     mergeSort( a, tmpArray, 0, a.size( ) - 1 );
    108 }
    109 
    110 /**
    111  * Internal method that makes recursive calls.
    112  * a is an array of Comparable items.
    113  * tmpArray is an array to place the merged result.
    114  * left is the left-most index of the subarray.
    115  * right is the right-most index of the subarray.
    116  */
    117 template <typename Comparable>
    118 void mergeSort( vector<Comparable> & a,
    119             vector<Comparable> & tmpArray, int left, int right )
    120 {
    121     if( left < right )
    122     {
    123         int center = ( left + right ) / 2;
    124         mergeSort( a, tmpArray, left, center );
    125         mergeSort( a, tmpArray, center + 1, right );
    126         merge( a, tmpArray, left, center + 1, right );
    127     }
    128 }
    129 
    130 /**
    131  * Internal method that merges two sorted halves of a subarray.
    132  * a is an array of Comparable items.
    133  * tmpArray is an array to place the merged result.
    134  * leftPos is the left-most index of the subarray.
    135  * rightPos is the index of the start of the second half.
    136  * rightEnd is the right-most index of the subarray.
    137  */
    138 template <typename Comparable>
    139 void merge( vector<Comparable> & a, vector<Comparable> & tmpArray,
    140         int leftPos, int rightPos, int rightEnd )
    141 {
    142     int leftEnd = rightPos - 1;
    143     int tmpPos = leftPos;
    144     int numElements = rightEnd - leftPos + 1;
    145 
    146     // Main loop
    147     while( leftPos <= leftEnd && rightPos <= rightEnd )
    148         if( a[ leftPos ] <= a[ rightPos ] )
    149             tmpArray[ tmpPos++ ] = a[ leftPos++ ];
    150         else
    151             tmpArray[ tmpPos++ ] = a[ rightPos++ ];
    152 
    153     while( leftPos <= leftEnd )    // Copy rest of first half
    154         tmpArray[ tmpPos++ ] = a[ leftPos++ ];
    155 
    156     while( rightPos <= rightEnd )  // Copy rest of right half
    157         tmpArray[ tmpPos++ ] = a[ rightPos++ ];
    158 
    159     // Copy tmpArray back
    160     for( int i = 0; i < numElements; i++, rightEnd-- )
    161         a[ rightEnd ] = tmpArray[ rightEnd ];
    162 }
    163 
    164 /**
    165  * Quicksort algorithm (driver).
    166  */
    167 template <typename Comparable>
    168 void quicksort( vector<Comparable> & a )
    169 {
    170     quicksort( a, 0, a.size( ) - 1 );
    171 }
    172 
    173 
    174 /**
    175  * Return median of left, center, and right.
    176  * Order these and hide the pivot.
    177  */
    178 template <typename Comparable>
    179 const Comparable & median3( vector<Comparable> & a, int left, int right )
    180 {
    181     int center = ( left + right ) / 2;
    182     if( a[ center ] < a[ left ] )
    183         swap( a[ left ], a[ center ] );
    184     if( a[ right ] < a[ left ] )
    185         swap( a[ left ], a[ right ] );
    186     if( a[ right ] < a[ center ] )
    187         swap( a[ center ], a[ right ] );
    188 
    189         // Place pivot at position right - 1
    190     swap( a[ center ], a[ right - 1 ] );
    191     return a[ right - 1 ];
    192 }
    193 
    194 /**
    195  * Internal quicksort method that makes recursive calls.
    196  * Uses median-of-three partitioning and a cutoff of 10.
    197  * a is an array of Comparable items.
    198  * left is the left-most index of the subarray.
    199  * right is the right-most index of the subarray.
    200  */
    201 template <typename Comparable>
    202 void quicksort( vector<Comparable> & a, int left, int right )
    203 {
    204     if( left + 10 <= right )
    205     {
    206         Comparable pivot = median3( a, left, right );
    207 
    208             // Begin partitioning
    209         int i = left, j = right - 1;
    210         for( ; ; )
    211         {
    212             while( a[ ++i ] < pivot ) { }
    213             while( pivot < a[ --j ] ) { }
    214             if( i < j )
    215                 swap( a[ i ], a[ j ] );
    216             else
    217                 break;
    218         }
    219 
    220         swap( a[ i ], a[ right - 1 ] );  // Restore pivot
    221 
    222         quicksort( a, left, i - 1 );     // Sort small elements
    223         quicksort( a, i + 1, right );    // Sort large elements
    224     }
    225     else  // Do an insertion sort on the subarray
    226         insertionSort( a, left, right );
    227 }
    228 
    229 /**
    230  * Internal insertion sort routine for subarrays
    231  * that is used by quicksort.
    232  * a is an array of Comparable items.
    233  * left is the left-most index of the subarray.
    234  * right is the right-most index of the subarray.
    235  */
    236 template <typename Comparable>
    237 void insertionSort( vector<Comparable> & a, int left, int right )
    238 {
    239     for( int p = left + 1; p <= right; p++ )
    240     {
    241         Comparable tmp = a[ p ];
    242         int j;
    243 
    244         for( j = p; j > left && tmp < a[ j - 1 ]; j-- )
    245             a[ j ] = a[ j - 1 ];
    246         a[ j ] = tmp;
    247     }
    248 }
    249 
    250 /**
    251  * Quick selection algorithm.
    252  * Places the kth smallest item in a[k-1].
    253  * a is an array of Comparable items.
    254  * k is the desired rank (1 is minimum) in the entire array.
    255  */
    256 template <typename Comparable>
    257 void quickSelect( vector<Comparable> & a, int k )
    258 {
    259     quickSelect( a, 0, a.size( ) - 1, k );
    260 }
    261 
    262 
    263 /**
    264  * Internal selection method that makes recursive calls.
    265  * Uses median-of-three partitioning and a cutoff of 10.
    266  * Places the kth smallest item in a[k-1].
    267  * a is an array of Comparable items.
    268  * left is the left-most index of the subarray.
    269  * right is the right-most index of the subarray.
    270  * k is the desired rank (1 is minimum) in the entire array.
    271  */
    272 template <typename Comparable>
    273 void quickSelect( vector<Comparable> & a, int left, int right, int k )
    274 {
    275     if( left + 10 <= right )
    276     {
    277         Comparable pivot = median3( a, left, right );
    278 
    279             // Begin partitioning
    280         int i = left, j = right - 1;
    281         for( ; ; )
    282         {
    283             while( a[ ++i ] < pivot ) { }
    284             while( pivot < a[ --j ] ) { }
    285             if( i < j )
    286                 swap( a[ i ], a[ j ] );
    287             else
    288                 break;
    289         }
    290 
    291         swap( a[ i ], a[ right - 1 ] );  // Restore pivot
    292 
    293             // Recurse; only this part changes
    294         if( k <= i )
    295             quickSelect( a, left, i - 1, k );
    296         else if( k > i + 1 )
    297             quickSelect( a, i + 1, right, k );
    298     }
    299     else  // Do an insertion sort on the subarray
    300         insertionSort( a, left, right );
    301 }
    302 
    303 /**
    304  * Class that wraps a pointer variable.
    305  */
    306 template <typename Comparable>
    307 class Pointer
    308 {
    309   public:
    310     Pointer( Comparable *rhs = NULL ) : pointee( rhs ) { }
    311 
    312     bool operator<( const Pointer & rhs ) const
    313         { return *pointee < *rhs.pointee; }
    314 
    315     operator Comparable * ( ) const
    316         { return pointee; }
    317   private:
    318     Comparable *pointee;
    319 };
    320 
    321 /**
    322  * Sort objects -- even large ones --
    323  * with only N + ln N Comparable moves on average.
    324  */
    325 template <typename Comparable>
    326 void largeObjectSort( vector<Comparable> & a )
    327 {
    328     vector<Pointer<Comparable> > p( a.size( ) );
    329     int i, j, nextj;
    330 
    331     for( i = 0; i < a.size( ); i++ )
    332         p[ i ] = &a[ i ];
    333 
    334     quicksort( p );
    335 
    336         // Shuffle items in place
    337     for( i = 0; i < a.size( ); i++ )
    338         if( p[ i ] != &a[ i ] )
    339         {
    340             Comparable tmp = a[ i ];
    341             for( j = i; p[ j ] != &a[ i ]; j = nextj )
    342             {
    343                 nextj = p[ j ] - &a[ 0 ];
    344                 a[ j ] = *p[ j ];
    345                 p[ j ] = &a[ j ];
    346             }
    347             a[ j ] = tmp;
    348             p[ j ] = &a[ j ];
    349         }
    350 }
    351 
    352 /*
    353  * This is the guts of the generic insertion sort routine.
    354  * It is logically a private routine.
    355  * It requires a beginning and ending iterator,
    356  * a comparison function object,
    357  * and a dummy parameter that is used to establish
    358  * the type of objects that are in the container.
    359  */
    360 template <typename RandomIterator, typename Comparator, typename Object>
    361 void insertionSort( const RandomIterator & begin,
    362                     const RandomIterator & end,
    363                     Comparator lessThan,
    364                     const Object & obj )
    365 {
    366     RandomIterator j;
    367 
    368     for( RandomIterator p = begin+1; p != end; ++p )
    369     {
    370         Object tmp = *p;
    371         for( j = p; j != begin && lessThan( tmp, *( j-1 ) ); --j )
    372             *j = *(j-1);
    373         *j = tmp;
    374     }
    375 }
    376 
    377 /*
    378  * This is the more public version of insertion sort.
    379  * It requires a pair of iterators and a comparison
    380  * function object. It calls the four parameter version
    381  * by sending *begin as the additional parameter.
    382  * The template expansion will allow the routine
    383  * above to then deduce Object, on the basis of *begin.
    384  */
    385 template <typename RandomIterator, typename Comparator>
    386 void insertionSort( const RandomIterator & begin,
    387                     const RandomIterator & end,
    388                     Comparator lessThan )
    389 {
    390     if( begin != end )
    391         insertionSort( begin, end, lessThan, *begin );
    392 }
    393 
    394 /*
    395  * The two-parameter version logically would call
    396  * the three parameter version, and send in a
    397  * default function object. The function object
    398  * would be less<Object>, but what is Object?
    399  * We don't know, so we pass *begin to another
    400  * version of insertionSort to deduce it.
    401  */
    402 template <typename RandomIterator>
    403 void insertionSort( const RandomIterator & begin,
    404                     const RandomIterator & end )
    405 {
    406     if( begin != end )
    407         insertionSortHelp( begin, end, *begin );
    408 }
    409 
    410 /*
    411  * The three-parameter helper
    412  * uses Object to construct less<Object>, and
    413  * calls the three-parameter version of insertionSort.
    414  */
    415 template <typename RandomIterator, typename Object>
    416 void insertionSortHelp( const RandomIterator & begin,
    417                         const RandomIterator & end,
    418                         const Object & obj )
    419 {
    420     insertionSort( begin, end, less<Object>( ) );
    421 }
    422 
    423 
    424 #endif

    测试:

     1 #include <iostream>
     2 #include "Sort.h"
     3 #include <vector>
     4 #include "Random.h"
     5 
     6 using namespace std;
     7 
     8 void checkSort( const vector<int> & a )
     9 {
    10     for( int i = 0; i < a.size( ); i++ )
    11         if( a[ i ] != i )
    12             cout << "Error at " << i << endl;
    13     cout << "Finished checksort" << endl;
    14 }
    15 
    16 
    17 void permute( vector<int> & a )
    18 {
    19     static Random r;
    20 
    21     for( int j = 1; j < a.size( ); j++ )
    22         swap( a[ j ], a[ r.randomInt( 0, j ) ] );
    23 }
    24 
    25 
    26 int main( )
    27 {
    28     const int NUM_ITEMS = 1000;
    29 
    30     vector<int> a( NUM_ITEMS );
    31     for( int i = 0; i < a.size( ); i++ )
    32         a[ i ] = i;
    33 
    34     for( int theSeed = 0; theSeed < 20; theSeed++ )
    35     {
    36         permute( a );
    37         insertionSort( a );
    38         checkSort( a );
    39 
    40         permute( a );
    41         insertionSort( a.begin( ), a.end( ) );
    42         checkSort( a );
    43 
    44         permute( a );
    45         heapsort( a );
    46         checkSort( a );
    47 
    48         permute( a );
    49         shellsort( a );
    50         checkSort( a );
    51 
    52         permute( a );
    53         mergeSort( a );
    54         checkSort( a );
    55 
    56         permute( a );
    57         quicksort( a );
    58         checkSort( a );
    59 
    60         permute( a );
    61         largeObjectSort( a );
    62         checkSort( a );
    63 
    64         permute( a );
    65         quickSelect( a, NUM_ITEMS / 2 );
    66         cout << a[ NUM_ITEMS / 2 - 1 ] << " " << NUM_ITEMS / 2 << endl;
    67     }
    68 
    69     return 0;
    70 }
  • 相关阅读:
    VC++中字符串编码的转换
    C与C++之间相互调用
    获取Windows下某进程监听的TCP/UDP端口
    C# byte数组与Image的相互转换
    C# IP地址与整数之间的转换
    NPOI读写Excel
    C#调用ArcGIS REST服务
    粗俗易懂的了解一下PHP的垃圾回收机制(好文章-转)
    从悲观锁和乐观锁的角度怎么避免死锁
    百度地图分布图(百度地图api司机位置实时定位分布图)
  • 原文地址:https://www.cnblogs.com/dracohan/p/3798344.html
Copyright © 2020-2023  润新知