1 / 16

Chapter 5 Sorting

Chapter 5 Sorting. There are several easy algorithms to sort in O( N 2 ), such as insertion sort. There is an algorithm, Shellsort, that is very simple to code, run in o( N 2 ), and is efficient in practice. There are slightly more complicated O( N log N ) sorting algorithms.

zuri
Download Presentation

Chapter 5 Sorting

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 5Sorting There are several easy algorithms to sort in O(N2), such as insertion sort. There is an algorithm, Shellsort, that is very simple to code, run in o(N2), and is efficient in practice. There are slightly more complicated O(N log N) sorting algorithms. Any general-purpose sorting algorithm requires (N log N) comparisons.

  2. 7.2 Insertion Sort Fig. 7.1 Insertion sort after each pass void InsertionSort( ElementType A[ ], int N ) { int j, P; ElementType Tmp; /* 1*/ for( P = 1; P < N; P++ ) { /* 2*/ Tmp = A[ P ]; /* 3*/ for( j = P; j > 0 && A[ j - 1 ] > Tmp; j-- ) /* 4*/ A[ j ] = A[ j - 1 ]; /* 5*/ A[ j ] = Tmp; } } Fig. 7.2 Insertion sort routine

  3. 7.3 The Lower Bound for Simple Sorting Algorithms • Theorem 7.1 The average number of insertions in an array of N distince numbers is N(N-1)/4. • Theorem 7.2 Any algorithm that sorts by exchangeing adjacent elements requires (N2) time on average.

  4. 7.4 Shellsort Fig. 7.3 Shellsort after each pass void Shellsort( ElementType A[ ], int N ) { int i, j, Increment; ElementType Tmp; /* 1*/ for( Increment = N / 2; Increment > 0; Increment /= 2 ) /* 2*/ for( i = Increment; i < N; i++ ) { /* 3*/ Tmp = A[ i ]; /* 4*/ for( j = i; j >= Increment; j -= Increment ) /* 5*/ if( Tmp < A[ j - Increment ] ) /* 6*/ A[ j ] = A[ j - Increment ]; else /* 7*/ break; /* 8*/ A[ j ] = Tmp; } } Fig. 7.3 Shellsort routine using Shell’s increments (better increments are Possible)

  5. 7.4.1 Worst-Case Analysis of Shellsort • Theorem 7.3 The worst-case running time of Shellsort, using Shell’s increments, is (N2). • Theorem 7.4 The worst-case running time of Shellsort, using Hibbard’s increments, is (N3/2). Fig 7.5 Bad case for Shellsort with Shell’s increments (positions are numbered 1 to 16)

  6. 7.5 Heapsort Fig. 7.6 (Max) heap after BuildHeap phase Fig. 7.7 Heap after first DeleteMax

  7. void Heapsort( ElementType A[ ], int N ) { int i; /* 1*/ for( i = N / 2; i >= 0; i-- ) /* BuildHeap */ /* 2*/ PercDown( A, i, N ); /* 3*/ for( i = N - 1; i > 0; i-- ) { /* 4*/ Swap( &A[ 0 ], &A[ i ] ); /* DeleteMax */ /* 5*/ PercDown( A, 0, i ); } } #define LeftChild( i ) ( 2 * ( i ) + 1 ) void PercDown( ElementType A[ ], int i, int N ) { int Child; ElementType Tmp; /* 1*/ for( Tmp = A[ i ]; LeftChild( i ) < N; i = Child ) { /* 2*/ Child = LeftChild( i ); /* 3*/ if( Child != N - 1 && A[ Child + 1 ] > A[ Child ] ) /* 4*/ Child++; /* 5*/ if( Tmp < A[ Child ] ) /* 6*/ A[ i ] = A[ Child ]; else /* 7*/ break; } /* 8*/ A[ i ] =Tmp; } Fig. 7.8 Heapsort

  8. 7.5.1 Analysis of Heapsort • Theorem 7.5 The average number of comparisons used to heapsort a random permutation of N distinct items is 2N logN - O(N loglog N).

  9. 7.6 Mergesort void Mergesort( ElementType A[ ], int N ) { ElementType *TmpArray; TmpArray = malloc( N * sizeof( ElementType ) ); if( TmpArray != NULL ) { MSort( A, TmpArray, 0, N - 1 ); free( TmpArray ); } else FatalError( "No space for tmp array!!!" ); } void MSort( ElementType A[ ], ElementType TmpArray[ ], int Left, int Right ) { int Center; if( Left < Right ) { Center = ( Left + Right ) / 2; MSort( A, TmpArray, Left, Center ); MSort( A, TmpArray, Center + 1, Right ); Merge( A, TmpArray, Left, Center + 1, Right ); } } Fig. 7.9 Mergesort routine

  10. /* Lpos = start of left half, Rpos = start of right half */ void Merge( ElementType A[ ], ElementType TmpArray[ ], int Lpos, int Rpos, int RightEnd ) { int i, LeftEnd, NumElements, TmpPos; LeftEnd = Rpos - 1; TmpPos = Lpos; NumElements = RightEnd - Lpos + 1; /* main loop */ while( Lpos <= LeftEnd && Rpos <= RightEnd ) if( A[ Lpos ] <= A[ Rpos ] ) TmpArray[ TmpPos++ ] = A[ Lpos++ ]; else TmpArray[ TmpPos++ ] = A[ Rpos++ ]; while( Lpos <= LeftEnd ) /* Copy rest of first half */ TmpArray[ TmpPos++ ] = A[ Lpos++ ]; while( Rpos <= RightEnd ) /* Copy rest of second half */ TmpArray[ TmpPos++ ] = A[ Rpos++ ]; /* Copy TmpArray back */ for( i = 0; i < NumElements; i++, RightEnd-- ) A[ RightEnd ] = TmpArray[ RightEnd ]; } Fig. 7.10 Merge routine

  11. 7.7 Quicksort Fig. 7.11 The steps of quicksort Illustrated by example

  12. 7.7.4 Actual Quicksort Routine void Quicksort( ElementType A[ ], int N ) { Qsort( A, 0, N - 1 ); } /* Return median of Left, Center, and Right */ /* Order these and hide the pivot */ ElementType Median3( ElementType A[ ], int Left, int Right ) { int Center = ( Left + Right ) / 2; if( A[ Left ] > A[ Center ] ) Swap( &A[ Left ], &A[ Center ] ); if( A[ Left ] > A[ Right ] ) Swap( &A[ Left ], &A[ Right ] ); if( A[ Center ] > A[ Right ] ) Swap( &A[ Center ], &A[ Right ] ); /* Invariant: A[ Left ] <= A[ Center ] <= A[ Right ] */ Swap( &A[ Center ], &A[ Right - 1 ] ); /* Hide pivot */ return A[ Right - 1 ]; /* Return pivot */ } Fig. 7.12 Driver for quicksort Fig. 7.13 Code to perform median-of-three partitioning

  13. #define Cutoff ( 3 ) void Qsort( ElementType A[ ], int Left, int Right ) { int i, j; ElementType Pivot; /* 1*/ if( Left + Cutoff <= Right ) { /* 2*/ Pivot = Median3( A, Left, Right ); /* 3*/ i = Left; j = Right - 1; /* 4*/ for( ; ; ) { /* 5*/ while( A[ ++i ] < Pivot ){ } /* 6*/ while( A[ --j ] > Pivot ){ } /* 7*/ if( i < j ) /* 8*/ Swap( &A[ i ], &A[ j ] ); else /* 9*/ break; } /*10*/ Swap( &A[ i ], &A[ Right - 1 ] ); /* Restore pivot */ /*11*/ Qsort( A, Left, i - 1 ); /*12*/ Qsort( A, i + 1, Right ); } else /* Do an insertion sort on the subarray */ /*13*/ InsertionSort( A + Left, Right - Left + 1 ); } Fig. 7.14 Main quicksort routine /* 3*/ i = Left + 1; j = Right - 2; /* 4*/ for( ; ; ) { /* 5*/ while( A[ i ] < Pivot ) i++; /* 6*/ while( A[ j ] > Pivot ) j--; /* 7*/ if( i < j ) /* 8*/ Swap( &A[ i ], &A[ j ] ); else /* 9*/ break; } Fig. 7.15 A small change to quicksort, which breaks the algorithm

  14. /* Places the kth smallest element in the kth position */ /* Because arrays start at 0, this will be index k-1 */ void Qselect( ElementType A[ ], int k, int Left, int Right ) { int i, j; ElementType Pivot; /* 1*/ if( Left + Cutoff <= Right ) { /* 2*/ Pivot = Median3( A, Left, Right ); /* 3*/ i = Left; j = Right - 1; /* 4*/ for( ; ; ) { /* 5*/ while( A[ ++i ] < Pivot ){ } /* 6*/ while( A[ --j ] > Pivot ){ } /* 7*/ if( i < j ) /* 8*/ Swap( &A[ i ], &A[ j ] ); else /* 9*/ break; } /*10*/ Swap( &A[ i ], &A[ Right - 1 ] ); /* Restore pivot */ /*11*/ if( k <= i ) /*12*/ Qselect( A, k, Left, i - 1 ); /*13*/ else if( k > i + 1 ) /*14*/ Qselect( A, k, i + 1, Right ); } else /* Do an insertion sort on the subarray */ /*15*/ InsertionSort( A + Left, Right - Left + 1 ); } 7.7.6 A Linear-Expected-Time Algorithm for Selection Fig. 7.16 Main quickselect routine

  15. 7.9 A General Lower Bound for Sorting Decision Trees Fig. 7.17 A decision tree for three-element sort

  16. Summary

More Related