231 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* s4quick.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved.
 | |
| 
 | |
|    Iterative Quick Sort Algorithm
 | |
| 
 | |
|    This algorithm is superior to the more traditional recursive
 | |
|    Quick Sort as the worst case stack size is proportional to 'log(n)'.
 | |
|    In this algorithm the stack is explicitly maintained.
 | |
| 
 | |
|    In the recursive algorithm, the worst case depth of recursion is
 | |
|    proportional to 'n'.  For example, if there were 1000 items to
 | |
|    sort, the Quick Sort could, in the worst case, call itself
 | |
|    1000 times.
 | |
| 
 | |
|    This routine assumes that there is a record number after the sort
 | |
|    data for final comparison resolutions in case that two keys are the same.
 | |
| */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static void **pointers ;
 | |
| static int nPointers ;
 | |
| static int sortLen ;
 | |
| static S4CMP_FUNCTION *cmp ;
 | |
| 
 | |
| static int sort( void ) ;
 | |
| 
 | |
| int s4quick( void **p, const int pN, S4CMP_FUNCTION *cmpRoutine, const int width )
 | |
| {
 | |
|    cmp = cmpRoutine ;
 | |
|    pointers = p ;
 | |
|    nPointers = pN ;
 | |
|    sortLen = width ;
 | |
|    if ( pN > 0 )
 | |
|       return sort() ;
 | |
|    else
 | |
|       return 0 ;
 | |
| }
 | |
| 
 | |
| static int sort( void )
 | |
