数据结构-各种排序算法

实现:

  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 }
原文地址:https://www.cnblogs.com/dracohan/p/3798344.html