home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l391 / 2.ddi / QSORT.BA$ / QSORT.bin
Encoding:
Text File  |  1992-08-19  |  6.9 KB  |  204 lines

  1. '
  2. ' QSORT.BAS  - Sorting program (Quicksort algorithm)
  3. '
  4. ' Source Profiler sample program discussed in Chapter 9 
  5. ' of the "Professional Features" manual.
  6. '
  7.  
  8. DEFINT A-Z      ' Default type integer.
  9.  
  10. DECLARE FUNCTION RandInt% (Lower, Upper)
  11. DECLARE FUNCTION GetWords (FileName$)
  12. DECLARE SUB QuickSort (Low, High)
  13. DECLARE SUB Main ()
  14. DECLARE SUB Usage ()
  15. DECLARE SUB OutWords (NumWords,Filename$)
  16. DECLARE SUB Comline(argc, argv$(), Max)
  17.  
  18. ' Maximum number of words to sort
  19. CONST MAXNUMWORDS = 1500
  20. DIM SHARED WordArray$(MAXNUMWORDS)
  21. DIM SHARED WordIndex(MAXNUMWORDS)
  22.  
  23. Main
  24.  
  25. END
  26.  
  27. ' ============================== Main ==================================
  28. '    Initializes the SortBackup and OptionTitle arrays.  It also calls the
  29. '    CheckScreen, BoxInit, and RandInt% procedures.
  30. ' ======================================================================
  31. '
  32. SUB Main STATIC
  33.  
  34.     DIM argv$(1 TO 4)
  35.  
  36.     PRINT "QSORT.BAS"
  37.     CALL ComLine(argc, argv$(), 3)
  38.     IF argc <> 2 THEN Usage
  39.     PRINT "Loading "; argv$(1)
  40.     NumWords = GetWords( argv$(1))
  41.     ' Initialize WordIndex array
  42.     FOR Index = 0 to NumWords
  43.         WordIndex(Index) = Index
  44.     NEXT Index
  45.     PRINT "Loaded";NumWords;"words."
  46.     PRINT "Sorting"
  47.     IF NumWords > 0 THEN
  48.         QuickSort 0, NumWords-1
  49.         OutWords NumWords, argv$(2)
  50.     END IF
  51. END SUB
  52.  
  53. ' ============================ GetWords ================================
  54. '    Loads the text file given in the Filename$ parameter and parses
  55. '    the output, filling in the WordArray$ array. This function returns
  56. '    the number of words loaded.
  57. ' ======================================================================
  58. '
  59. FUNCTION GetWords (Filename$)
  60.     TempChar$ = ""
  61.     CharNumber = 0
  62.     OPEN Filename$ FOR INPUT AS #1
  63.  
  64.     WHILE (WordNumber < MAXNUMWORDS) AND NOT EOF(1)
  65.         TempChar = ASC(INPUT$(1, #1)):Print TempChar$;
  66.             ' Word delimiters
  67.             IF TempChar = 32 OR TempChar = 13 OR TempChar = 9 OR TempChar = 10 THEN
  68.                 ' Start new word unless at beginning
  69.                 IF CharNumber <> 0 THEN
  70.                     CharNumber = 0
  71.                     WordNumber = WordNumber + 1
  72.                 END IF
  73.             ELSE
  74.                 ' Characters to add to word
  75.                 WordArray$(WordNumber) = WordArray$(WordNumber) + CHR$(TempChar)
  76.                 CharNumber = CharNumber + 1
  77.             END IF
  78.     WEND
  79.     CLOSE #1
  80.     GetWords =  WordNumber
  81. END FUNCTION
  82.  
  83. ' ============================== QuickSort ===================================
  84. '   QuickSort works by picking a random "pivot" element in SortArray, then
  85. '   moving every element that is bigger to one side of the pivot, and every
  86. '   element that is smaller to the other side.  QuickSort is then called
  87. '   recursively with the two subdivisions created by the pivot.  Once the
  88. '   number of elements in a subdivision reaches two, the recursive calls end
  89. '   and the array is sorted.
  90. ' ============================================================================
  91. '
  92. SUB QuickSort (Low, High)
  93.    IF Low < High THEN
  94.  
  95.       ' Only two elements in this subdivision; swap them if they are out of
  96.       ' order, then end recursive calls:
  97.       IF High - Low = 1 THEN
  98.          IF UCASE$(WordArray$(WordIndex(Low))) > UCASE$(WordArray$(WordIndex(High))) THEN
  99.             SWAP    Low, High
  100.          END IF
  101.       ELSE
  102.  
  103.          ' Pick a pivot element at random, then move it to the end:
  104.          RandIndex = RandInt%(Low, High)
  105.          SWAP   WordIndex(High), WordIndex(RandIndex)
  106.          Partition$ = UCASE$(WordArray$(WordIndex(High)))
  107.          DO
  108.  
  109.             ' Move in from both sides towards the pivot element:
  110.             I = Low: J = High
  111.             DO WHILE (I < J) AND (UCASE$(WordArray$(WordIndex(I))) <= Partition$)
  112.                I = I + 1
  113.             LOOP
  114.             DO WHILE (J > I) AND (UCASE$(WordArray$(WordIndex(J))) >= Partition$)
  115.                J = J - 1
  116.             LOOP
  117.  
  118.             ' If we haven't reached the pivot element, it means that two
  119.             ' elements on either side are out of order, so swap them:
  120.             IF I < J THEN
  121.                SWAP WordIndex(I), WordIndex(J)
  122.             END IF
  123.          LOOP WHILE I < J
  124.  
  125.          ' Move the pivot element back to its proper place in the array:
  126.          SWAP WordIndex(I), WordIndex(High)
  127.  
  128.          ' Recursively call the QuickSort procedure (pass the smaller
  129.          ' subdivision first to use less stack space):
  130.          IF (I - Low) < (High - I) THEN
  131.             QuickSort Low, I - 1
  132.             QuickSort I + 1, High
  133.          ELSE
  134.             QuickSort I + 1, High
  135.             QuickSort Low, I - 1
  136.          END IF
  137.       END IF
  138.    END IF
  139. END SUB
  140.  
  141. ' ============================= OutWords ==================================
  142. '   Copies the output
  143. '
  144. ' =========================================================================
  145. SUB OutWords(NumWords, Filename$)
  146.     OPEN Filename$ FOR OUTPUT AS #1
  147.     FOR TempIndex=0 TO NumWords-1
  148.         PRINT #1, WordArray$(WordIndex(TempIndex))
  149.     NEXT TempIndex
  150.     CLOSE #1
  151. END SUB
  152.  
  153. SUB Usage
  154.     PRINT "Performs QuickSort on a file and sends results to a file."
  155.     PRINT "Usage: QSORT <input> <output>"
  156.     PRINT "Where <input> is the name of the text file to sort and <output> is the"
  157.     PRINT "name of the file to store the sorted output.  JABBER.TXT is supplied"
  158.     PRINT "as sample input."
  159. END
  160. END SUB
  161. ' =============================== RandInt% ===================================
  162. '   Returns a random integer greater than or equal to the Lower parameter
  163. '   and less than or equal to the Upper parameter.
  164. ' ============================================================================
  165. '
  166. FUNCTION RandInt% (Lower, Upper) STATIC
  167.    RandInt% = INT(RND * (Upper - Lower + 1)) + Lower
  168. END FUNCTION
  169.  
  170. 'SUB procedure to get command line and split into arguments.
  171. 'Parameters:  NumArgs : Number of command line args found.
  172. '             Args$() : Array in which to return arguments.
  173. '             MaxArgs : Maximum number of arguments array can return.
  174. SUB Comline(NumArgs,Args$(),MaxArgs) STATIC
  175. CONST TRUE=-1, FALSE=0
  176.  
  177.    NumArgs=0 : In=FALSE
  178.    'Get the command line using the COMMAND$ function.
  179.    Cl$=COMMAND$
  180.    L=LEN(Cl$)
  181.    'Go through the command line a character at a time.
  182.    FOR I=1 TO L
  183.       C$=MID$(Cl$,I,1)
  184.       'Test for character being a blank or a tab.
  185.       IF (C$<>" " AND C$<>CHR$(9)) THEN
  186.       'Neither blank nor tab. Test if you're already inside an argument.
  187.          IF NOT In THEN
  188.          'You've found the start of a new argument.
  189.             'Test for too many arguments.
  190.             IF NumArgs=MaxArgs THEN EXIT FOR
  191.             NumArgs=NumArgs+1
  192.             In=TRUE
  193.          END IF
  194.          'Add the character to the current argument.
  195.          Args$(NumArgs)=Args$(NumArgs)+C$
  196.       ELSE
  197.       'Found a blank or a tab.
  198.          'Set "Not in an argument" flag to FALSE.
  199.          In=FALSE
  200.       END IF
  201.    NEXT I
  202.  
  203. END SUB
  204.