home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / FORTRAN / DISK6 / SORTDEMO.FO$ / SORTDEMO.bin
Text File  |  1989-02-22  |  32KB  |  1,022 lines

  1. CC  SORTDEMO.FOR
  2. CC
  3. CC  This program graphically demonstrates six common sorting algorithms.
  4. CC  It displays 25 or 43 horizontal bars different lengths in random order,
  5. CC  then sorts the bars from shortest to longest.
  6. CC
  7. CC  The program also uses the DosBeep API function to generate sounds of
  8. CC  different pitches, depending on the location of the bar being displayed.
  9. CC  Note that calls to the DosBeep and DosSleep functions delay the speed
  10. CC  of each sorting algorithm so you can follow the progress of the sort.
  11. CC  Therefore, the times shown are for comparisons only.  They are not an
  12. CC  accurate measure of sort speed.
  13. CC
  14. CC  If you use these sorting routines in your own programs, you may notice
  15. CC  a difference in their relative speeds -- for example, the exchange
  16. CC  sort may be faster than the shell sort.  The speed of each algorithm
  17. CC  depends on the number of elements to be sorted and how "scrambled"
  18. CC  they are to begin with.
  19. CC
  20. CC  To compile this program, the following OS/2 include files must be copied
  21. CC  from the distribution disks (as described in PACKING.LST on the SETUP
  22. CC  disk) to either your current directory or the directory specified by
  23. CC  the INCLUDE environment variable:
  24. CC
  25. CC      BSE.FI          BSEDOS.FI       BSESUB.FI
  26. CC      BSE.FI          BSEDOS.FI       BSESUB.FI
  27. CC
  28. CC  To compile a protect-mode version, use the following command line:
  29. CC
  30. CC      FL /Lp sortdemo.for
  31. CC
  32. CC  To compile a bound version that can be run from either DOS or OS/2,
  33. CC  use the following command line:
  34. CC
  35. CC      FL /Lp /Fb sortdemo.for
  36. CC
  37. CC  You cannot create a DOS-only version. Note that /Lp may not be
  38. CC  required, depending on the library names you selected during setup.
  39. CC
  40.  
  41. $NOTRUNCATE
  42. $STORAGE:2
  43.  
  44. $DEFINE  INCL_NOCOMMON
  45. $DEFINE  INCL_DOSPROCESS
  46. $DEFINE  INCL_KBD
  47. $DEFINE  INCL_VIO
  48.  
  49.       INCLUDE 'BSE.FI'
  50.       INCLUDE 'BSE.FD'
  51.  
  52.       INTEGER*2            dummy, MaxBars, MaxColors, Pause,
  53.      +                     CurRow, CurCol, C_LENGTH
  54.       LOGICAL              Sound
  55.       PARAMETER          ( C_LENGTH = 8000 )
  56.       CHARACTER*(C_LENGTH) CellStr
  57.       RECORD /VIOMODEINFO/ NewMode, OldMode
  58.  
  59.       COMMON /misc/        MaxBars, MaxColors, Sound, Pause
  60.  
  61. C
  62. C     Get cursor position, screen contents, and current video mode.
  63. C     The parameter C_LENGTH is the length of a cell string to hold
  64. C     the screen contents, including attribute bytes.  Its value of
  65. C     8000 allows enough space for 50-line mode.
  66. C
  67.       dummy      = VioGetCurPos( CurRow, CurCol, 0 )
  68.       dummy      = VioReadCellStr( CellStr, C_LENGTH, 0, 0, 0 )
  69.       OldMode.cb = 14
  70.       NewMode.cb = 14
  71.       dummy      = VioGetMode( OldMode, 0 )
  72.       dummy      = VioGetMode( NewMode, 0 )
  73.  
  74. C
  75. C     MaxColors is number of colors used when displaying bars.
  76. C     If monochrome or color burst disabled, use one color.
  77. C
  78.       MaxColors = 15
  79.       IF( (.NOT. BTEST( NewMode.fbType, 0 ))  .OR.
  80.      +           BTEST( NewMode.fbType, 2 ) ) MaxColors = 1
  81.  
  82. C
  83. C     MaxBars is number of bars, one for each screen line.
  84. C     First try 43-line mode.  If neither EGA or VGA is
  85. C     available, set for 25-line mode.
  86. C
  87.       MaxBars = 43
  88.       IF( NewMode.row .NE. 43 ) THEN
  89.          NewMode.row  = 43
  90.          NewMode.hres = 640
  91.          NewMode.vres = 350
  92.          IF( VioSetMode( NewMode, 0 ) .NE. 0 ) THEN
  93.             dummy       = VioGetMode( NewMode, 0 )
  94.             MaxBars     = 25
  95.             NewMode.row = 25
  96.             dummy       = VioSetMode( NewMode, 0 )
  97.          END IF
  98.       END IF
  99.  
  100.       CALL Initialize
  101.       CALL SortMenu
  102.  
  103. C
  104. C     Restore line mode, screen contents, and cursor position
  105. C     before exiting.
  106. C
  107.       dummy     = VioSetMode( OldMode, 0 )
  108.       dummy     = VioWrtCellStr( CellStr, C_LENGTH, 0, 0, 0 )
  109.       dummy     = VioSetCurPos( CurRow, CurCol, 0 )
  110.       END
  111.  
  112.  
  113.  
  114. CC  Block Data Subprogram - Initializes data held in common block /misc/.
  115. CC
  116. CC  Uses:    MaxBars   - Number of bars to sort (25 or 43)
  117. CC           MaxColors - Number of colors (1 or 15)
  118. CC           Sound     - .TRUE. for sound on, .FALSE. for sound off
  119. CC           Pause     - Number of milliseconds to pause when
  120. CC                       displaying sorting speed
  121.  
  122.       BLOCK DATA
  123.       IMPLICIT INTEGER*2 ( a - z )
  124.  
  125.       LOGICAL       Sound
  126.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  127.       DATA          Sound, Pause  / .TRUE., 30 /
  128.       END
  129.  
  130.  
  131.  
  132. CC  Initialize - Generates a pattern of bar in random lengths and colors,
  133. CC  then stores the pattern in the SortBackup array.  Also calls the
  134. CC  BoxInit subroutine.
  135. CC
  136. CC  Params:  None
  137.  
  138.       SUBROUTINE Initialize
  139.       IMPLICIT INTEGER*2 ( a - z )
  140.  
  141.       LOGICAL       Sound
  142.       REAL*4        Rand
  143.       DIMENSION     TempArray(43)
  144.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  145.       COMMON        SortArray(2,43), SortBackup(2,43),
  146.      +              BarLength, BarColor, Select
  147.  
  148. C
  149. C     BarLength and BarColor are indexes for the row dimensions of
  150. C     SortArray and SortBackup.  Bar lengths are contained in the
  151. C     first row of SortArray, and bar colors in the second row.
  152. C
  153.       BarLength = 1
  154.       BarColor  = 2
  155.       DO i = 1, MaxBars
  156.          TempArray(i) = i
  157.       END DO
  158. C
  159. C     Seed the random-number generator with current hundredth second.
  160. C
  161.       CALL GETTIM( dummy, dummy, dummy, Rseed )
  162.       CALL SEED( Rseed )
  163.  
  164.       MaxIndex = MaxBars
  165.       DO i = 1, MaxBars
  166. C
  167. C        Find a random element in TempArray between 1 and MaxIndex, 
  168. C        then assign the value in that element to LengthBar.
  169. C
  170.          CALL RANDOM( Rand )
  171.  
  172.          Index     = (MaxIndex * Rand) + 1
  173.          LengthBar = TempArray(index)
  174. C
  175. C        Overwrite the value in TempArray(Index) with the value in
  176. C        TempArray(MaxIndex) so the value in TempArray(Index) is
  177. C        chosen only once.
  178. C
  179.          TempArray(index) = TempArray(MaxIndex)
  180. C
  181. C        Decrease the value of MaxIndex so that TempArray(MaxIndex) can't
  182. C        be chosen on the next pass through the loop.
  183. C
  184.          MaxIndex = MaxIndex - 1
  185.  
  186.          SortBackup(BarLength,i) = LengthBar
  187.          IF( MaxColors .EQ. 1 ) THEN
  188.             SortBackup(BarColor,i) = 7
  189.          ELSE  
  190.             SortBackup(BarColor,i) = MOD( LengthBar, MaxColors ) + 1
  191.          END IF
  192.       END DO
  193.  
  194.       CALL cls
  195. C
  196. C     Assign values in SortBackup to SortArray and redraw unsorted
  197. C     bars on the screen.
  198. C
  199.       CALL Reinitialize
  200. C
  201. C     Draw frame and display the SortDemo menu.
  202. C
  203.       CALL BoxInit
  204.       RETURN
  205.       END
  206.  
  207.  
  208.  
  209. CC  BoxInit - Calls the DrawFrame procedure to draw the frame around
  210. CC  the SortDemo menu, then displays the menu.
  211. CC
  212. CC  Params:  None
  213.  
  214.       SUBROUTINE BoxInit
  215.       IMPLICIT INTEGER*2 ( a - z )
  216.  
  217.       INTEGER*1     COLOR
  218.       INTEGER*2     FIRSTMENU, LEFT, LINELENGTH, NLINES, WIDTH
  219.       CHARACTER*4   Factor
  220.       CHARACTER*12  BLANK
  221.       PARAMETER   ( COLOR      = 15, FIRSTMENU = 1 , LEFT  = 48     ,
  222.      +              LINELENGTH = 28, NLINES    = 18, WIDTH = 80-LEFT,
  223.      +              BLANK      = '            ' )
  224.       LOGICAL       Sound
  225.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  226.       COMMON        SortArray(2,43), SortBackup(2,43),
  227.      +              BarLength, BarColor, Select
  228.  
  229.       CHARACTER*(LINELENGTH)  menu(NLINES)
  230.       DATA menu / '     FORTRAN Sorting Demo',
  231.      +            ' ',
  232.      +            'Insertion',
  233.      +            'Bubble',
  234.      +            'Heap',
  235.      +            'Exchange',
  236.      +            'Shell',
  237.      +            'Quick',
  238.      +            ' ',
  239.      +            'Toggle Sound: ',
  240.      +            ' ',
  241.      +            'Pause Factor: ',
  242.      +            '<   (Slower)',
  243.      +            '>   (Faster)',
  244.      +            ' ',
  245.      +            'Type first character of',
  246.      +            'choice ( I B H E S Q T < > )',
  247.      +            'or ESC key to end program: ' /
  248.  
  249.       CALL DrawFrame( 1, LEFT-3, WIDTH + 3, 22)
  250.  
  251.       DO i = 1, NLINES
  252.          dummy = VioWrtCharStrAtt( menu(i), LINELENGTH,
  253.      +                             FIRSTMENU + i, LEFT, COLOR, 0)
  254.       END DO
  255.  
  256.       WRITE (Factor, '(I2.2)') Pause / 30
  257.       dummy = VioWrtCharStrAtt( Factor, LEN( Factor ), 13,
  258.      +                          LEFT + 14, COLOR, 0)
  259.  
  260. C
  261. C     Erase the speed option if the length of the Pause is at a limit.
  262. C
  263.       IF( Pause .EQ. 900 ) THEN
  264.          dummy = VioWrtCharStrAtt( BLANK, 12, 14, LEFT, COLOR, 0 )
  265.       ELSEIF( Pause .EQ. 0 ) THEN
  266.          dummy = VioWrtCharStrAtt( BLANK, 12, 15, LEFT, COLOR, 0 )
  267.       END IF
  268.  
  269. C
  270. C     Display the current value for Sound.
  271. C
  272.       IF( Sound ) THEN
  273.         dummy = VioWrtCharStrAtt( 'ON ', 3, 11, LEFT + 14, COLOR, 0 )
  274.       ELSE
  275.         dummy = VioWrtCharStrAtt( 'OFF', 3, 11, LEFT + 14, COLOR, 0 )
  276.       END IF
  277.  
  278.       RETURN
  279.       END
  280.  
  281.  
  282.  
  283. CC  DrawFrame - Draws a rectangular frame using the high-order ASCII
  284. CC  characters 201, 187, 200, 188, 186, and 205.
  285. CC
  286. CC  Params:  Top    - row number of top line
  287. CC           Left   - column number of left edge
  288. CC           Width  - number of columns in frame
  289. CC           Height - number of rows in frame
  290.  
  291.       SUBROUTINE DrawFrame( Top, Left, Width, Height )
  292.       IMPLICIT INTEGER*2 ( a - z )
  293.  
  294.       INTEGER*1     cell(2), COLOR, ULEFT, URIGHT, LLEFT,
  295.      +              LRIGHT, VERTICAL, HORIZONTAL, SPACE
  296.       CHARACTER*80  TempStr
  297.       PARAMETER   ( ULEFT  = '╔', URIGHT   = '╗', LLEFT      = '╚',
  298.      +              LRIGHT = '╝', VERTICAL = '║', HORIZONTAL = '═',
  299.      +              SPACE  = ' ', COLOR    = 15 )
  300.  
  301.       bottom  = Top  + Height - 1
  302.       right   = Left + Width  - 1
  303.       cell(2) = COLOR
  304.       cell(1) = ULEFT
  305.       dummy   = VioWrtNCell( cell, 1, Top, Left, 0)
  306.       cell(1) = HORIZONTAL
  307.       dummy   = VioWrtNCell( cell, Width-2, Top, Left + 1, 0)
  308.       cell(1) = URIGHT
  309.       dummy   = VioWrtNCell( cell, 1, Top, right, 0)
  310.       TempStr(1:1) = CHAR( VERTICAL )
  311.  
  312.       DO i = 2, Width-1
  313.          TempStr(i:i) = CHAR( SPACE )
  314.       END DO
  315.  
  316.       TempStr(Width:Width) = CHAR( VERTICAL )
  317.       DO i = 1, Height-2
  318.          dummy = VioWrtCharStrAtt( TempStr, Width, i + Top,
  319.      +                             Left, COLOR, 0)
  320.       END DO
  321.  
  322.       cell(1) = LLEFT
  323.       dummy   = VioWrtNCell( cell, 1, bottom, Left, 0)
  324.       cell(1) = HORIZONTAL
  325.       dummy   = VioWrtNCell( cell, Width-2, bottom, Left + 1, 0)
  326.       cell(1) = LRIGHT
  327.       dummy   = VioWrtNCell( cell, 1, bottom, right, 0)
  328.       RETURN
  329.       END
  330.  
  331.  
  332.  
  333.  
  334. CC  ElapsedTime - Displays seconds elapsed since the given sorting routine
  335. CC  started.  Note that this time includes both the time it takes to
  336. CC  redraw the bars plus the pause while the DosBeep function plays a
  337. CC  note, and thus is not meant to be a true measure of sorting speed.
  338. CC
  339. CC  Params:  CurrentRow
  340. CC
  341. CC  Uses:    SortArray, SortBackup - length and color for each bar
  342. CC           time0 - Starting time for sort
  343.  
  344.       SUBROUTINE ElapsedTime( CurrentRow )
  345.       IMPLICIT INTEGER*2 ( a - z )
  346.  
  347.       INTEGER*1     COLOR
  348.       INTEGER*4     time0, time1
  349.       CHARACTER*7   Timing
  350.       LOGICAL       Sound
  351.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  352.       COMMON /time/ time0
  353.       COMMON        SortArray(2,43), SortBackup(2,43),
  354.      +              BarLength, BarColor, Select
  355.       PARAMETER   ( COLOR = 15, FIRSTMENU = 1, LEFT = 48 )
  356.  
  357.       CALL GETTIM( Hour, Minute, Second, Hundredth )
  358.       time1 = Hour   * 360000 +
  359.      +        Minute * 6000   +
  360.      +        Second * 100    +
  361.      +        Hundredth
  362.  
  363.       WRITE (Timing, '(F7.2)') FLOAT( time1 - time0 ) / 100.0
  364. C
  365. C     Display the number of seconds elapsed.
  366. C
  367.       dummy = VioWrtCharStrAtt( Timing, LEN( Timing ),
  368.      +                          Select+FIRSTMENU+3, LEFT+15, COLOR, 0)
  369.  
  370.       IF( Sound ) dummy = DosBeep( 60 * CurrentRow, 32 )
  371.       dummy = DosSleep( INT4( Pause ) )
  372.       RETURN
  373.       END
  374.  
  375.  
  376.  
  377. CC  InsertionSort - The InsertionSort procedure compares the length of
  378. CC  each successive element in SortArray with the lengths of all the
  379. CC  preceding elements.  When the procedure finds the appropriate place
  380. CC  for the new element, it inserts the element in its new place, and
  381. CC  moves all the other elements down one place.
  382. CC
  383. CC  Params:  None
  384.  
  385.       SUBROUTINE InsertionSort
  386.       IMPLICIT INTEGER*2 ( a - z )
  387.  
  388.       DIMENSION     TempArray(2)
  389.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  390.       COMMON        SortArray(2,43), SortBackup(2,43),
  391.      +              BarLength, BarColor, Select
  392.  
  393.       DO Row = 2, MaxBars
  394.          TempArray(BarLength) = SortArray(BarLength,Row)
  395.          TempArray(BarColor)  = SortArray(BarColor,Row)
  396.          DO j = Row, 2, -1
  397. C
  398. C           As long as the length of the j-1st element is greater than the
  399. C           length of the original element in SortArray(Row), keep shifting
  400. C           the array elements down.
  401. C
  402.             IF( SortArray(BarLength,j - 1) .GT.
  403.      +          TempArray(BarLength) ) THEN
  404.                 SortArray(BarLength,j) = SortArray(BarLength,j - 1)
  405.                 SortArray(BarColor,j)  = SortArray(BarColor,j - 1)
  406.                 CALL PrintOneBar(j)
  407.                 CALL ElapsedTime(j)
  408.             ELSE
  409.                 EXIT
  410.             END IF
  411.          END DO
  412.      
  413. C
  414. C        Insert the original value of SortArray(Row) in SortArray(j).
  415. C
  416.          SortArray(BarLength,j) = TempArray(BarLength)
  417.          SortArray(BarColor,j)  = TempArray(BarColor)
  418.          CALL PrintOneBar( j )
  419.          CALL ElapsedTime( j )
  420.       END DO
  421.       RETURN
  422.       END
  423.  
  424.  
  425.  
  426. CC  BubbleSort - The BubbleSort algorithm cycles through SortArray,
  427. CC  comparing adjacent elements and swapping pairs that are out of
  428. CC  order.  It continues to do this until no pairs are swapped.
  429. CC
  430. CC  Params:  None
  431.  
  432.       SUBROUTINE BubbleSort
  433.       IMPLICIT INTEGER*2 ( a - z )
  434.  
  435.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  436.       COMMON        SortArray(2,43), SortBackup(2,43),
  437.      +              BarLength, BarColor, Select
  438.  
  439.       limit  = MaxBars
  440.       DO WHILE( limit .NE. 0 )
  441.          switch = 0
  442.          DO row = 1, limit-1
  443. C
  444. C           If two adjacent elements are out of order, swap
  445. C           their values and redraw those two bars.
  446. C
  447.             IF( SortArray(BarLength,row ) .GT. 
  448.      +          SortArray(BarLength,row + 1 ) ) THEN
  449.                 CALL SwapSortArray( row, row + 1 )
  450.                 CALL SwapBars( row, row + 1 )
  451.                 switch = row
  452.             END IF
  453.          END DO
  454. C
  455. C        Sort on next pass only to where the last switch was made.
  456. C
  457.          limit = switch
  458.       END DO
  459.       RETURN
  460.       END
  461.  
  462.  
  463.  
  464.  
  465. CC  ExchangeSort - Beginning with the first element, ExchangeSort compares
  466. CC  each element in SortArray with every following element.  If any of the
  467. CC  following elements is smaller than the current element, it is exchanged
  468. CC  with the current element.  The process is then repeated for the next
  469. CC  element in SortArray.
  470. CC
  471. CC  Params:  None
  472.  
  473.       SUBROUTINE ExchangeSort
  474.       IMPLICIT INTEGER*2 ( a - z )
  475.  
  476.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  477.       COMMON        SortArray(2,43), SortBackup(2,43),
  478.      +              BarLength, BarColor, Select
  479.  
  480.       DO Row = 1, MaxBars-1
  481.          SmallestRow = Row
  482.          DO j = Row + 1, MaxBars
  483.             IF( SortArray(BarLength,j) .LT.
  484.      +          SortArray(BarLength,SmallestRow) ) THEN
  485.                 SmallestRow = j
  486.                 CALL ElapsedTime( j )
  487.             END IF
  488.          END DO
  489.          IF( SmallestRow .GT. Row ) THEN
  490. C
  491. C           Found a row shorter than the current row,
  492. C           so swap those two array elements.
  493. C
  494.             CALL SwapSortArray( Row, SmallestRow )
  495.             CALL SwapBars( Row, SmallestRow )
  496.          END IF
  497.       END DO
  498.       RETURN
  499.       END
  500.  
  501.  
  502.  
  503. CC  HeapSort - The HeapSort subroutine works by calling two other
  504. CC  subroutines:  PercolateUp and PercolateDown.  PercolateUp turns
  505. CC  SortArray into a "heap," which has the properties outlined in the
  506. CC  diagram below.
  507. CC
  508. CC                               SortArray(1)
  509. CC                               /          \
  510. CC                    SortArray(2)           SortArray(3)
  511. CC                   /          \            /          \
  512. CC         SortArray(4)   SortArray(5)   SortArray(6)  SortArray(7)
  513. CC          /      \       /       \       /      \      /      \
  514. CC        ...      ...   ...       ...   ...      ...  ...      ...
  515. CC
  516. CC
  517. CC  Here each "parent node" is greater than each of its "child nodes".
  518. CC  For example, the value of SortArray(1) is greater than that of
  519. CC  SortArray(2) or SortArray(3), SortArray(3) is greater than
  520. CC  SortArray(6) or SortArray(7), and so forth.
  521. CC
  522. CC  Therefore, once the first DO loop in HeapSort is finished, the largest
  523. CC  element is in SortArray(1).
  524. CC
  525. CC  The second DO loop in HeapSort swaps the element in SortArray(1) with
  526. CC  the element in MaxRow, rebuilds the heap (with PercolateDown) for
  527. CC  MaxRow - 1, then swaps the element in SortArray(1) with the element
  528. CC  in MaxRow - 1, rebuilds the heap for MaxRow - 2, and continues in
  529. CC  this way until the array is sorted.
  530. CC
  531. CC  Params:  None
  532.  
  533.       SUBROUTINE HeapSort
  534.       IMPLICIT INTEGER*2 ( a - z )
  535.  
  536.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  537.       COMMON        SortArray(2,43), SortBackup(2,43),
  538.      +              BarLength, BarColor, Select
  539.  
  540.       DO i = 2, MaxBars
  541.          CALL PercolateUp( i )
  542.       END DO
  543.  
  544.       DO i = MaxBars, 2, -1
  545.          CALL SwapSortArray( 1, i )
  546.          CALL SwapBars( 1, i )
  547.          CALL PercolateDown( i - 1 )
  548.       END DO
  549.       RETURN
  550.       END
  551.  
  552.  
  553.  
  554. CC  PercolateUp - The PercolateUp procedure converts elements 1 to
  555. CC  MaxLevel in SortArray into a "heap".  (See the diagram with the
  556. CC  HeapSort procedure.)
  557. CC
  558. CC  Params:  MaxLevel - Highest element in heap
  559.  
  560.       SUBROUTINE PercolateUp( MaxLevel )
  561.       IMPLICIT INTEGER*2 ( a - z )
  562.  
  563.       COMMON   SortArray(2,43), SortBackup(2,43),
  564.      +         BarLength, BarColor, Select
  565.  
  566. C
  567. C     Move the value in SortArray(MaxLevel) up the heap until it has
  568. C     reached its proper node -- that is, until it is greater than either
  569. C     of its child nodes, or until it has reached 1, the top of the heap.
  570. C
  571.       i = MaxLevel
  572.       DO WHILE( i .NE. 1 )
  573.  
  574. C
  575. C        Get the subscript for the parent node.
  576. C
  577.          Parent = i / 2
  578.  
  579. C
  580. C        If the value at the current node is still bigger than the
  581. C        value at its parent node, swap these two array elements.
  582. C        Otherwise, the element has reached its proper place in the
  583. C        heap, in which case the procedure exits.
  584. C
  585.          IF( SortArray(BarLength,i) .GT.
  586.      +       SortArray(BarLength,Parent) ) THEN
  587.              CALL SwapSortArray( Parent, i )
  588.              CALL SwapBars( Parent, i )
  589.              i = Parent
  590.          ELSE
  591.              i = 1
  592.          END IF
  593.       END DO
  594.       RETURN
  595.       END
  596.  
  597.  
  598.  
  599. CC  PercolateDown - The PercolateDown procedure restores elements 1
  600. CC  to MaxLevel in SortArray from a "heap".  (See the diagram with
  601. CC  the HeapSort procedure.)
  602. CC
  603. CC  Params:  MaxLevel - Highest element in heap
  604.  
  605.       SUBROUTINE PercolateDown( MaxLevel )
  606.       IMPLICIT INTEGER*2 ( a - z )
  607.  
  608.       COMMON   SortArray(2,43), SortBackup(2,43),
  609.      +         BarLength, BarColor, Select
  610.  
  611. C     Move the value in SortArray(1) down the heap until it has reached
  612. C     its proper node -- that is, until it is less than its parent node
  613. C     or until it has reached MaxLevel, the bottom of the current heap.
  614. C
  615.       i = 1
  616.       DO WHILE( .TRUE. )
  617.  
  618. C
  619. C        Get the subscript for the child node.
  620. C
  621.          Child = 2 * i
  622.  
  623. C
  624. C        IF the bottom of the heap is reached, exit this procedure.
  625. C
  626.          IF( Child .GT. MaxLevel) EXIT
  627.  
  628. C
  629. C        If there are two child nodes, determine which is bigger.
  630. C
  631.          IF( Child + 1 .LE. MaxLevel ) THEN
  632.             IF( SortArray(BarLength,Child + 1) .GT.
  633.      +          SortArray(BarLength,Child) ) Child = Child + 1
  634.          END IF
  635.  
  636. C
  637. C        Move the value down if it is still not bigger than either of
  638. C        its children.  Otherwise, SortArray has been restored to a
  639. C        heap from 1 to MaxLevel, in which case the routine exits.
  640. C
  641.          IF( SortArray(BarLength,i) .LT.
  642.      +       SortArray(BarLength,Child) ) THEN
  643.              CALL SwapSortArray(i, Child)
  644.              CALL SwapBars(i, Child)
  645.              i = Child
  646.          ELSE
  647.              EXIT
  648.          END IF
  649.       END DO
  650.       RETURN
  651.       END
  652.  
  653.  
  654.  
  655. CC  ShellSort - The ShellSort procedure is similar to the BubbleSort
  656. CC  procedure.  However, ShellSort begins by comparing elements that
  657. CC  are far apart -- that is, separated by the value of the Offset
  658. CC  variable, which is initially half the distance between the first
  659. CC  and last element.  The procedure repeats by comparing elements that
  660. CC  are successively closer together.  Note that when Offset is one, the
  661. CC  last iteration of this procedure is merely a bubble sort.
  662. CC
  663. CC  Params:  None
  664.  
  665.       SUBROUTINE ShellSort
  666.       IMPLICIT INTEGER*2 ( a - z )
  667.  
  668.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  669.       COMMON        SortArray(2,43), SortBackup(2,43),
  670.      +              BarLength, BarColor, Select
  671.  
  672. C
  673. C     Set comparison offset to half the number of records in SortArray.
  674. C
  675.       Offset = MaxBars / 2
  676.       DO WHILE( Offset .GT. 0 )
  677.          Limit  = MaxBars - Offset
  678.          Switch = 1
  679.          DO WHILE( Switch .GT. 0 )
  680.  
  681. C
  682. C           Assume no switches at this offset.
  683. C
  684.             Switch = 0
  685. C
  686. C           Compare elements and switch ones out of order.
  687. C
  688.             DO Row = 1, Limit
  689.                IF( SortArray(BarLength,Row) .GT. 
  690.      +             SortArray(BarLength,Row + Offset) ) THEN
  691.                    CALL SwapSortArray( Row, Row + Offset )
  692.                    CALL SwapBars( Row, Row + Offset )
  693.                    Switch = Row
  694.                END IF
  695.             END DO
  696.  
  697. C
  698. C           Sort on next pass only to where last switch was made.
  699. C
  700.             Limit = Switch - Offset
  701.          END DO
  702. C
  703. C        No switches at last offset, try one half as big.
  704. C
  705.          Offset = Offset / 2
  706.       END DO
  707.       RETURN
  708.       END
  709.  
  710.  
  711.  
  712. CC  QuickSort - QuickSort works by picking a random "pivot" element in
  713. CC  SortArray, then moving every element that is bigger to one side of
  714. CC  the pivot, and every element that is smaller to the other side.  The
  715. CC  procedure is repeated with the two subdivisions created by the pivot.
  716. CC  When the number of elements in a subdivision reaches two, the array
  717. CC  is sorted.
  718. CC
  719. CC  Params:  Low, High - Lower and upper boundaries for sorting
  720.  
  721.       SUBROUTINE QuickSort( Low, High )
  722.       IMPLICIT INTEGER*2 ( a - z )
  723.  
  724.       PARAMETER ( LOG2MAXBARS = 6 )
  725.       INTEGER*1   StackPtr, Upper(LOG2MAXBARS), Lower(LOG2MAXBARS)
  726.       COMMON      SortArray(2,43), SortBackup(2,43),
  727.      +            BarLength, BarColor, Select
  728.  
  729.       Lower(1) = Low
  730.       Upper(1) = High
  731.       StackPtr = 1
  732.  
  733.       DO WHILE( StackPtr .GT. 0 )
  734.          IF( Lower(StackPtr) .GE. Upper(StackPtr) ) THEN
  735.             StackPtr = StackPtr - 1
  736.             CYCLE
  737.          END IF
  738. C
  739. C        Move in from both sides towards the pivot element.
  740. C
  741.          i     = Lower(StackPtr)
  742.          j     = Upper(StackPtr)
  743.          Pivot = SortArray(BarLength,j)
  744.  
  745.          DO WHILE( i .LT. j )
  746.             DO WHILE( (i .LT. j)  .AND.
  747.      +                (SortArray(BarLength,i) .LE. Pivot) )
  748.                i = i + 1
  749.             END DO
  750.  
  751.             DO WHILE( (j .GT. i)  .AND.
  752.      +                (SortArray(BarLength,j) .GE. Pivot ) )
  753.                j = j - 1
  754.             END DO
  755. C
  756. C           If the pivot element is not yet reached, it means that two
  757. C           elements on either side are out of order, so swap them.
  758. C
  759.             IF( i .LT. j ) THEN
  760.                CALL SwapSortArray( i, j )
  761.                CALL SwapBars( i, j )
  762.             END IF
  763.          END DO
  764.  
  765. C
  766. C        Move the pivot element back to its proper place in the array.
  767. C
  768.          j = Upper(StackPtr)
  769.          CALL SwapSortArray( i, j )
  770.          CALL SwapBars( i, j )
  771.  
  772.          IF( (i - Lower(StackPtr)) .LT. (Upper(StackPtr) - i) ) THEN
  773.             Lower(StackPtr + 1) = Lower(StackPtr)
  774.             Upper(StackPtr + 1) = i - 1
  775.             Lower(StackPtr)     = i + 1
  776.          ELSE
  777.             Lower(StackPtr + 1) = i + 1
  778.             Upper(StackPtr + 1) = Upper(StackPtr)
  779.             Upper(StackPtr)     = i - 1
  780.          END IF
  781.  
  782.          StackPtr = StackPtr + 1
  783.       END DO
  784.       RETURN
  785.       END
  786.  
  787.  
  788.  
  789. CC  PrintOneBar - Displays SortArray(BarLength,Row) at the row indicated
  790. CC  by the Row parameter, using the color in SortArray(BarColor,Row).
  791. CC  The VioWrtNCell display function assumes row numbering begins with
  792. CC  0 instead of 1; therefore, the value passed to this function is 1
  793. CC  less than the value of Row.
  794. CC
  795. CC  Params:  Row
  796.  
  797.       SUBROUTINE PrintOneBar( Row )
  798.       IMPLICIT INTEGER*2 ( a - z )
  799.  
  800.       INTEGER*1     cell(2), BLOCK, SPACE, COLOR
  801.       PARAMETER   ( BLOCK = '▀', SPACE = ' ', COLOR = 7 )
  802.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  803.       COMMON        SortArray(2,43), SortBackup(2,43),
  804.      +              BarLength, BarColor, Select
  805.  
  806.       cell(1) = BLOCK
  807.       cell(2) = SortArray(BarColor,Row)
  808.       dummy   = VioWrtNCell( cell, SortArray(BarLength,Row),
  809.      +                       Row - 1, 1, 0 )
  810.       blanks  = MaxBars - SortArray(BarLength,Row)
  811.       IF( blanks .GT. 0 ) THEN
  812.          cell(1) = SPACE
  813.          cell(2) = COLOR
  814.          dummy   = VioWrtNCell( cell, blanks, Row - 1,
  815.      +                          SortArray(BarLength,Row) + 1, 0 )
  816.       END IF
  817.       RETURN
  818.       END
  819.  
  820.  
  821.  
  822. CC  Reinitialize - Restores the array SortArray to its original unsorted
  823. CC  state while displaying the unsorted bars.
  824. CC
  825. CC  Params:  None
  826. CC
  827. CC  Uses:    time0 - Starting time for sort
  828.  
  829.       SUBROUTINE Reinitialize
  830.       IMPLICIT INTEGER*2 ( a - z )
  831.  
  832.       INTEGER*4     time0
  833.       COMMON /misc/ MaxBars, MaxColors, Sound, Pause
  834.       COMMON /time/ time0
  835.       COMMON        SortArray(2,43), SortBackup(2,43),
  836.      +              BarLength, BarColor, Select
  837.  
  838.       DO row = 1, MaxBars
  839.          SortArray(BarLength,row) = SortBackup(BarLength,row)
  840.          SortArray(BarColor,row)  = SortBackup(BarColor,row)
  841.          CALL PrintOneBar( row )
  842.       END DO
  843.  
  844.       CALL GETTIM( Hour, Minute, Second, Hundredth )
  845.       time0 = Hour   * 360000 +
  846.      +        Minute * 6000   +
  847.      +        Second * 100    +
  848.      +        Hundredth
  849.       RETURN
  850.       END
  851.  
  852.  
  853.  
  854. CC  SortMenu - The SortMenu procedure first calls the Reinitialize
  855. CC  procedure to make sure the SortArray is in its unsorted form,
  856. CC  then prompts for one of the following selections:
  857. CC
  858. CC           *  One of the sorting algorithms
  859. CC           *  Toggle sound on or off
  860. CC           *  Increase or decrease speed
  861. CC           *  End the program
  862. CC
  863. CC  Params:  None
  864.  
  865.       SUBROUTINE SortMenu
  866.       IMPLICIT INTEGER*2 ( a - z )
  867.  
  868.       INCLUDE 'BSE.FD'
  869.  
  870.       PARAMETER         ( FIRSTMENU = 1, NLINES = 18, SPACE = 32 )
  871.       CHARACTER*1         inkey
  872.       LOGICAL             Sound
  873.       RECORD /KBDKEYINFO/ kbd
  874.       COMMON /misc/       MaxBars, MaxColors, Sound, Pause
  875.       COMMON              SortArray(2,43), SortBackup(2,43),
  876.      +                    BarLength, BarColor, Select
  877.  
  878. C
  879. C     Locate the cursor
  880. C
  881.       dummy = VioSetCurPos( FIRSTMENU + NLINES, 75, 0 )
  882.  
  883.       DO WHILE( .TRUE. )
  884.          dummy = KbdCharIn( kbd, 0, 0 )
  885.          inkey = kbd.chChar
  886.  
  887. C
  888. C        Make input character upper case for easier comparisons.
  889. C
  890.          IF( LGE( inkey, 'a' )  .AND.  LLE( inkey, 'z' ) )
  891.      +      inkey = CHAR( ICHAR( inkey ) - SPACE )
  892.  
  893. C
  894. C        Branch to the appropriate procedure depending on the key typed.
  895. C
  896.          IF( inkey .EQ. 'I' ) THEN
  897.             Select = 0
  898.             CALL Reinitialize
  899.             CALL InsertionSort
  900.             CALL ElapsedTime( 0 )
  901.  
  902.          ELSEIF( inkey .EQ. 'B' ) THEN
  903.             Select = 1
  904.             CALL Reinitialize
  905.             CALL BubbleSort
  906.             CALL ElapsedTime( 0 )
  907.  
  908.          ELSEIF( inkey .EQ. 'H' ) THEN
  909.             Select = 2
  910.             CALL Reinitialize
  911.             CALL HeapSort
  912.             CALL ElapsedTime( 0 )
  913.  
  914.          ELSEIF( inkey .EQ. 'E' ) THEN
  915.             Select = 3
  916.             CALL Reinitialize
  917.             CALL ExchangeSort
  918.             CALL ElapsedTime( 0 )
  919.  
  920.          ELSEIF( inkey .EQ. 'S' ) THEN
  921.             Select = 4
  922.             CALL Reinitialize
  923.             CALL ShellSort
  924.             CALL ElapsedTime( 0 )
  925.  
  926.          ELSEIF( inkey .EQ. 'Q' ) THEN
  927.             Select = 5
  928.             CALL Reinitialize
  929.             CALL QuickSort( 1, MaxBars )
  930.             CALL ElapsedTime( 0 )
  931.  
  932. C
  933. C        If 'T', toggle the sound, then redraw the menu to clear any
  934. C        timing results since they won't compare with future results.
  935. C
  936.          ELSEIF( inkey .EQ. 'T' ) THEN
  937.             Sound = .NOT. Sound
  938.             CALL Boxinit
  939.  
  940. C
  941. C        If '<', increase pause length to slow down sorting time, then
  942. C        redraw the menu to clear any timing results since they won't
  943. C        compare with future results.
  944. C
  945.          ELSEIF( inkey .EQ. '<'  .AND.  Pause .NE. 900 ) THEN
  946.             Pause = Pause + 30
  947.             CALL BoxInit
  948.  
  949. C
  950. C        If '>', decrease pause length to speed up sorting time, then
  951. C        redraw the menu to clear any timing results since they won't
  952. C        compare with future results.
  953. C
  954.          ELSEIF( inkey .EQ. '>'  .AND.  Pause .NE. 0 ) THEN
  955.             Pause = Pause - 30
  956.             CALL BoxInit
  957.  
  958. C
  959. C        If ESC key, exit loop and return.
  960. C
  961.          ELSEIF( inkey .EQ. CHAR( 27 ) ) THEN
  962.             EXIT
  963.          END IF
  964.  
  965.       END DO
  966.       RETURN
  967.       END
  968.  
  969.  
  970.  
  971. CC  SwapBars - Calls PrintOneBar twice to switch the two bars in Row1
  972. CC  and Row2, then calls the ElapsedTime procedure.
  973. CC
  974. CC  Params:  Row1, Row2
  975.  
  976.       SUBROUTINE SwapBars( Row1, Row2 )
  977.       IMPLICIT INTEGER*2 ( a - z )
  978.  
  979.       CALL PrintOneBar( Row1 )
  980.       CALL PrintOneBar( Row2 )
  981.       CALL ElapsedTime( Row1 )
  982.       RETURN
  983.       END
  984.  
  985.  
  986.  
  987. CC  SwapSortArray - Swaps color and length for two bars by exchanging
  988. CC  elements i and j in both rows of SortArray.  Row 1 of SortArray
  989. CC  holds bar lengths and row 2 holds bar colors.
  990. CC
  991. CC  Params:  i, j - Element numbers for bars to be swapped
  992.  
  993.       SUBROUTINE SwapSortArray( i, j )
  994.       IMPLICIT INTEGER*2 ( a - z )
  995.  
  996.       COMMON   SortArray(2,43), SortBackup(2,43),
  997.      +         BarLength, BarColor, Select
  998.  
  999.       temp           = SortArray(1,i)
  1000.       SortArray(1,i) = SortArray(1,j)
  1001.       SortArray(1,j) = temp
  1002.       temp           = SortArray(2,i)
  1003.       SortArray(2,i) = SortArray(2,j)
  1004.       SortArray(2,j) = temp
  1005.       RETURN
  1006.       END
  1007.  
  1008.  
  1009.  
  1010. CC  cls - Clears screen using a normal display attribute of 7.
  1011. CC
  1012. CC  Params:  None
  1013.  
  1014.       SUBROUTINE cls
  1015.       IMPLICIT INTEGER*2 ( a - z )
  1016.  
  1017.       INTEGER*1 cell(2)  / ' ', 7 /
  1018.  
  1019.       dummy = VioScrollDn( 0, 0, -1, -1, -1, cell, 0 )
  1020.       RETURN
  1021.       END
  1022.