| {
 | |
|    /* A stack size of 32 is enough to sort four billion items. */
 | |
|    int stackStart[32], stackEnd[32], stackOn ;
 | |
|    int f, l, i, j, k, middle, rc ;
 | |
|    void *flip_data ;
 | |
|    long l1, l2 ;
 | |
| 
 | |
|    stackOn = 0 ;
 | |
|    stackStart[0] = 0 ;
 | |
|    stackEnd[0] = nPointers - 1 ;
 | |
| 
 | |
|    while( stackOn >= 0 )
 | |
|    {
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( ( stackOn > sizeof( stackStart ) / sizeof( int ) ) || stackOn < 0  )
 | |
|             return error4( 0, e4info, E81801 ) ;
 | |
|       #endif
 | |
| 
 | |
|       f = stackStart[stackOn] ;
 | |
|       l = stackEnd[stackOn] ;
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( f >= nPointers || l >= nPointers || f < 0 || l < 0 )
 | |
|             error4( 0, e4info, E81801 ) ;
 | |
|       #endif
 | |
|       stackOn-- ;
 | |
| 
 | |
|       while( l-f > 7 )
 | |
|       {
 | |
|          /* use fast-pivot method to find best partition */
 | |
|          middle = ( l + f ) / 2 ;
 | |
|          #ifdef E4ANALYZE
 | |
|             if ( middle >= nPointers || middle < 0 )
 | |
|                error4( 0, e4info, E81801 ) ;
 | |
|          #endif
 | |
| 
 | |
|          /* rc = greater( middle, l ) ; */
 | |
|          rc = (*cmp)( pointers[middle], pointers[l], (unsigned int)sortLen ) ;
 | |
|          if ( rc == 0 )
 | |
|          {
 | |
|             memcpy( (void *)&l1, ((char *)pointers[middle])+sortLen, sizeof(long) ) ;
 | |
|             memcpy( (void *)&l2, ((char *)pointers[l])+sortLen, sizeof(long) ) ;
 | |
|             rc = (l1 > l2) ? 1 : 0 ;
 | |
|          }
 | |
|          if ( rc > 0 )
 | |
|          {
 | |
|             /* rc = flip( middle, l ) ; */
 | |
|             flip_data  = pointers[middle] ;
 | |
|             pointers[middle] = pointers[l] ;
 | |
|             pointers[l] = flip_data ;
 | |
|          }
 | |
| 
 | |
|          /* rc = greater( middle, f ) ; */
 | |
|          rc = (*cmp)( pointers[middle], pointers[f], (unsigned int)sortLen ) ;
 | |
|          if ( rc == 0 )
 | |
|          {
 | |
|             memcpy( (void *)&l1, ((char *)pointers[middle])+sortLen, sizeof(long) ) ;
 | |
|             memcpy( (void *)&l2, ((char *)pointers[f])+sortLen, sizeof(long) ) ;
 | |
|             rc = (l1 > l2) ? 1 : 0 ;
 | |
|          }
 | |
|          if ( rc > 0 )
 | |
|          {
 | |
|             /* rc = flip( f, middle ) ; */
 | |
|             flip_data  = pointers[f] ;
 | |
|             pointers[f] = pointers[middle] ;
 | |
|             pointers[middle] = flip_data ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             /* rc = greater( f, l ) ; */
 | |
|             rc = (*cmp)( pointers[f], pointers[l], (unsigned int)sortLen ) ;
 | |
|             if ( rc == 0 )
 | |
|             {
 | |
|                memcpy( (void *)&l1, ((char *)pointers[f])+sortLen, sizeof(long) ) ;
 | |
|                memcpy( (void *)&l2, ((char *)pointers[l])+sortLen, sizeof(long) ) ;
 | |
|                rc = (l1 > l2) ? 1 : 0 ;
 | |
|             }
 | |
|             if ( rc > 0 )
 | |
|             {
 | |
|                /* rc = flip( f , l ) ; */
 | |
|                flip_data  = pointers[f] ;
 | |
|                pointers[f] = pointers[l] ;
 | |
|                pointers[l] = flip_data ;
 | |
|             }
 | |
|          }
 | |
| 
 | |
|          /* arrange elements around the partition */
 | |
|          i = f ;
 | |
|          j = l ;
 | |
|          for( ;; )
 | |
|          {
 | |
|             do
 | |
|             {
 | |
|                i++ ;
 | |
|                #ifdef E4ANALYZE
 | |
|                   if ( i >= nPointers )
 | |
|                      return error4( 0, e4result, E81801 ) ;
 | |
|                #endif
 | |
|                /* rc = less( i, f ) ; */
 | |
|                rc = (*cmp)( pointers[i], pointers[f], (unsigned int)sortLen ) ;
 | |
|                if ( rc == 0 )
 | |
|                {
 | |
|                   memcpy( (void *)&l1, ((char *)pointers[i])+sortLen, sizeof(long) ) ;
 | |
|                   memcpy( (void *)&l2, ((char *)pointers[f])+sortLen, sizeof(long) ) ;
 | |
|                   rc = (l1 < l2) ? -1 : 0 ;
 | |
|                }
 | |
|             }
 | |
|             while( rc < 0 ) ;
 | |
| 
 | |
|             do
 | |
|             {
 | |
|                j-- ;
 | |
|                /* rc = greater( j, f ) ; */
 | |
|                rc = (*cmp)( pointers[j], pointers[f], (unsigned int)sortLen ) ;
 | |
|                if ( rc == 0 )
 | |
|                {
 | |
|                   memcpy( (void *)&l1, ((char *)pointers[j])+sortLen, sizeof(long) ) ;
 | |
|                   memcpy( (void *)&l2, ((char *)pointers[f])+sortLen, sizeof(long) ) ;
 | |
|                   rc = (l1 > l2) ? 1 : 0 ;
 | |
|                }
 | |
|             }
 | |
|             while ( rc > 0 ) ;
 | |
| 
 | |
|             if ( i > j )
 | |
|                break ;
 | |
| 
 | |
|             /* rc = flip( i, j ) ; */
 | |
|             flip_data  = pointers[i] ;
 | |
|             pointers[i] = pointers[j] ;
 | |
|             pointers[j] = flip_data ;
 | |
|          }
 | |
| 
 | |
|          /* replace partition element where it belongs */
 | |
|          /* rc = flip( f, j ) ; */
 | |
|          flip_data  = pointers[f] ;
 | |
|          pointers[f] = pointers[j] ;
 | |
|          pointers[j] = flip_data ;
 | |
| 
 | |
|          /* sort both sides of the partition (smaller side first) */
 | |
|          if ( j - f > l - j )
 | |
|          {
 | |
|             /* Left sort is larger, put it on the stack */
 | |
|             stackStart[++stackOn] = f ;
 | |
|             stackEnd[stackOn] = j - 1 ;
 | |
|             f = j + 1 ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             /* Right sort is larger, put it on the stack */
 | |
|             stackStart[++stackOn] = j + 1 ;
 | |
|             stackEnd[stackOn] = l ;
 | |
|             l = j - 1 ;
 | |
|          }
 | |
|          #ifdef E4ANALYZE
 | |
|             if ( ( stackOn > sizeof( stackStart ) / sizeof( int ) ) || stackOn < 0  )
 | |
|                return error4( 0, e4info, E81801 ) ;
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       /* for a small number of items sort using an insertion algorithm */
 | |
|       for ( i = f+1 ; i <= l ; i++ )
 | |
|       {
 | |
|          for ( j = i ; j > f ; j-- )
 | |
|          {
 | |
|             k = j-1 ;
 | |
|             /* greater( j-1, j ) */
 | |
|             rc = (*cmp)( pointers[k], pointers[j], (unsigned int)sortLen ) ;
 | |
|             if ( rc == 0 )
 | |
|             {
 | |
|                memcpy( (void *)&l1, ((char *)pointers[k])+sortLen, sizeof(long) ) ;
 | |
|                memcpy( (void *)&l2, ((char *)pointers[j])+sortLen, sizeof(long) ) ;
 | |
|                rc = (l1 > l2) ? 1 : 0 ;
 | |
|             }
 | |
|             if ( rc <= 0 )
 | |
|                break ;
 | |
| 
 | |
|             /* flip( j-1, j ) ; */
 | |
|             flip_data  = pointers[k] ;
 | |
|             pointers[k] = pointers[j] ;
 | |
|             pointers[j] = flip_data ;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 |