ShellSort
From Pickwiki
Jump to navigationJump to search* sort1 sorts a dynamic array by the requested delimiter
************************************************************************
SUBROUTINE SORT1 (ARRAY, DELIM, SORTTYPE)
************************************************************************
* Modifications since date stamp
* ******************************
* None at present.
* 07/05/96 : Swap routine made much simpler and shorter. Rewrite done due
* to a bug when sorting numbers left justified.
* NOTE
* ****
* awy Jun93 : This uses the Shell sort (named after Donald Shell at IBM)
* It is a general-purpose, pretty efficient sort, and by
* using matrices is quite fast. It works by comparing and
* swapping if necessary items which are 'n' places apart.
* 'n' starts at half the total number of items and is halved
* for each pass. This makes it an n-log(n) sort. There are a
* variety of rules about how to 'tweak' it, but this version
* is pretty crude.
FIELDCOUNT = DCOUNT(ARRAY, DELIM)
IF FIELDCOUNT LT 2 THEN RETURN ;* No point sorting 0 or 1
* Convert dynamic array into matrix
DIMENSION MATRIX(FIELDCOUNT)
MATPARSE MATRIX FROM ARRAY, DELIM
* Set up ascend/descent, justify, and start interval
AD = SORTTYPE[1,1]
LR = SORTTYPE[2,1]
INTERVAL = INT(FIELDCOUNT*0.5)
* Now to business - the outer LOOP continues until the swap interval
* has been through 1 to become zero. The inner FOR 'bubbles' each entry
* up as far as it will go by calling SWAP
LOOP UNTIL INTERVAL EQ 0
FOR BUBBLE = INTERVAL+1 TO FIELDCOUNT
SWAPVAR = BUBBLE
GOSUB SWAP:
NEXT
INTERVAL = INT(INTERVAL*0.5)
REPEAT
* Now rebuild dynamic array and return
* MATBUILD ARRAY FROM MATRIX USING DELIM ;* Doesn't work - infobasic bug
MATBUILD ARRAY FROM MATRIX USING @IM
CONVERT @IM TO DELIM IN ARRAY
RETURN
********************************
* This simply compares the current entry with the entry INTERVAL before.
* If it is in the correct order, or the current entry is too close to the
* top it returns. Otherwise it swaps the two entries, and loops to see if
* it can move the current entry even higher.
SWAP:
LOOP
COMPVAR = SWAPVAR - INTERVAL
IF COMPVAR LT 1 THEN RETURN
IF LR EQ 'R'
THEN COMPVALUE = COMPARE( MATRIX(SWAPVAR), MATRIX( COMPVAR), "R")
ELSE COMPVALUE = COMPARE( MATRIX(SWAPVAR), MATRIX( COMPVAR), "L")
IF AD EQ "D" THEN COMPVALUE = 0 - COMPVALUE
IF COMPVALUE GE 0 THEN RETURN
TEMP = MATRIX(COMPVAR)
MATRIX(COMPVAR) = MATRIX(SWAPVAR)
MATRIX(SWAPVAR) = TEMP
SWAPVAR = COMPVAR
REPEAT
END