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 ;
 | 
						|
}
 |