home *** CD-ROM | disk | FTP | other *** search
- /*
- * QSORT.C C version of the quicksort algorithm
- *
- * This program is described in Chapters 2 and 3 of the Microsoft Source
- * Profiler User's Guide.
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /* Macro to get a random integer within a specified range */
- #define getrandom( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min))
-
- /* Maximum number of words to sort */
- #define MAXNUMWORDS 1500
- /* Maximum word length (in characters) */
- #define MAXWORDSIZE 15
-
-
- char WordArray[MAXNUMWORDS][MAXWORDSIZE];
- int WordIndex[MAXNUMWORDS];
-
- void usage(void);
- int GetWords(char *filename);
- void QuickSort(int Low, int High );
- void SwapWords( int index1, int index2 );
- void OutWords(int NumWords, char *filename);
-
- /* main - The main function calls functions that load the input file,
- * sort it, and save the output to another file. It also calls the usage
- * statement on bad command-line arguments and sets up the index array.
- */
- int main (int argc, char *argv[])
- {
- int NumWords;
- int index;
- puts( "QSORT.C" );
- if ( argc != 3 )
- usage();
- printf( "Loading %s\n", argv[1] );
- NumWords = GetWords( argv[1] );
- /* Initialize WordIndex array */
- for ( index = 0; index < NumWords; index++ )
- WordIndex[index] = index;
- printf( "Loaded %i words.\n", NumWords );
- puts( "Sorting" );
- if ( NumWords > 0 )
- {
- QuickSort( 0, NumWords-1 );
- OutWords( NumWords, argv[2] );
- }
-
- return 0;
- }
-
- /* GetWords - GetWords loads and parses an ASCII text file and stores each
- * word into WordArray. Returns the number of words read.
- */
- int GetWords(char *filename)
- {
- FILE *FileHandle;
- int WordNumber = 0;
- int CharNumber = 0;
- char TempChar = '\0';
-
- FileHandle = fopen(filename, "r");
- if (FileHandle == NULL)
- {
- puts("Error opening input file.");
- return 0;
- }
-
- while ((WordNumber < MAXNUMWORDS) && (TempChar != EOF))
- {
- TempChar = fgetc(FileHandle);
- switch(TempChar)
- {
- /* Word delimiters */
- case ' ' :
- case '\n':
- case '\t':
- /* Start new word unless at beginning */
- if (CharNumber != 0)
- {
- WordArray[WordNumber][CharNumber] = '\0';
- CharNumber = 0;
- WordNumber++;
- }
- break;
- /* Quit if at end of file */
- case EOF:
- break;
- /* Characters to add to word */
- default:
- WordArray[WordNumber][CharNumber] = TempChar;
- /* Truncate word if too long */
- if (++CharNumber >= MAXWORDSIZE)
- {
- WordArray[WordNumber][CharNumber-1] = '\0';
- CharNumber = 0;
- WordNumber++;
- /* Skip over remaining characters */
- while ((TempChar != ' ') && (TempChar != '\n') &&
- (TempChar != '\t'))
- TempChar = fgetc(FileHandle);
- }
- break;
- }
- }
- fclose( FileHandle );
- return WordNumber;
- }
-
- /* QuickSort - QuickSort works by picking a random "pivot" element,
- * then moving every element that is bigger to one side of the pivot,
- * and every element that is smaller to the other side. QuickSort is
- * then called recursively with the two subdivisions created by the pivot.
- * Once the number of elements in a subdivision reaches two, the recursive
- * calls end and the array is sorted.
- */
- void QuickSort( int Low, int High )
- {
- int Up, Down;
-
- char cBreak[MAXWORDSIZE];
-
- if( Low < High )
- {
- /* Only two elements in this subdivision; swap them if they are
- * out of order, then end recursive calls.
- */
- if( (High - Low) == 1 )
- {
- if( stricmp( WordArray[WordIndex[Low]], WordArray[WordIndex[High]] ) > 0 )
- SwapWords( Low, High );
- }
- else
- {
- /* Pick a pivot element at random, then move it to the end. */
- SwapWords( High, getrandom( Low, High ) );
- strcpy( cBreak, WordArray[WordIndex[High]] );
- do
- {
- /* Move in from both sides towards the pivot element. */
- Up = Low;
- Down = High;
- while( (Up < Down) &&
- (stricmp( WordArray[WordIndex[Up]], cBreak ) <= 0) )
- Up++;
- while( (Down > Up) &&
- (stricmp( WordArray[WordIndex[Down]], cBreak ) >= 0) )
- Down--;
- /* If we haven't reached the pivot, it means that two
- * elements on either side are out of order, so swap them.
- */
- if( Up < Down )
- SwapWords( Up, Down );
- } while ( Up < Down );
-
- /* Move pivot element back to its proper place in the array. */
- SwapWords( Up, High );
-
- /* Recursively call the QuickSort procedure (pass the smaller
- * subdivision first to use less stack space).
- */
- if( (Up - Low) < (High - Up) )
- {
- QuickSort( Low, Up - 1 );
- QuickSort( Up + 1, High );
- }
- else
- {
- QuickSort( Up + 1, High );
- QuickSort( Low, Up - 1 );
- }
- }
- }
- }
-
- /* SwapWords - SwapWords swaps the WordIndex index values of two words,
- * thereby swapping the indexed positions of the words.
- */
- void SwapWords( int index1, int index2 )
- {
- int TempIndex;
- TempIndex = WordIndex[index1];
- WordIndex[index1] = WordIndex[index2];
- WordIndex[index2] = TempIndex;
- }
-
- /* OutWords - OutWords writes the sorted array of words to a file.
- */
- void OutWords(int NumWords, char *filename)
- {
- FILE *FileHandle;
- int TempIndex;
- FileHandle = fopen(filename, "w");
- if (FileHandle == NULL)
- {
- puts("Error opening output file.");
- return;
- }
- for (TempIndex=0; TempIndex < NumWords; TempIndex++ )
- if ( fputs( WordArray[WordIndex[TempIndex]], FileHandle ) == EOF)
- {
- puts("Error writing output file.");
- break;
- }
- else
- fputs( "\n", FileHandle );
- fclose( FileHandle );
- }
-
- /* usage - The usage function displays the syntax of QSORT and exits to the
- * system.
- */
- void usage(void)
- {
- puts("Performs QuickSort on a file and sends results to a file.");
- puts("Usage: QSORT <input> <output>");
- puts("Where <input> is the name of the text file to sort and <output> is the");
- puts("name of the file to store the sorted output.");
- exit (0);
- }
-