Author Topic: Russian Sorting Halves Danilin  (Read 13370 times)

0 Members and 1 Guest are viewing this topic.

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Russian Sorting Halves Danilin
« on: October 15, 2018, 07:40:40 pm »
Russian Sorting Halves and fast and human
sorts 1'000'000 in 2.2 seconds

number of elements is written to file with c:/N.txt or use variable n
array d(n) can be read from a file or synthesized in a program

Code: QB64: [Select]
  1. ' Russian Sorting Halves Danilin
  2.  
  3. DECLARE SUB RussianSortingHalvesDAV (ab!, yz!, part!, age!)
  4. OPEN "c:/N.txt" FOR INPUT AS #1
  5. INPUT #1, n
  6. 'n=1234567
  7. age = 1 + LOG(n) / LOG(2)
  8.  
  9. DIM SHARED d(n) 'AS LONG
  10. DIM SHARED a(n) 'AS LONG
  11.  
  12. 'OPEN "c:/ISX.txt" FOR INPUT AS #2
  13. 'FOR i=1 TO n: INPUT #2, d(i): NEXT
  14.  
  15. 'FOR i = 1 TO n: d(i) = n - i + 1: NEXT ' INT(RND*n)
  16. FOR i = 1 TO n: d(i) = INT(RND * n): NEXT '
  17.  
  18. FOR k = 1 TO 20: PRINT d(k);: NEXT: PRINT: PRINT
  19. FOR k = n - 19 TO n: PRINT d(k);: NEXT: PRINT: PRINT
  20.  
  21. start = TIMER
  22.  
  23. IF age > 0 THEN
  24.     CALL RussianSortingHalvesDAV(1, n, 1, age)
  25.  
  26. finish = TIMER
  27.  
  28. PRINT finish - start; "second ": PRINT
  29.  
  30. OPEN "c:/=RuSortHalves_dav.txt" FOR OUTPUT AS #3
  31. PRINT #3, finish - start; "second "
  32. PRINT #3, n; "elements", "RECURSION"
  33. FOR i = 1 TO 22: PRINT #3, d(i): NEXT
  34. FOR i = n - 22 TO n: PRINT #3, d(i): NEXT
  35.  
  36. FOR k = 1 TO 20: PRINT d(k);: NEXT: PRINT: PRINT
  37. FOR k = n - 19 TO n: PRINT d(k);: NEXT: PRINT: PRINT
  38.  
  39.  
  40. SUB RussianSortingHalvesDAV (ab, yz, part, age)
  41.  
  42. IF yz - ab < 1 THEN EXIT SUB
  43.  
  44. FOR i = ab TO yz
  45.     summa = summa + d(i)
  46. middle = summa / (yz - ab + 1)
  47.  
  48. abc = ab - 1
  49. xyz = yz + 1
  50.  
  51. FOR i = ab TO yz
  52.     IF d(i) < middle THEN abc = abc + 1: a(abc) = d(i): ELSE xyz = xyz - 1: a(xyz) = d(i)
  53.  
  54. FOR i = ab TO yz: d(i) = a(i): NEXT
  55.  
  56. IF part < age THEN
  57.     IF abc >= ab THEN CALL RussianSortingHalvesDAV(ab, abc, part + 1, age)
  58.     IF xyz <= yz THEN CALL RussianSortingHalvesDAV(xyz, yz, part + 1, age)
  59.  
  60.  

Russian Sorting Halves Danilin visualisation



http://kenokeno.ucoz.ru/win/rusortpol10.gif

  [ You are not allowed to view this attachment ]  
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #1 on: October 15, 2018, 08:30:26 pm »
Welcome to the forum DANILIN,

Let me guess, you are running in Linux. Can't remember last time Windows let us print to root, c:\

Are files really necessary?

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #2 on: October 15, 2018, 09:35:17 pm »
With a couple mods, no. I found this sort for n=1234567 to be slower by considerable margins than even the visualized version of FlashSort.
Code: QB64: [Select]
  1. TYPE SortRec
  2.     Swaps AS DOUBLE
  3.     compares AS DOUBLE
  4.     writes AS DOUBLE
  5.     timestart AS DOUBLE
  6.     timeend AS DOUBLE
  7.     accumulatedtime AS DOUBLE
  8.     runs AS SINGLE
  9.     NSorted AS DOUBLE
  10.     retrievals AS DOUBLE
  11.     NotSwapped AS DOUBLE
  12.     title AS STRING * 256
  13.     sorttocall AS INTEGER
  14.  
  15. TYPE PixelRec
  16.     pcolor AS INTEGER
  17.     pixnum AS LONG
  18. DIM SHARED Sorts(0 TO 255) AS SortRec
  19. DIM SHARED SortNum
  20. DIM SHARED numcolors%
  21. maxscreenx = 1366
  22. maxscreeny = 768
  23. numcolors% = 256
  24. n& = (maxscreenx * maxscreeny)
  25. DIM SHARED Pixels(0 TO n& - 1) AS PixelRec
  26. SCREEN _NEWIMAGE(maxscreenx, maxscreeny, numcolors%)
  27. DIM t AS SortRec
  28. '* OpenFile t, "r", channel%, "stats.txt"
  29. 'DO
  30. '    IF i& > LOF(channel%) \ LEN(t) THEN
  31. '        EXIT DO
  32. '    ELSE
  33. '        i& = i& + 1
  34. '        GET #channel%, i&, t
  35. '        Sorts(i&) = t
  36. '    END IF
  37. 'LOOP
  38. lastsort% = -1
  39.     SortNum = 3 'INT(RND * 19)
  40.     Sorts(SortNum).sorttocall = SortNum
  41.     SELECT CASE SortNum
  42.         CASE 1
  43.             HandleSort Sorts(), "QuickSort (Recursive) -- CAR Hoare", 0, n& - 1, maxscreenx
  44.         CASE 2
  45.             HandleSort Sorts(), "ShellSort (Metzler Variant) -- (DL Shell) with improvement by Donald Metzler and seal of approval by Donald knuth", 0, n& - 1, maxscreenx
  46.         CASE 3
  47.             HandleSort Sorts(), "FlashSort -- (Karl Dietrich Neubert) non-comparison sort really fast", 1, n& - 1, maxscreenx
  48.         CASE 4
  49.             HandleSort Sorts(), "Radix Sort -- Jon Von Neumann", 0, n& - 1, maxscreenx
  50.         CASE 5
  51.             HandleSort Sorts(), "Shell Sort (Original) -- (DL Shell)", 0, (n& - 1) \ 8, maxscreenx
  52.         CASE 6
  53.             HandleSort Sorts(), "Shell Sort (Single pass per gap - shrink factor = 1.247...) -- (DL Shell)", 0, n& - 1, maxscreenx
  54.         CASE 7
  55.             HandleSort Sorts(), "HeapSort -- (BR Heap)", 0, n& - 1, maxscreenx
  56.         CASE 8
  57.             HandleSort Sorts(), "CombSort  -- Wlodzimierz Dobosiewicz (later, Lacey, Box)", 0, n& - 1, maxscreenx
  58.         CASE 9
  59.             HandleSort Sorts(), "ShearSort -- some CompuGeeks", 0, 16 * maxscreenx - 1, maxscreenx
  60.             ResetScreen% = -1
  61.         CASE 10
  62.             HandleSort Sorts(), "PostSort -- Your Local Mailman", 0, n& - 1, maxscreenx
  63.         CASE 11
  64.             BatcherScreenX& = 1
  65.             DO
  66.                 IF BatcherScreenX& * 2 > maxscreenx THEN
  67.                     EXIT DO
  68.                 ELSE
  69.                     BatcherScreenX& = BatcherScreenX& * 2
  70.                 END IF
  71.             LOOP
  72.             BatcherScreenY& = 1
  73.             DO
  74.                 IF BatcherScreenY& * 2 > maxscreeny THEN
  75.                     EXIT DO
  76.                 ELSE
  77.                     BatcherScreenY& = BatcherScreenY& * 2
  78.                 END IF
  79.             LOOP
  80.             xy& = BatcherScreenX& * BatcherScreenY&
  81.             HandleSort Sorts(), "Batcher Odd-even MergeSort -- Kenneth E Batcher", 0, xy& - 1, BatcherScreenX&
  82.             ResetScreen% = -1
  83.         CASE 12
  84.             HandleSort Sorts(), "Bucket Sort -- Bucky T (not really)", 0, n& - 1, maxscreenx
  85.         CASE 13
  86.             HandleSort Sorts(), "MergeSort (recursive)", 0, n& - 1, maxscreenx
  87.         CASE 14
  88.             HandleSort Sorts(), "QuickSort Recursive (Stable) -- CAR Hoare, Codeguy!", 0, n& - 1, maxscreenx
  89.         CASE 15
  90.             HandleSort Sorts(), "QuickSort Iterative -- CAR Hoare", 0, n& - 1, maxscreenx
  91.         CASE 16
  92.             HandleSort Sorts(), "MergeExperiment -- ** codeguy! **", 0, n& - 1, maxscreenx
  93.         CASE 17
  94.             HandleSort Sorts(), "Bidirectional ShellSort -- guys in white coats & codeguy", 0, n& - 1, maxscreenx
  95.         CASE 18
  96.             HandleSort Sorts(), "CodeGuySort -- Who Knows but it works -- and fast -- invented by codeguy", 0, n& - 1, maxscreenx
  97.         CASE 19
  98.             HandleSort Sorts(), "Prime Gap Sort -- codeguy", 0, n& - 1, maxscreenx
  99.         CASE 20
  100.             HandleSort Sorts(), "QuickStepRecursive", 0, n& - 1, maxscreenx
  101.         CASE 97
  102.             HandleSort Sorts(), "Tree Sort Ascending -- the keebler elves", 0, 2 * (n& - 1) \ 8, maxscreenx
  103.         CASE 98
  104.             HandleSort Sorts(), "OESort", 0, n& - 1, maxscreenx
  105.         CASE 99
  106.             HandleSort Sorts(), "JSort -- Some guy named J", 0, (n& - 1) \ 16, maxscreenx
  107.         CASE ELSE
  108.             HandleSort Sorts(), "CodeGuySort -- Who Knows but it works -- and fast -- invented by codeguy", 0, n& - 1, maxscreenx
  109.     END SELECT
  110.     IF SortNum <> lastsort% THEN
  111.         IF ResetScreen% THEN
  112.             SCREEN _NEWIMAGE(maxscreenx, maxscreeny, numcolors%)
  113.             ResetScreen% = 0
  114.             lastsort% = SortNum
  115.         END IF
  116.     END IF
  117.     x$ = INKEY$
  118.     IF x$ = "\" THEN
  119.         EXIT DO
  120.     END IF
  121. nprinted = 0: GetRawSpeed% = -1
  122. FOR i = 0 TO UBOUND(sorts)
  123.     IF Sorts(i).runs > 0 THEN
  124.         IF Sorts(i).accumulatedtime > 0 THEN
  125.             IF Sorts(i).NSorted > 0 THEN
  126.                 LOCATE nprinted \ 2 + 1, (nprinted MOD 2) * 40 + 1
  127.                 PRINT USING "SpeedIndex(lo=fast)####.####:"; SpeedIndex#(Sorts(i), 0, n& - 1, GetRawSpeed%, tstart#, tend#, maxscreenx)
  128.                 PRINT USING "Swaps    ###,###,###,###,###:"; Sorts(i).Swaps
  129.                 PRINT USING "comparisons#,###,###,###,###:"; Sorts(i).compares
  130.                 PRINT USING "writes     #,###,###,###,###:"; Sorts(i).writes
  131.                 PRINT USING "10000(acc)time##,###,###,###:"; Sorts(i).accumulatedtime * 10000
  132.                 PRINT USING "times executed##,###,###,###:"; Sorts(i).runs
  133.                 PRINT USING "items sorted ###,###,###,###:"; Sorts(i).NSorted
  134.                 PRINT USING "NRetrievals#,###,###,###,###:"; Sorts(i).retrievals
  135.                 PRINT USING "Not Swapped#,###,###,###,###:"; Sorts(i).NotSwapped
  136.                 PRINT USING "Items/sec##,###,###,###.####:"; Sorts(i).NSorted / Sorts(i).accumulatedtime
  137.                 PRINT USING "time(start)  ##,###,###.####:"; Sorts(i).timestart
  138.                 PRINT USING "time(end)    ##,###,###.####:"; Sorts(i).timeend
  139.                 PRINT LTRIM$(RTRIM$(Sorts(i).title))
  140.                 PRINT STRING$(100, "-")
  141.                 nprinted = nprinted + 1
  142.             END IF
  143.         END IF
  144.     END IF
  145.     '* PUT #channel%, i, Sorts(i)
  146. '* OpenFile t, "c", channel%, "stats.txt"
  147.     x$ = INKEY$
  148. LOOP UNTIL x$ = ""
  149.     x$ = INKEY$
  150. LOOP UNTIL x$ = CHR$(27)
  151.  
  152. SUB OpenFile (rec AS SortRec, mode$, channel%, f$)
  153.     channel% = FREEFILE
  154.     IF channel% > 0 THEN
  155.         SELECT CASE mode$
  156.             CASE "r"
  157.                 OPEN f$ FOR RANDOM AS channel% LEN = LEN(rec)
  158.             CASE "o"
  159.                 OPEN f$ FOR OUTPUT AS channel%
  160.             CASE "a"
  161.                 OPEN f$ FOR APPEND AS channel%
  162.             CASE "i"
  163.                 OPEN f$ FOR INPUT AS channel%
  164.             CASE "c"
  165.                 IF channel% > 0 THEN
  166.                     CLOSE channel%
  167.                 END IF
  168.         END SELECT
  169.     END IF
  170. SUB HandleSort (s() AS SortRec, x$, start&, finish&, maxw)
  171.     SortNum = s(SortNum).sorttocall
  172.     s(SortNum).title = "[" + LTRIM$(STR$(SortNum)) + "]" + x$
  173.     s(SortNum).sorttocall = SortNum
  174.     _TITLE Sorts(SortNum).title
  175.     s(SortNum).NSorted = s(SortNum).NSorted + finish& - start& + 1
  176.     SCREEN _NEWIMAGE(maxw, (finish& - start& + 1) / maxw, numcolors%)
  177.     FOR i& = start& TO finish&
  178.         Pixels(i&).pcolor = INT(RND * numcolors%) + 1
  179.         Pixels(i&).pixnum = i&
  180.         PixelSet i&, maxw, Pixels(i&).pcolor
  181.     NEXT
  182.     s(SortNum).timestart = TIMER
  183.     SELECT CASE SortNum
  184.         CASE 1
  185.             QuickSort start&, finish&, maxw
  186.         CASE 2
  187.             ShellSortMetzler start&, finish&, maxw
  188.         CASE 3
  189.             FlashSort start&, finish&, maxw
  190.         CASE 4
  191.             RadixSort start&, finish&, maxw
  192.         CASE 5
  193.             ShellSort start&, finish&, maxw
  194.         CASE 6
  195.             ShellSortSinglepass start&, finish&, maxw
  196.         CASE 7
  197.             HeapSort start&, finish&, maxw
  198.         CASE 8
  199.             CombSort start&, finish&, maxw
  200.         CASE 9
  201.             ShearSort start&, finish&, maxw
  202.             ResetScreen% = -1
  203.         CASE 10
  204.             PostSort start&, finish&, maxw
  205.         CASE 11
  206.             BatcherOddEvenMergeSort start&, finish&, maxw
  207.             ResetScreen% = -1
  208.         CASE 12
  209.             BucketSort start&, finish&, maxw
  210.         CASE 13
  211.             MergeSort start&, finish&, maxw
  212.         CASE 14
  213.             QuickSortRStable Pixels(), start&, finish&, maxw
  214.         CASE 15
  215.             QuickSortIterative start&, finish&, maxw
  216.         CASE 16
  217.             MergeExperiment start&, finish&, maxw
  218.         CASE 17
  219.             BidirectionalShellSort start&, finish&, maxw
  220.         CASE 18
  221.             CodeGuySort start&, finish&, maxw
  222.         CASE 19
  223.             PrimeGapSort start&, finish&, maxw
  224.         CASE 20
  225.             QuickStepRecursive start&, finish&, 2, maxw
  226.             QuickStepRecursive start&, finish&, 1, maxw
  227.         CASE 97
  228.             TreeSortAscending start&, finish&, maxw
  229.         CASE 98
  230.             OESort start&, finish&, maxw
  231.         CASE 99
  232.             JSort start&, finish&, maxw
  233.         CASE ELSE
  234.             CodeGuySort start&, finish&, maxw
  235.     END SELECT
  236.     s(SortNum).timeend = TIMER
  237.     s(SortNum).runs = s(SortNum).runs + 1
  238.     IF s(SortNum).timeend < s(SortNum).timestart THEN
  239.         s(SortNum).accumulatedtime = s(SortNum).accumulatedtime + (s(SortNum).timeend - s(SortNum).timestart) + 86400
  240.     ELSE
  241.         s(SortNum).accumulatedtime = s(SortNum).accumulatedtime + s(SortNum).timeend - s(SortNum).timestart
  242.     END IF
  243. SUB SetRandomPixels (p() AS PixelRec, start&, finish&, maxw)
  244.     FOR i& = start& TO finish&
  245.         Pixels(i&).pixnum = i&
  246.         Pixels(i&).pcolor = INT(RND * numcolors%) + 1
  247.     NEXT
  248.  
  249. SUB QuickSort (start&, finish&, maxw)
  250.     IF finish& - start& = 1 THEN
  251.         IF LessThan%(CompareScreen%(finish&, start&, maxw)) THEN
  252.             PixelSwap start&, finish&, maxw
  253.         END IF
  254.     ELSE
  255.         IF finish& - start& > 1 THEN
  256.             i& = start&
  257.             j& = finish&
  258.             m% = GetPixel%(i& + RND * (j& - i& + 1), maxw)
  259.             DO
  260.                 WHILE GetPixel%(i&, maxw) < m%
  261.                     i& = i& + 1
  262.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  263.                 WEND
  264.                 WHILE GetPixel%(j&, maxw) > m%
  265.                     j& = j& - 1
  266.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  267.                 WEND
  268.                 IF i& < j& THEN
  269.                     PixelSwap i&, j&, maxw
  270.                 END IF
  271.                 i& = i& + 1
  272.                 j& = j& - 1
  273.             LOOP UNTIL i& > j&
  274.             QuickSort i&, finish&, maxw
  275.             QuickSort start&, j&, maxw
  276.         END IF
  277.     END IF
  278.  
  279. '* Radix sort is akin to Postman's sort, however instead of sorting items after they've been inserted into their proper "boxes,"
  280. '* another pass is made using the next character (in this case bit) of the sortation key. bits& can be changed to the number of
  281. '* characters in the sorting key (Field length). RadixSort also has a linear running time, but requires extra storage in exchange
  282. '* for speed. RadixSort is not a true comparison sort. It's actually more of a computed distribution sort than anything else. RadixSort
  283. '* in this implementation is Stable. Speed... Stability... Linear running time... (Hmmm...)
  284.  
  285. SUB RadixSort (Start&, Finish&, maxw)
  286.     'ChangeTitleBar "RadixSort ****"
  287.     FOR i& = Start& TO Finish&
  288.         t% = GetPixel%(i&, maxw)
  289.         IF t% > h% THEN
  290.             h% = t%
  291.         END IF
  292.     NEXT
  293.     DIM PsCount%(0 TO h%, Start& TO Finish&), ct&(h%), Pow2&(32)
  294.     bits& = LOG(h% + 2) \ LOG(2) + 1
  295.     FOR i = 0 TO bits&
  296.         Pow2&(i) = 2 ^ i
  297.     NEXT
  298.     FOR j& = 0 TO bits&
  299.         FOR i& = Start& TO Finish&
  300.             a% = GetPixel%(i&, maxw)
  301.             x% = a% AND Pow2&(j&)
  302.             PsCount%(x%, ct&(x%)) = a%
  303.             ct&(x%) = ct&(x%) + 1
  304.         NEXT
  305.         index& = Start&
  306.         FOR u% = 0 TO h%
  307.             FOR i& = 0 TO ct&(u%) - 1
  308.                 PixelSet index&, maxw, PsCount%(u%, i&)
  309.                 index& = index& + 1
  310.             NEXT
  311.             ct&(u%) = 0
  312.         NEXT
  313.     NEXT
  314.  
  315. '* this is dl shell's sort but modified for faster running time than standard shellsort.
  316. SUB ShellSortMetzler (Start&, Finish&, maxw)
  317.     m& = Metzler&(Start&, Finish&)
  318.     WHILE m& > 0
  319.         FOR j& = Start& TO Finish& - m&
  320.             l& = j& + m&
  321.             B% = GetPixel%(l&, maxw)
  322.             FOR i& = j& TO Start& STEP -m&
  323.                 IF GetPixel%(i&, maxw) > B% THEN
  324.                     PixelSwap i& + m&, i&, maxw
  325.                     l& = i&
  326.                 ELSE
  327.                     i& = Start&
  328.                 END IF
  329.                 Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  330.             NEXT
  331.             PixelSet l&, maxw, B%
  332.         NEXT
  333.         m& = (m& - 1) \ 3
  334.     WEND
  335.  
  336. FUNCTION Metzler& (a&, b&)
  337.     x& = (b& - a& + 1) \ 3
  338.     s& = 0
  339.     DO
  340.         IF x& < 1 THEN
  341.             EXIT DO
  342.         ELSE
  343.             s& = 3 * s& + 1
  344.             x& = (x& - 1) \ 3
  345.         END IF
  346.     LOOP
  347.     Metzler& = s&
  348.  
  349. SUB ShellSort (start, finish&, maxw)
  350.     Gap& = (finish& - Start& + 1)
  351.     DO
  352.         st& = Start&: b& = st&
  353.         ends& = finish& - Gap&: a& = ends&
  354.         DO
  355.             st& = b&
  356.             ends& = a&
  357.             a& = st&
  358.             b& = ends&
  359.             FOR i& = st& TO ends&
  360.                 IF GetPixel%(i&, maxw) > GetPixel%(i& + Gap&, maxw) THEN
  361.                     PixelSwap i&, i& + Gap&, maxw
  362.                     a& = i&
  363.                     IF i& < b& THEN
  364.                         b& = i&
  365.                     END IF
  366.                 END IF
  367.             NEXT
  368.         LOOP WHILE (a& > st&) ' OR (b& = ends&)
  369.         Gap& = Gap& \ 2
  370.         st& = Start&
  371.         ends& = finish& - Gap&
  372.     LOOP UNTIL Gap& < 1
  373.  
  374. SUB ShellSortSinglepass (start&, finish&, maxw)
  375.     Gap& = (finish& - start& + 1) \ 1.247#
  376.     DO
  377.         FOR i& = start& TO finish& - Gap&
  378.             IF CompareScreen%(i&, i& + Gap&, maxw) = 1 THEN
  379.                 PixelSwap i&, i& + Gap&, maxw
  380.             END IF
  381.         NEXT
  382.         Gap& = INT(Gap& / 1.247#)
  383.     LOOP UNTIL Gap& < 1
  384.  
  385. SUB FlashSort (Start&, finish&, maxw)
  386.     m& = .128 * finish&
  387.     DIM L(m&), a(Start& TO finish&)
  388.     nmax& = Start&
  389.     minptr& = Start&
  390.     FOR i& = Start& TO finish&
  391.         a(i&) = GetPixel%(i&, maxw)
  392.         IF CompareScreen%(i&, minptr&, maxw) = -1 THEN minptr& = i&
  393.         IF CompareScreen%(i&, nmax&, maxw) = 1 THEN nmax& = i&
  394.     NEXT i&
  395.     IF CompareScreen%(minptr&, nmax&, maxw) = 0 THEN EXIT SUB
  396.     C1# = (m& - 1) / (a(nmax&) - a(minptr&))
  397.     FOR k& = 1 TO m&
  398.         L(k&) = 0
  399.     NEXT k&
  400.     FOR i& = Start& TO finish&
  401.         k& = 1 + INT(C1# * (a(i&) - a(minptr&)))
  402.         L(k&) = L(k&) + 1
  403.     NEXT i&
  404.     FOR k& = 2 TO m&
  405.         L(k&) = L(k&) + L(k& - 1)
  406.     NEXT k&
  407.     anmin% = a(minptr&)
  408.     hold% = a(nmax&)
  409.     a(nmax&) = a(Start&)
  410.     a(Start&) = hold%
  411.     PixelSwap nmax&, Start&, maxw
  412.     PixelSet Start&, hold%, maxw
  413.     nmove& = 0
  414.     j& = 1
  415.     k& = m&
  416.     WHILE (nmove& < (finish& - 1))
  417.         WHILE (j& > L(k&))
  418.             j& = j& + 1
  419.             k& = 1 + INT(C1# * (a(j&) - anmin%))
  420.         WEND
  421.         flash% = a(j&)
  422.         PixelSet j&, maxw, flash%
  423.         WHILE (NOT (j& = (L(k&) + 1)))
  424.             k& = 1 + INT(C1# * (flash% - anmin%))
  425.             PixelSet L(k&), maxw, a(L(k&))
  426.             hold% = a(L(k&))
  427.             a(L(k&)) = flash%
  428.             PixelSet L(k&), maxw, flash%
  429.             flash% = hold%
  430.             L(k&) = L(k&) - 1
  431.             nmove& = nmove& + 1
  432.         WEND
  433.     WEND
  434.     FOR i& = finish& - 2 TO Start& STEP -1
  435.         IF CompareArray%(a(), i& + 1, i&) = -1 THEN
  436.             hold% = a(i&)
  437.             j& = i&
  438.             WHILE (a(j& + 1) < hold%)
  439.                 PixelSwap j&, j& + 1, maxw
  440.                 a(j&) = a(j& + 1)
  441.                 j& = j& + 1
  442.             WEND
  443.             a(j&) = hold%
  444.             PixelSet j&, maxw, hold%
  445.         END IF
  446.     NEXT i&
  447.  
  448. FUNCTION GetPixel% (i&, maxw)
  449.     col% = i& MOD maxw
  450.     row% = (i& - col%) / maxw
  451.     GetPixel% = POINT(col%, row%)
  452.     Sorts(SortNum).retrievals = Sorts(SortNum).retrievals + 1
  453.  
  454. SUB PixelSet (i&, maxw, c%)
  455.     col% = i& MOD maxw
  456.     row% = (i& - col%) / maxw
  457.     PSET (col%, row%), c%
  458.     Sorts(SortNum).writes = Sorts(SortNum).writes + 1
  459.     'Pixels(i&).pcolor = c%
  460.  
  461. SUB PixelSwap (i&, j&, maxw)
  462.     IF i& <> j& THEN
  463.         a% = GetPixel%(i&, maxw)
  464.         b% = GetPixel%(j&, maxw)
  465.         IF a% = b% THEN
  466.             Sorts(SortNum).NotSwapped = Sorts(SortNum).NotSwapped + 1
  467.         ELSE
  468.             PixelSet j&, maxw, a%
  469.             PixelSet i&, maxw, b%
  470.             Sorts(SortNum).Swaps = Sorts(SortNum).Swaps + 1
  471.             'Pixels(i&).pcolor = b%
  472.             'Pixels(j&).pcolor = a%
  473.         END IF
  474.     END IF
  475.  
  476. FUNCTION CompareScreen% (i&, j&, maxw)
  477.     s% = 0
  478.     IF GetPixel%(i&, maxw) > GetPixel%(j&, maxw) THEN
  479.         s% = 1
  480.     ELSE
  481.         IF GetPixel%(i&, maxw) < GetPixel%(j&, maxw) THEN
  482.             s% = -1
  483.         END IF
  484.     END IF
  485.     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  486.     CompareScreen% = s%
  487.  
  488. FUNCTION CompareArray% (a(), i&, j&)
  489.     s% = 0
  490.     IF a(i&) < a(j&) THEN
  491.         s% = -1
  492.     ELSE
  493.         IF a(i&) > a(j&) THEN
  494.             s% = 1
  495.         END IF
  496.     END IF
  497.     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  498.     CompareArray% = s%
  499.  
  500. FUNCTION LessThan% (a%)
  501.     s% = 0
  502.     IF a% = -1 THEN
  503.         s% = -1
  504.     END IF
  505.     LessThan% = s%
  506.  
  507. SUB QuickStepRecursive (start&, finish&, incby%, maxw)
  508.     IF finish& - start& < incby% ^ 2 THEN
  509.         IF LessThan%(CompareScreen%(finish&, start&, maxw)) THEN
  510.             PixelSwap finish&, start&, maxw
  511.         END IF
  512.     ELSE 'IF finish& - start& > incby% ^ 2 THEN
  513.         i& = start&
  514.         remainder% = (finish& - start&) MOD incby%
  515.         j& = i& + incby% * ((finish& - start& - remainder%) / incby%)
  516.         'j& = start& + incby% * ((finish& - start&) / (incby%))
  517.         middle& = i& + (j& - i&) \ (incby%)
  518.         m% = GetPixel%(middle&, maxw)
  519.         DO
  520.             WHILE GetPixel%(i&, maxw) < m% AND i& < j&
  521.                 i& = i& + incby%
  522.             WEND
  523.             WHILE GetPixel%(j&, maxw) > m% AND j& > i&
  524.                 j& = j& - incby%
  525.             WEND
  526.             IF i& < j& THEN
  527.                 PixelSwap i&, j&, maxw
  528.             END IF
  529.             i& = i& + incby%
  530.             j& = j& - incby%
  531.         LOOP UNTIL j& - i& <= incby% ^ 2
  532.         QuickStepRecursive i&, finish&, incby%, maxw
  533.         QuickStepRecursive start&, j&, incby%, maxw
  534.     END IF
  535.  
  536. FUNCTION NLOGN# (n&)
  537.     NLOGN# = n& * (LOG(n&) / LOG(2))
  538.  
  539. ' this version of HeapSort can now sort parts of lists, rather than being limited to entire lists. The one that usually appears is one that
  540. ' sorts from the beginning to the end.
  541.  
  542. SUB HeapSort (Start&, Finish&, maxw)
  543.     FOR i& = Start& + 1 TO Finish&
  544.         PercolateUp Start&, i&, maxw
  545.     NEXT i&
  546.  
  547.     FOR i& = Finish& TO Start& + 1 STEP -1
  548.         PixelSwap Start&, i&, maxw
  549.         PercolateDown Start&, i& - 1, maxw
  550.     NEXT i&
  551.  
  552.  
  553. SUB PercolateDown (Start&, MaxLevel&, maxw)
  554.     i& = Start&
  555.     ' Move the value in GetPixel%(Start&) down the heap until it has
  556.     ' reached its proper node (that is, until it is less than its parent
  557.     ' node or until it has reached MaxLevel&, the bottom of the current heap):
  558.     DO
  559.         Child& = 2 * (i& - Start&) + Start& ' Get the subscript for the Child& node.
  560.         ' Reached the bottom of the heap, so exit this procedure:
  561.         IF Child& > MaxLevel& THEN EXIT DO
  562.         ' If there are two Child nodes, find out which one is bigger:
  563.         ax& = Child& + 1
  564.         IF ax& <= MaxLevel& THEN
  565.             IF CompareScreen%(ax&, Child&, maxw) = 1 THEN
  566.                 Child& = ax&
  567.             END IF
  568.         END IF
  569.  
  570.         ' Move the value down if it is still not bigger than either one of
  571.         ' its Child&ren:
  572.         IF CompareScreen%(i&, Child&, maxw) = -1 THEN
  573.             PixelSwap i&, Child&, maxw
  574.             i& = Child&
  575.  
  576.             ' Otherwise, GetPixel%() has been restored to a heap from 0 to MaxLevel&,
  577.             ' so exit:
  578.         ELSE
  579.             EXIT DO
  580.         END IF
  581.     LOOP
  582.  
  583. SUB PercolateUp (Start&, MaxLevel&, maxw)
  584.     i& = MaxLevel&
  585.  
  586.     ' Move the value in GetPixel%(MaxLevel&, maxw) up the heap until it has
  587.     ' reached its proper node (that is, until it is greater than either
  588.     ' of its Child& nodes, or until it has reached 1, the top of the heap):
  589.     DO UNTIL i& = Start&
  590.         Parent& = Start& + (i& - Start&) \ 2 ' Get the subscript for the parent node.
  591.  
  592.         ' The value at the current node is still bigger than the value at
  593.         ' its parent node, so swap these two array elements:
  594.         IF CompareScreen%(i&, Parent&, maxw) = 1 THEN
  595.             PixelSwap Parent&, i&, maxw
  596.             i& = Parent&
  597.  
  598.             ' Otherwise, the element has reached its proper place in the heap,
  599.             ' so exit this procedure:
  600.         ELSE
  601.             EXIT DO
  602.         END IF
  603.     LOOP
  604.  
  605. SUB CombSort (Start&, Finish&, maxw)
  606.     m = INT(RND * 2)
  607.     SELECT CASE m
  608.         CASE 0
  609.             ShrinkFactor# = 1.247330950103979#
  610.         CASE ELSE
  611.             ShrinkFactor# = 1.3#
  612.     END SELECT
  613.     gap& = Finish& - Start&
  614.     BooleanSwapped% = -1
  615.     WHILE (gap& > 1) OR BooleanSwapped%
  616.         IF (gap& > 1) THEN
  617.             gap& = INT(gap& / ShrinkFactor#)
  618.         END IF
  619.         BooleanSwapped% = 0
  620.         FOR i& = Start& TO Finish& - gap&
  621.             IF CompareScreen%(i&, i& + gap&, maxw) = 1 THEN
  622.                 PixelSwap i&, i& + gap&, maxw
  623.                 BooleanSwapped% = -1
  624.             END IF
  625.         NEXT
  626.         IF (gap& = 1 AND NOT BooleanSwapped%) THEN
  627.             EXIT SUB
  628.         END IF
  629.     WEND
  630.  
  631. '* ShearSort rearranges elements into a "square" array and then sorts even and odd sets of columns and rows. this is the slice and dice method of sorting
  632. '* which i assume runs far more quickly on multiprocessors. it is included only as a matter of interest as it is what i consider a "beautiful," even if not
  633. '* blindingly fast sorting method. this is a parallel sorting algo translated to single-processor (could be tackled with simultaneous threading if our man
  634. '* Galleon could find some way to exploit multiple threads and processors).
  635.  
  636. SUB ShearSort (start&, finish&, maxw)
  637.     MakeSquare% = -1
  638.     sortorder% = 1
  639.     IF MakeSquare% THEN
  640.         '* put elements into a "square" arrangement.
  641.         rows& = INT(SQR(finish& - start& + 1))
  642.         IF (finish& - start& + 1) MOD rows& THEN
  643.             cols& = (finish& - start& + 1) \ rows& + 1
  644.         ELSE
  645.             cols& = (finish& - start& + 1) / rows&
  646.         END IF
  647.         IF rows& > cols& THEN
  648.             rows& = cols&
  649.         ELSE
  650.             cols& = rows&
  651.         END IF
  652.     ELSE
  653.         cols& = maxw
  654.         rows& = (finish& - start& + 1) / maxw
  655.     END IF
  656.     SCREEN _NEWIMAGE(cols&, rows&, numcolors%)
  657.     FOR i& = start& TO finish&
  658.         PixelSet i&, cols&, Pixels(i&).pcolor
  659.     NEXT
  660.  
  661.     colsminusone& = cols& - 1
  662.     rminuslplusoneminuscols& = finish& - start& + 1 - cols&
  663.     k& = rows&
  664.     DO
  665.         '* slice
  666.         FOR j& = 1 TO cols&
  667.             tmpj& = j& MOD 2
  668.             FOR i& = start& TO finish& STEP cols&
  669.                 IF ((i& - start&) / cols&) MOD 2 THEN
  670.                     OETransSort i& + tmpj&, i& + colsminusone&, 1, -sortorder%, cols& '-sortorder%
  671.                 ELSE
  672.                     OETransSort i& + tmpj&, i& + colsminusone&, 1, sortorder%, cols& '+sortorder% +
  673.                 END IF
  674.             NEXT
  675.         NEXT
  676.         '* and then dice
  677.         FOR j& = 1 TO rows&
  678.             tmpj& = j& MOD 2
  679.             FOR i& = start& TO start& + colsminusone&
  680.                 SELECT CASE tmpj&
  681.                     CASE 0
  682.                         OETransSort i&, rminuslplusoneminuscols& + i&, cols&, -sortorder%, cols&
  683.                     CASE ELSE
  684.                         OETransSort i& + tmpj& * cols&, rminuslplusoneminuscols& + i&, cols&, -sortorder%, cols& '-s%
  685.                 END SELECT
  686.             NEXT
  687.         NEXT
  688.         FOR j& = 1 TO cols&
  689.             tmpj& = j& MOD 2
  690.             FOR i& = l& TO r& STEP cols&
  691.                 SELECT CASE tmpj&
  692.                     CASE 0
  693.                         OETransSort i&, i& + colsminusone&, rows&, sortorder%, cols&
  694.                     CASE ELSE
  695.                         OETransSort i& + tmpj&, i& + colsminusone&, rows&, sortorder%, cols&
  696.                 END SELECT
  697.             NEXT
  698.         NEXT
  699.         k& = (k& - (k& MOD 2)) \ 2
  700.     LOOP WHILE k& > 2
  701.  
  702.     EXIT SUB
  703.     FOR j& = 1 TO cols&
  704.         tmpj& = j& MOD 2
  705.         FOR i& = l& TO r& STEP cols&
  706.             SELECT CASE tmpj&
  707.                 CASE 0
  708.                     OETransSort i&, i& + colsminusone&, 1, sortorder%, cols&
  709.                 CASE ELSE
  710.                     OETransSort i& + tmpj&, i& + colsminusone&, 1, sortorder%, cols&
  711.             END SELECT
  712.         NEXT
  713.     NEXT
  714.  
  715. SUB OETransSort (l&, r&, gap&, order%, maxw)
  716.     rx& = gap&
  717.     lst& = r& - rx&
  718.     FOR i& = l& TO lst& STEP gap& * 2
  719.         x% = CompareScreen%(i&, i& + gap&, maxw)
  720.         IF x% <> order% THEN
  721.             IF x% THEN
  722.                 PixelSwap i&, i& + gap&, maxw
  723.             END IF
  724.         END IF
  725.     NEXT
  726.  
  727. '* PostSort find the range of the data to be sorted and loads those into "boxes," which is essentially a 2-d array.
  728. '* then sort what's in the "boxes" individually using whatever sort -- in this case quicksort.
  729. SUB PostSort (start&, Finish&, maxw)
  730.     FindMinMax start&, Finish&, lptr&, rptr&, maxw
  731.     cmin% = GetPixel%(lptr&, maxw)
  732.     cmax% = GetPixel%(rptr&, maxw)
  733.     DIM PsCount&(cmin% TO cmax%, start& TO Finish&), ct&(cmin% TO cmax%)
  734.     FOR i& = start& TO Finish&
  735.         x% = GetPixel%(i&, maxw)
  736.         PsCount&(x%, ct&(x%)) = x%
  737.         ct&(x%) = ct&(x%) + 1
  738.     NEXT
  739.     Index& = start&
  740.     Last = start&
  741.     FOR i% = cmin% TO cmax%
  742.         FOR j& = 0 TO ct&(i%) - 1
  743.             PixelSet Index&, maxw, PsCount&(i%, start& + j&)
  744.             Index& = Index& + 1
  745.         NEXT
  746.         QuickSort Last&, Last& + ct&(i%) - 1, maxw
  747.         Last& = Index&
  748.     NEXT
  749.  
  750. SUB BatcherOddEvenMergeSort (Start&, Finish&, maxw)
  751.     IF (Finish& > 1) THEN
  752.         m& = (Finish& + (Finish& MOD 2)) \ 2
  753.         BatcherOddEvenMergeSort Start&, m&, maxw
  754.         BatcherOddEvenMergeSort Start& + m&, m&, maxw
  755.         BatcheroddEvenMerge Start&, Finish&, 1, maxw
  756.     END IF
  757.  
  758. SUB BatcheroddEvenMerge (Start&, Finish&, r&, maxw)
  759.     m& = r& * 2
  760.     IF (m& < Finish&) AND m& > 0 THEN
  761.         BatcheroddEvenMerge Start&, Finish&, m&, maxw
  762.         BatcheroddEvenMerge Start& + r&, Finish&, m&, maxw
  763.         i& = Start& + r&
  764.         DO
  765.             IF i& + m& > Start& + Finish& THEN
  766.                 EXIT DO
  767.             ELSE
  768.                 IF GetPixel%(i&, maxw) > GetPixel%(i& + r&, maxw) THEN
  769.                     PixelSwap i&, i& + r&, maxw
  770.                 END IF
  771.                 i& = i& + m&
  772.             END IF
  773.         LOOP
  774.     ELSE
  775.         IF GetPixel%(Start&, maxw) > GetPixel%(Start& + r&, maxw) THEN
  776.             PixelSwap Start&, Start& + r&, maxw
  777.         END IF
  778.     END IF
  779.  
  780. SUB JSortReHeap (length&, i&, maxw)
  781.     done% = 0
  782.     T% = GetPixel%(i&, maxw)
  783.     parent& = i&
  784.     child& = 2 * (i& + 1) - 1
  785.     WHILE ((child& < length&) AND NOT (done%))
  786.         IF (child& < length& - 1) THEN
  787.             IF (GetPixel%(child&, maxw) >= GetPixel%(child& + 1, maxw)) THEN
  788.                 child& = child& + 1
  789.             END IF
  790.         END IF
  791.         IF (T% < GetPixel%(child&, maxw)) THEN
  792.             done% = -1
  793.         ELSE
  794.             PixelSet parent&, maxw, GetPixel%(child&, maxw)
  795.             parent& = child&
  796.             child& = 2 * (parent& + 1) - 1
  797.         END IF
  798.         PixelSet parent&, maxw, T%
  799.     WEND
  800.  
  801. SUB JSortInvReHeap (length&, i&, maxw)
  802.     done% = 0
  803.     T% = GetPixel%(length& - 1 - i&, maxw)
  804.     parent& = i&
  805.     child& = 2 * (i& + 1) - 1
  806.     WHILE ((child& < length&) AND (NOT done%))
  807.         IF (child& < length& - 1) THEN
  808.             ns& = length& - 1
  809.             IF GetPixel%(ns& - child&, maxw) <= GetPixel%(ns& - child& - 1, maxw) THEN
  810.                 child& = child& + 1
  811.             END IF
  812.         END IF
  813.         IF T% > GetPixel%(length& - 1 - child&, maxw) THEN
  814.             done% = -1
  815.         ELSE
  816.             PixelSet length& - 1 - parent&, maxw, GetPixel%(length& - 1 - child&, maxw)
  817.             parent& = child&
  818.             child& = 2 * (parent& + 1) - 1
  819.         END IF
  820.     WEND
  821.     PixelSet length& - 1 - parent&, maxw, T%
  822.  
  823. SUB JSort (start&, finish&, maxw)
  824.     '// Do an insertion sort on the almost sorted array
  825.     FOR j& = start& TO finish& - 1
  826.         '// Heapify top down
  827.         IF finish& > j& THEN
  828.             FOR i& = finish& - 1 TO j& STEP -2
  829.                 JSortReHeap i&, j&, maxw
  830.             NEXT
  831.             FOR i& = finish& - 1 TO j& STEP -2
  832.                 JSortInvReHeap i&, j&, maxw
  833.             NEXT
  834.         END IF
  835.         T% = GetPixel%(j&, maxw)
  836.         a& = j&
  837.         DO
  838.             IF a& > start& THEN
  839.                 b& = a&
  840.                 a& = a& - 1
  841.                 IF GetPixel%(a&, maxw) > T% THEN
  842.                     PixelSwap a&, b&, maxw
  843.                 ELSE
  844.                     EXIT DO
  845.                 END IF
  846.             ELSE
  847.                 EXIT DO
  848.             END IF
  849.         LOOP
  850.         PixelSet b&, maxw, T%
  851.     NEXT
  852.  
  853. '* to keep BucketSort stable, you must use a stable sort on Lists&(), or if you prefer speed, just use quicksort if you don't care about
  854. '* sort stability.
  855.  
  856. SUB BucketSort (start&, finish&, maxw)
  857.     FindMinMax start&, finish&, lptr&, rptr&, maxw
  858.     min% = GetPixel%(lptr&, maxw)
  859.     max% = GetPixel%(rptr&, maxw)
  860.     NBuckets& = SQR(((max% - min%) / 2) ^ 2)
  861.     BucketSize& = 1.28 * (finish& - start& + 1) \ (NBuckets&)
  862.     DIM Lists&(NBuckets&, BucketSize&), Counts&(min% TO max%), OverFlowedCt&(min% TO max%)
  863.     difference& = (max% - min% + 1) \ NBuckets&
  864.     FOR i& = start& TO finish&
  865.         BucketNum& = GetPixel%(i&, maxw) \ difference&
  866.         DO
  867.             IF Counts&(BucketNum&) > BucketSize& THEN
  868.                 OverFlowedCt&(BucketNum&) = -1
  869.                 IF BucketNum& > 0 THEN
  870.                     IF Counts&(BucketNum& - 1) > BucketSize& THEN
  871.                         BucketNum& = BucketNum& + 1
  872.                     ELSE
  873.                         BucketNum& = BucketNum& - 1
  874.                     END IF
  875.                 ELSE
  876.                     IF BucketNum& < NBuckets& THEN
  877.                         BucketNum& = BucketNum& + 1
  878.                     ELSE
  879.                         STOP
  880.                     END IF
  881.                 END IF
  882.             ELSE
  883.                 EXIT DO
  884.             END IF
  885.         LOOP
  886.         Lists&(BucketNum&, Counts&(BucketNum&)) = GetPixel%(i&, maxw)
  887.         Counts&(BucketNum&) = Counts&(BucketNum&) + 1
  888.     NEXT
  889.     idx& = start&
  890.     last& = start&
  891.     FOR i& = min% TO max%
  892.         '* roughly sorts Lists&() in a stable manner
  893.         SortBuckets Lists&(), 0, Counts&(i&) - 1, i&, maxw
  894.         FOR u& = 0 TO Counts&(i&) - 1
  895.             PixelSet idx&, maxw, Lists&(i&, u&)
  896.             idx& = idx& + 1
  897.         NEXT
  898.         ShellSortMetzler last&, idx& - 1, maxw
  899.         last& = idx&
  900.     NEXT
  901.  
  902. SUB SortBuckets (Lists&(), Start&, Finish&, ListIndex&, maxw)
  903.     IF Finish& - Start& = 1 THEN
  904.         IF Lists&(ListIndex&, Start&) > Lists&(ListIndex&, Finish&) THEN
  905.             SWAP Lists&(ListIndex&, Start&), Lists&(ListIndex&, Finish&)
  906.         END IF
  907.     ELSE
  908.         IF Finish& - Start& > 1 THEN
  909.             'u& = (Finish& - Start&) MOD 2
  910.             m& = Start& + (Finish& - Start&) \ 2
  911.             SortBuckets Lists&(), Start&, m&, ListIndex&, maxw
  912.             SortBuckets Lists&(), m&, Finish&, ListIndex&, maxw
  913.         END IF
  914.     END IF
  915.  
  916. SUB FindMinMax (start&, finish&, MinPtr&, MaxPtr&, maxw)
  917.     MinPtr& = start&: min% = GetPixel%(start&, maxw)
  918.     MaxPtr& = start&: max% = GetPixel%(start&, maxw)
  919.     FOR i& = start& TO finish&
  920.         m% = GetPixel%(i&, maxw)
  921.         IF m% < min% THEN
  922.             min% = m%
  923.             MinPtr& = i&
  924.         END IF
  925.         IF m% > max% THEN
  926.             max% = m%
  927.             MaxPtr& = i&
  928.         END IF
  929.     NEXT
  930.  
  931. SUB MergeSort (start&, finish&, maxw)
  932.     IF start& >= finish& THEN EXIT SUB
  933.     length& = finish& - start& + 1
  934.     middle& = start& + (finish& - start&) \ 2
  935.     MergeSort start&, middle&, maxw
  936.     MergeSort middle& + 1, finish&, maxw
  937.     DIM temp(length& - 1)
  938.     FOR i& = 0 TO length& - 1
  939.         temp(i&) = GetPixel%(start& + i&, maxw)
  940.     NEXT
  941.     mptr& = 0
  942.     sptr& = middle& - start& + 1
  943.     FOR i& = 0 TO length& - 1
  944.         IF sptr& <= finish& - start& THEN
  945.             IF mptr& <= middle& - start& THEN
  946.                 IF temp(mptr&) > temp(sptr&) THEN
  947.                     PixelSet i& + start&, maxw, temp(sptr&)
  948.                     sptr& = sptr& + 1
  949.                 ELSE
  950.                     PixelSet i& + start&, maxw, temp(mptr&)
  951.                     mptr& = mptr& + 1
  952.                 END IF
  953.             ELSE
  954.                 PixelSet i& + start&, maxw, temp(sptr&)
  955.                 sptr& = sptr& + 1
  956.             END IF
  957.         ELSE
  958.             PixelSet i& + start&, maxw, temp(mptr&)
  959.             mptr& = mptr& + 1
  960.         END IF
  961.     NEXT
  962.  
  963. SUB OESort (Start&, Finish&, maxw)
  964.     sorted = 0
  965.     WHILE NOT sorted
  966.         sorted = -1
  967.         FOR i& = Start& TO Finish& - 1 STEP 2
  968.             IF CompareScreen%(i&, i& + 1, maxw) = 1 THEN
  969.                 PixelSwap i&, i& + 1, maxw
  970.                 sorted = 0
  971.             END IF
  972.         NEXT
  973.         FOR i& = Start& + 1 TO Finish& - 2 STEP 2
  974.             IF CompareScreen%(i&, i& + 1, maxw) = 1 THEN
  975.                 PixelSwap i&, i& + 1, maxw
  976.             END IF
  977.         NEXT
  978.     WEND
  979.  
  980. SUB QuickSortRStable (r() AS PixelRec, start&, finish&, maxw)
  981.     IF finish& - start& = 1 THEN
  982.         CompareRecs r(), start&, finish&, maxw
  983.     ELSE
  984.         IF finish& - start& > 1 THEN
  985.             i& = start&
  986.             j& = finish&
  987.             p# = StableIndex#(r(), (i& + (j& - i& + 1) \ 2), maxw)
  988.             DO
  989.                 WHILE StableIndex#(r(), i&, maxw) < p#
  990.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  991.                     i& = i& + 1
  992.                 WEND
  993.                 WHILE StableIndex#(r(), j&, maxw) > p#
  994.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  995.                     j& = j& - 1
  996.                 WEND
  997.                 IF i& <= j& THEN
  998.                     CompareRecs r(), i&, j&, maxw
  999.  
  1000.                     i& = i& + 1
  1001.                     j& = j& - 1
  1002.                 END IF
  1003.             LOOP UNTIL i& > j&
  1004.             QuickSortRStable r(), i&, finish&, maxw
  1005.             QuickSortRStable r(), start&, j&, maxw
  1006.         END IF
  1007.     END IF
  1008.  
  1009. '* swapping indexes is much faster than swapping entire records
  1010. '* the index for this Pixels is simply the r().pixnum field of Pixels type PixelRec r()
  1011. SUB CompareRecs (r() AS PixelRec, i&, j&, maxw)
  1012.     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  1013.     IF r(r(i&).pixnum).pcolor <= r(r(j&).pixnum).pcolor THEN
  1014.         IF r(i&).pixnum > r(j&).pixnum THEN
  1015.             SWAP r(i&).pixnum, r(j&).pixnum
  1016.         END IF
  1017.     ELSE
  1018.         Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  1019.         IF r(r(i&).pixnum).pcolor > r(r(j&).pixnum).pcolor THEN
  1020.             SWAP r(i&).pixnum, r(j&).pixnum
  1021.         END IF
  1022.     END IF
  1023.     PixelSet i&, maxw, r(r(i&).pixnum).pcolor
  1024.     PixelSet j&, maxw, r(r(j&).pixnum).pcolor
  1025.     EXIT SUB
  1026.     IF StableIndex#(r(), i&, maxw) > StableIndex#(r(), j&, maxw) THEN
  1027.         PixelSwap r(r(i&).pixnum).pixnum, r(r(j&).pixnum).pixnum, maxw
  1028.         SWAP r(i&).pixnum, r(j&).pixnum
  1029.     END IF
  1030.  
  1031. FUNCTION StableIndex# (r() AS PixelRec, a&, maxw)
  1032.     np# = 10 ^ (LOG(UBOUND(r) + 1) \ LOG(10))
  1033.     StableIndex# = r(r(a&).pixnum).pcolor * np# + r(a&).pixnum
  1034.  
  1035. SUB QuickSortIterative (Start&, Finish&, maxw)
  1036.     MinStack& = LOG(Finish& - Start& + 1) \ LOG(2) + 1
  1037.     DIM LStack&(MinStack&, 1)
  1038.     StackPtr% = 0
  1039.     LStack&(StackPtr%, 0) = Start&
  1040.     LStack&(StackPtr%, 1) = Finish&
  1041.     DO
  1042.         Low& = LStack&(StackPtr%, 0)
  1043.         Hi& = LStack&(StackPtr%, 1)
  1044.         DO
  1045.             i& = Low&
  1046.             j& = Hi&
  1047.             Mid& = Low& + (Hi& - Low& + 1) \ 2
  1048.             Compare% = GetPixel%(Mid&, maxw)
  1049.             DO
  1050.                 DO WHILE GetPixel%(i&, maxw) < Compare%
  1051.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  1052.                     i& = i& + 1
  1053.                 LOOP
  1054.                 DO WHILE GetPixel%(j&, maxw) > Compare%
  1055.                     Sorts(SortNum).compares = Sorts(SortNum).compares + 1
  1056.                     j& = j& - 1
  1057.                 LOOP
  1058.                 IF i& < j& THEN
  1059.                     PixelSwap i&, j&, maxw
  1060.                 END IF
  1061.                 i& = i& + 1
  1062.                 j& = j& - 1
  1063.             LOOP UNTIL i& > j&
  1064.             IF j& - Low& < Hi& - i& THEN
  1065.                 IF i& < Hi& THEN
  1066.                     LStack&(StackPtr%, 0) = i&
  1067.                     LStack&(StackPtr%, 1) = Hi&
  1068.                     StackPtr% = StackPtr% + 1
  1069.                 END IF
  1070.                 Hi& = j&
  1071.             ELSE
  1072.                 IF Low& < j& THEN
  1073.                     LStack&(StackPtr%, 0) = Low&
  1074.                     LStack&(StackPtr%, 1) = j&
  1075.                     StackPtr% = StackPtr% + 1
  1076.                 END IF
  1077.                 Low& = i&
  1078.             END IF
  1079.         LOOP WHILE Low& < Hi&
  1080.         StackPtr% = StackPtr% - 1
  1081.     LOOP UNTIL StackPtr% < 0
  1082.  
  1083. ' this sort splits the list in half and then merges them, however, it requires extra space -- the travails of gaining extra speed!
  1084. ' but on average, it is quicker than quicksorting the entire list as the arrays are already sorted by the time they get merged, which
  1085. ' itself is a nearly linear process. as long as a stable sort is used to sort array segments, this should remain a stable sort!
  1086. SUB MergeExperiment (Start&, Finish&, maxw)
  1087.     HowManySets = 2 'LOG(Finish& - Start& + 1) \ LOG(2) + 1
  1088.     DIM Starts&(HowManySets), Ends&(HowManySets)
  1089.     m& = (Finish& - Start&) MOD HowManySets
  1090.     segment& = (Finish& - Start& - m&) / HowManySets
  1091.     u = HowManySets - 1
  1092.     f& = Finish&
  1093.     DO
  1094.         Ends&(u) = f&
  1095.         Starts&(u) = f& - segment&
  1096.         f& = f& - (segment& + 1)
  1097.         u = u - 1
  1098.     LOOP UNTIL u < 0
  1099.     index& = 0
  1100.     FOR i = 0 TO HowManySets - 1
  1101.         MergeSort Starts&(i), Ends&(i), maxw
  1102.     NEXT
  1103.     mergetosum& = 0
  1104.     FOR i = 0 TO HowManySets - 1 STEP 2
  1105.         StartMast& = Starts&(i)
  1106.         EndMast& = Ends&(i)
  1107.         StartSlave& = Starts&(i + 1)
  1108.         EndSlave& = Ends&(i + 1)
  1109.         REDIM Master%(StartMast& TO EndMast&)
  1110.         REDIM Slave%(StartSlave& TO EndSlave&)
  1111.         FOR i& = StartMast& TO EndMast&
  1112.             Master%(i&) = GetPixel%(i&, maxw)
  1113.         NEXT
  1114.         FOR i& = StartSlave& TO EndSlave&
  1115.             Slave%(i&) = GetPixel%(i&, maxw)
  1116.         NEXT
  1117.         Master& = StartMast&
  1118.         Slave& = StartSlave&
  1119.         index& = Start&
  1120.         DO
  1121.             IF Master& > EndMast& THEN
  1122.                 IF Slave& > EndSlave& THEN '* both lists are fully traversed
  1123.                     EXIT DO
  1124.                 ELSE '* empty the slave list
  1125.                     PixelSet index&, maxw, Slave%(Slave&)
  1126.                     Slave& = Slave& + 1
  1127.                 END IF
  1128.             ELSE
  1129.                 IF Slave& > EndSlave& THEN '* empty the master list
  1130.                     PixelSet index&, maxw, Master%(Master&)
  1131.                     Master& = Master& + 1
  1132.                 ELSE '* Master%() and Slave%() both have unprocessed elements
  1133.                     IF Master%(Master&) > Slave%(Slave&) THEN
  1134.                         PixelSet index&, maxw, Slave%(Slave&)
  1135.                         Slave& = Slave& + 1
  1136.                     ELSE
  1137.                         PixelSet index&, maxw, Master%(Master&)
  1138.                         Master& = Master& + 1
  1139.                     END IF
  1140.                 END IF
  1141.             END IF
  1142.             index& = index& + 1
  1143.         LOOP
  1144.     NEXT
  1145.  
  1146. '* part 2, dammit!
  1147.  
  1148. '* this has been modified to become a bidirectional shellsort, which is far faster than the bubblesort version, which is a special case where
  1149. '* gap& is 1, and runs in polynomial time when gap& is 1
  1150. SUB BidirectionalShellSort (Start&, Finish&, maxw)
  1151.     gap& = (Finish& - Start& + 1) \ 2
  1152.     DO
  1153.         up% = -1: down% = -1
  1154.         startup& = Start&: endup& = Finish& - gap&: FirstUp& = Finish& - gap&: LastUp& = Start&
  1155.         startdn& = Finish&: enddown& = Start& + gap&: FirstDown& = Start& + gap&: LastDown& = Finish&
  1156.         DO
  1157.             IF up% THEN
  1158.                 up% = 0
  1159.                 FOR i& = startup& TO endup&
  1160.                     IF CompareScreen%(i&, i& + gap&, maxw) = 1 THEN
  1161.                         PixelSwap i&, i& + gap&, maxw
  1162.                         IF i& < FirstUp& THEN
  1163.                             FirstUp& = i&
  1164.                         END IF
  1165.                         LastUp& = i&
  1166.                         up% = -1
  1167.                     END IF
  1168.                 NEXT
  1169.                 startup& = FirstUp&
  1170.                 endup& = LastUp&
  1171.                 SWAP FirstUp&, LastUp&
  1172.             END IF
  1173.             '*******************************
  1174.             IF down% THEN
  1175.                 down% = 0
  1176.                 FOR i& = startdn& TO enddown& STEP -1
  1177.                     IF CompareScreen%(i&, i& - gap&, maxw) = -1 THEN
  1178.                         PixelSwap i&, i& - gap&, maxw
  1179.                         IF i& > FirstDown& THEN
  1180.                             FirstDown& = i&
  1181.                         END IF
  1182.                         LastDown& = i&
  1183.                         down% = -1
  1184.                     END IF
  1185.                 NEXT
  1186.                 startdn& = FirstDown&
  1187.                 enddown& = LastDown&
  1188.                 SWAP FirstDown&, LastDown&
  1189.             END IF
  1190.         LOOP UNTIL NOT (up% OR down%)
  1191.         gap& = gap& \ 2
  1192.     LOOP WHILE gap& > 0
  1193.  
  1194. '* for highly repetitive data, TreeSortAscending becomes like an insertion sort, which degenerates to polynomial time, which is NOT good. this sort is far
  1195. '* better suited to data that is not repetitive. by the way, 16 is an arbitrary number and can be set to whatever your threshold of pain for a possibly
  1196. '* polynomial time sort.
  1197.  
  1198. SUB TreeSortAscending (start&, finish&, maxw)
  1199.     FindMinMax start&, finish&, MinPtr&, MaxPtr&, maxw
  1200.     delta# = GetPixel%(MaxPtr&, maxw) - GetPixel%(MinPtr&, maxw)
  1201.     IF delta# = 0 THEN 'already sorted because they're all equal
  1202.         EXIT SUB
  1203.     ELSE
  1204.         IF ABS((finish& - start& + 1) / delta#) > 65535 THEN
  1205.             BucketSort start&, finish&, maxw
  1206.             EXIT SUB
  1207.         END IF
  1208.     END IF
  1209.     NilValue% = GetPixel%(MinPtr&, maxw) - 1
  1210.     TYPE TreeNode
  1211.         value AS LONG
  1212.         left AS LONG
  1213.         right AS LONG
  1214.     END TYPE
  1215.     DIM tree(start& + 1 TO finish& + 1) AS TreeNode
  1216.     FOR x& = start& + 1 TO finish& + 1
  1217.         tree(x&).value = NilValue%
  1218.         tree(x&).left = NilValue%
  1219.         tree(x&).right = NilValue%
  1220.     NEXT
  1221.     tree(1).value = GetPixel%(1 - 1, maxw)
  1222.     free& = 2
  1223.     FOR x& = 2 TO finish&
  1224.         pointer& = 1
  1225.         xv& = (GetPixel%(x& - 1, maxw))
  1226.         DO
  1227.             IF xv& < tree(pointer&).value THEN
  1228.                 IF tree(pointer&).left = NilValue% THEN
  1229.                     tree(pointer&).left = free&
  1230.                     tree(free&).value = xv&
  1231.                     'PixelSet free& - 1, maxw, tree(tree(pointer&).left).value
  1232.                     free& = free& + 1
  1233.                     EXIT DO
  1234.                 ELSE
  1235.                     pointer& = tree(pointer&).left
  1236.                 END IF
  1237.             ELSE
  1238.                 IF tree(pointer&).right = NilValue% THEN
  1239.                     tree(pointer&).right = free&
  1240.                     tree(free&).value = xv&
  1241.                     'PixelSet free& - 1, maxw, tree(tree(pointer&).right).value
  1242.                     free& = free& + 1
  1243.                     EXIT DO
  1244.                 ELSE
  1245.                     pointer& = tree(pointer&).right
  1246.                 END IF
  1247.             END IF
  1248.         LOOP
  1249.     NEXT x&
  1250.     depth& = 1
  1251.     traverse start& + 1, depth&, tree(), NilValue%, maxw
  1252.  
  1253. SUB traverse (start&, depth&, tree() AS TreeNode, NilValue%, maxw)
  1254.     IF tree(start&).left <> NilValue% THEN traverse tree(start&).left, depth&, tree(), NilValue%, maxw
  1255.     PixelSet depth& - 1, maxw, tree(start&).value
  1256.     depth& = depth& + 1
  1257.     IF tree(start&).right <> NilValue% THEN traverse tree(start&).right, depth&, tree(), NilValue%, maxw
  1258.  
  1259. '* this algo at first glance looks like it'd be just another slow version of shellsort, but crap if it doesn't rank well with my sortindex at 31
  1260. SUB CodeGuySort (Start&, Finish&, maxw)
  1261.     'rows& = (Finish& - Start& + 1) / maxw
  1262.     gap& = (Finish& - Start& + 1) \ 2
  1263.     DO
  1264.         IF gap& < maxw THEN
  1265.             m& = Start&
  1266.             FOR x% = 0 TO (Finish& - Start& + 1) \ maxw
  1267.                 ShellSortMetzler m&, m& + gap&, maxw
  1268.                 m& = m& + gap&
  1269.             NEXT
  1270.         ELSE
  1271.             rows& = (Finish& - Start& - gap&) / maxw
  1272.             FOR b% = 0 TO 1
  1273.                 FOR offset& = b% TO maxw STEP b% + 1
  1274.                     FOR x% = b% TO (maxw - gap&) \ gap& STEP b% + 1
  1275.                         FOR j& = b% TO rows& STEP b% + 1
  1276.                             y& = j& * maxw + offset&
  1277.                             z& = y& + gap&
  1278.                             IF z& > Finish& THEN
  1279.                                 exitnextfor = -1
  1280.                                 EXIT FOR
  1281.                             END IF
  1282.                             IF CompareScreen%(y&, z&, maxw) = 1 THEN
  1283.                                 PixelSwap y&, z&, maxw
  1284.                             END IF
  1285.                         NEXT
  1286.                         IF exitnextfor THEN
  1287.                             exitnextfor = 0
  1288.                             EXIT FOR
  1289.                         END IF
  1290.                     NEXT
  1291.                 NEXT
  1292.             NEXT
  1293.         END IF
  1294.         gap& = INT((gap& / 5) * 4)
  1295.     LOOP UNTIL gap& < 1
  1296.  
  1297. SUB SortColumns (Start&, Finish&, maxw)
  1298.     EXIT SUB
  1299.     FOR column& = 0 TO maxw - 1
  1300.         IF GetPixel%(column&, maxw) > GetPixel%(column& + maxw, maxw) THEN
  1301.             PixelSwap column&, column& + maxw, maxw
  1302.         END IF
  1303.     NEXT
  1304.  
  1305. '* uses PrimeNumber&() function to calculate the prime number less than or equal to the gap
  1306. SUB PrimeGapSort (start&, finish&, maxw)
  1307.     Gap& = (finish& - start& + 1)
  1308.     DO
  1309.         FOR i& = start& TO finish& - Gap&
  1310.             'IF i& > finish& - Gap& THEN
  1311.             '    IF CompareScreen%(i&, i& + Gap& - finish&, maxw) = -1 THEN
  1312.             '        PixelSwap i&, i& + Gap& - finish&, maxw
  1313.             '    END IF
  1314.             'ELSE
  1315.             IF CompareScreen%(i&, i& + Gap&, maxw) = 1 THEN
  1316.                 PixelSwap i&, i& + Gap&, maxw
  1317.             END IF
  1318.             'END IF
  1319.             'IF i& < Gap& THEN
  1320.             '    IF CompareScreen%(i&, i& - Gap& + finish&, maxw) = 1 THEN
  1321.             '        PixelSwap i&, i& - Gap& + finish&, maxw
  1322.             '    END IF
  1323.             'ELSE
  1324.             '    IF CompareScreen%(i&, i& - Gap&, maxw) = -1 THEN
  1325.             '        PixelSwap i&, i& - Gap&, maxw
  1326.             '    END IF
  1327.             'END IF
  1328.         NEXT
  1329.         Gap& = primeNumber&(Gap& * .727)
  1330.         'PrimeNumber&(Gap& \ 2)
  1331.     LOOP UNTIL Gap& <= 1
  1332.     FOR i& = finish& - 2 TO start& STEP -1
  1333.         IF CompareScreen%(i& + 1, i&, maxw) = -1 THEN
  1334.             hold% = GetPixel%(i&, maxw)
  1335.             j& = i&
  1336.             WHILE (GetPixel%(j& + 1, maxw) < hold%)
  1337.                 PixelSwap j&, j& + 1, maxw
  1338.                 'a(j&) = a(j& + 1)
  1339.                 j& = j& + 1
  1340.             WEND
  1341.             'a(j&) = hold%
  1342.             PixelSet j&, maxw, hold%
  1343.         END IF
  1344.     NEXT i&
  1345.  
  1346. FUNCTION primeNumber& (a&)
  1347.     ' Find a prime number below a& (excluding 3 and 5)
  1348.     '
  1349.     ' Notice that there is a:
  1350.     ' 59,9% chance for a single successive guess,
  1351.     ' 83,9% chance for a successive guess out of two guesses,
  1352.     ' 93,6% chance for a successive guess out of three guesses,
  1353.     ' 97,4% chance for a successive guess out of four guesses,
  1354.     ' 99,98% chance for a successive guess out of ten guesses...
  1355.     '
  1356.     ' Worst bad luck over 10000 tested primes: 19 guesses.
  1357.  
  1358.     STATIC firstCall%
  1359.     STATIC pps%() 'Previous Prime in Sequence. Contains about 59.9% of all primes modulo 30.
  1360.  
  1361.     IF firstCall% = 0 THEN
  1362.         firstCall% = -1
  1363.         REDIM pps%(0 TO 29)
  1364.         ' Map numbers from 0 to 29 to the next lower prime in the sequence {1,7,11,13,17,19,23,29}.
  1365.         pps%(0) = -1: pps%(1) = -1 ' -1 = 29 (modulo 30)
  1366.         pps%(2) = 1: pps%(3) = 1: pps%(4) = 1: pps%(5) = 1: pps%(6) = 1: pps%(7) = 1
  1367.         pps%(8) = 7: pps%(9) = 7: pps%(10) = 7: pps%(11) = 7
  1368.         pps%(12) = 11: pps%(13) = 11:
  1369.         pps%(14) = 13: pps%(15) = 13: pps%(16) = 13: pps%(17) = 13
  1370.         pps%(18) = 17: pps%(19) = 17
  1371.         pps%(20) = 19: pps%(21) = 19: pps%(22) = 19: pps%(23) = 19
  1372.         pps%(24) = 23: pps%(25) = 23: pps%(26) = 23: pps%(27) = 23: pps%(28) = 23: pps%(29) = 23
  1373.     END IF
  1374.  
  1375.     b& = a& + 1
  1376.     c& = (b& \ 30) * 30: b& = c& + pps%(b& - c&)
  1377.     div& = 3
  1378.     DO
  1379.         IF b& MOD div& THEN
  1380.             IF b& / div& < div& THEN
  1381.                 EXIT DO
  1382.             ELSE
  1383.                 div& = div& + 2
  1384.             END IF
  1385.         ELSE
  1386.             c& = (b& \ 30) * 30: b& = c& + pps%(b& - c&)
  1387.             div& = 3
  1388.         END IF
  1389.     LOOP
  1390.     primeNumber& = b&
  1391.  
  1392. FUNCTION SpeedIndex# (T AS SortRec, start&, finish&, doit%, tstart#, tend#, maxw)
  1393.     IF doit% THEN
  1394.         tstart# = TIMER
  1395.         FOR npixel& = start& TO finish&
  1396.             p% = GetPixel%(npixel&, maxw)
  1397.         NEXT
  1398.         tend# = TIMER
  1399.         IF tend# < start# THEN
  1400.             tend# = tend# + 86400
  1401.         END IF
  1402.         doit% = 0
  1403.     END IF
  1404.     SpeedIndex# = ((finish& - start& + 1) / (tend# - tstart#)) / (T.NSorted / T.accumulatedtime)
  1405.  

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #3 on: October 15, 2018, 09:44:50 pm »
Using a simple configuration is convenient in conjunction with standalone exe and in the program it is possible to change the path and i welcome any improvements.

On Internet, more and more sites include visualization and comparison of sortings.

I assume on QB64 it is possible to create a program with a menu that compares 2 or more sorting live.
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #4 on: October 15, 2018, 09:57:19 pm »
The performance profile is similar to Bitonic Sort, respectable but not insanely efficient. Yes, you can visualize a lot of algorithms, just as I did in the code submitted to this thread.

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #5 on: October 15, 2018, 10:09:35 pm »
feature of the algorithm of the topic:
everyone is able to understand this algorithm
unlike certain incomprehensible algorithms machine sorting.

especially considering: my algorithm is pretty quick.

means using for example sorting of goods
or sorting the way people can be sure:
algorithm and quick and understandable to people.

and another feature: speeds up slow sorts
2 ... 4 ... 8 times dividing the bubble sort array
which makes my algorithm even more human.



Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #6 on: October 15, 2018, 10:19:16 pm »
It's comparable speed to MergeSort. Yes, it's a fairly simple but efficient algorithm. I will give it a passing review as it performs well enough to be competitive with O(NLogN) class sorting methods. The fact it's not in-place isn't much of a deterrent for reasonable array sizes. In all, nicely done. I have learned something new. Good luck.

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #7 on: October 16, 2018, 04:30:50 am »
info for an expected review:

Russian Sorting Halves
author: Andrey Danilin

Danilin is last name


« Last Edit: October 16, 2018, 06:45:12 am by DANILIN »
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #8 on: October 18, 2018, 05:21:02 am »
O(N) = 3*N*LOG(N;2)

requires recalculation of entire array
and further distribution of entire array
and further return of sub-array back are required.

and number of distributions takes into account division by halves.
proves visualization and counters.

O(N) = 3*N*LOG(N;2)

Created 13 options are Russian sorting halves:

1. Acceleration of bubble sorting by 2 times
adding a few lines code by dividing array into 2 parts

2. Acceleration of bubble sorting 4 times
adding a few lines code by dividing array into 4 parts

3. Acceleration of selection sorting by 2 times
adding a few lines code by dividing array into 2 parts

4. Acceleration of selection sorting by 4 times
adding a few lines code by dividing array into 4 parts

5. Recursive of QB64 1'000'000 in 2.2 seconds
6. Recursive of PureBasic 1'000'000 in 0.3 seconds
7. Recursive of FreeBasic 1'000'000 in 0.15 seconds
8. Recursive of C# Csharp 1'000'000 in 0.2 seconds
9. QB64 sorting integral of letters

10. Excel fast for 250 items on 5 second
11. Excel animation for 250 items on 150 second

12. Acceleration of bubble sorting
by dividing into 4 parts C# Csharp
13. Nested loops and indexes of indexes
« Last Edit: November 06, 2018, 06:43:40 am by DANILIN »
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #9 on: October 18, 2018, 08:56:52 am »
BubbleSortModified which can sort ranges is designed to be adaptive and increases speed over standard BubbleSort by twice on average for randomly arranged datasets. Also, if the array is mostly sorted by the time  BubbleSort is called, you can use InsertionSort to better effect.

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #10 on: October 18, 2018, 09:05:16 am »
to use insertionsort people need to know insertionsort
and for those who massively know only bubblesort:

a human-friendly solution that accelerates bubblesort 4 times:
division of array by method of Russian sorting halves.

Russian Sorting Halves and risk management:
in 1st approximation relative to risk of 50%:

to left events with minimal risk for large participation
to right of event with maximum risk for small participation

and still easy to sort inside 2 parts
at least dividing risks into 4 parts.

Russian Sort Halves Accelerate Danilin visualisation
« Last Edit: October 18, 2018, 09:23:56 am by DANILIN »
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #11 on: October 27, 2018, 07:57:49 am »
news:

Russian Sorting Halves and fast and human

9. Recursive version of C# Csharp 1'000'000 in 0.2 seconds

resume:

Russian Sorting Halves and fast and human
sorts 1'000'000 in 2.2 seconds on QB64
sorts 1'000'000 in 0.3 seconds on PureBasic
sorts 1'000'000 in 0.2 seconds on C# Csharp
sorts 1'000'000 in 0.15 seconds on Freebasic
« Last Edit: October 27, 2018, 09:42:22 am by DANILIN »
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #12 on: October 28, 2018, 11:04:14 am »
It's comparable speed to MergeSort. Yes, it's a fairly simple but efficient algorithm. I will give it a passing review as it performs well enough to be competitive with O(NLogN) class sorting methods. The fact it's not in-place isn't much of a deterrent for reasonable array sizes. In all, nicely done. I have learned something new. Good luck.

Blah! It sucks in comparison to simple, easy to understand, standard QSort:

Code: QB64: [Select]
  1. _TITLE "Compare RussianSorting presented by Danilin to a Basic standard QuickSort by B+ 2018-10-28"
  2.  
  3. 'first here is Danilin's main code: ------------------------------------------------------------------------
  4. 'DECLARE SUB RussianSortingHalvesDAV (ab!, yz!, part!, age!)
  5. 'CLOSE
  6. 'OPEN "c:/N.txt" FOR INPUT AS #1
  7. 'INPUT #1, n
  8. ''n=1234567
  9. 'age = 1 + LOG(n) / LOG(2)
  10. 'PRINT n
  11.  
  12. 'DIM SHARED d(n) 'AS LONG
  13. 'DIM SHARED a(n) 'AS LONG
  14.  
  15. ''OPEN "c:/ISX.txt" FOR INPUT AS #2
  16. ''FOR i=1 TO n: INPUT #2, d(i): NEXT
  17.  
  18. ''FOR i = 1 TO n: d(i) = n - i + 1: NEXT ' INT(RND*n)
  19. 'FOR i = 1 TO n: d(i) = INT(RND * n): NEXT '
  20. 'FOR k = 1 TO 20: PRINT d(k);: NEXT: PRINT: PRINT
  21. 'FOR k = n - 19 TO n: PRINT d(k);: NEXT: PRINT: PRINT
  22.  
  23. 'start = TIMER
  24.  
  25. 'IF age > 0 THEN
  26. '    CALL RussianSortingHalvesDAV(1, n, 1, age)
  27. 'END IF
  28.  
  29. 'finish = TIMER
  30.  
  31. 'PRINT finish - start; "second ": PRINT
  32.  
  33. 'OPEN "c:/=RuSortHalves_dav.txt" FOR OUTPUT AS #3
  34. 'PRINT #3, finish - start; "second "
  35. 'PRINT #3, n; "elements", "RECURSION"
  36. 'FOR i = 1 TO 22: PRINT #3, d(i): NEXT
  37. 'FOR i = n - 22 TO n: PRINT #3, d(i): NEXT
  38.  
  39. 'FOR k = 1 TO 20: PRINT d(k);: NEXT: PRINT: PRINT
  40. 'FOR k = n - 19 TO n: PRINT d(k);: NEXT: PRINT: PRINT
  41.  
  42. 'END  - of Danilin's code --------------------------------------------------------------------
  43.  
  44. 'Since the timed test involves nothing to do with file input and output, leave that crap out!
  45. 'And since Danilin is advertising this crap as the cat's meow, lets do a sort of random type single
  46. '
  47. ' Here is the only relevant parts of Danilin
  48. CONST n = 1000000
  49. DIM SHARED d(n) ' single
  50. DIM SHARED a(n) ' single
  51. DIM SHARED QS(n) ' to compare to Danilin's "simple" code
  52.  
  53. ' Make a sample set of test data
  54. FOR i = 1 TO n
  55.     r = RND * n
  56.     d(i) = r
  57.     QS(i) = r
  58.  
  59. ' Since Danilin does not provide us with "c:/N.txt" file data, can't be important to his demo
  60. age = 1 + LOG(n) / LOG(2)
  61. start = TIMER
  62. IF age > 0 THEN
  63.     CALL RussianSortingHalvesDAV(1, n, 1, age)
  64. finish = TIMER
  65. PRINT finish - start; "second "
  66. IF n > 100 THEN stopper = 100 ELSE stopper = n
  67. FOR i = 1 TO stopper
  68.     PRINT d(i); ", ";
  69. DanilinTime = finish - start
  70. PRINT: PRINT: INPUT "Now for the Quick Sort Test, press enter...", enter$
  71.  
  72. 'now try good ole Quick Sort
  73. start = TIMER
  74. qSort 1, n
  75. finish = TIMER
  76. PRINT finish - start; "sec."
  77. IF n > 100 THEN stopper = 100 ELSE stopper = n
  78. FOR i = 1 TO stopper
  79.     PRINT d(i); ", ";
  80. QSortTime = finish - start
  81. PRINT: PRINT: PRINT "Ha, ha, ha QSort took "; INT(QSortTime / DanilinTime * 1000) / 1000; " times lomger than Danilin's Sort!"
  82.  
  83.  
  84. SUB RussianSortingHalvesDAV (ab, yz, part, age)
  85.  
  86.     IF yz - ab < 1 THEN EXIT SUB
  87.  
  88.     FOR i = ab TO yz '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> really a time waster and String Array Buster here!!!!!
  89.         summa = summa + d(i)
  90.     NEXT
  91.     middle = summa / (yz - ab + 1)
  92.  
  93.     abc = ab - 1
  94.     xyz = yz + 1
  95.  
  96.     FOR i = ab TO yz
  97.         IF d(i) < middle THEN abc = abc + 1: a(abc) = d(i): ELSE xyz = xyz - 1: a(xyz) = d(i)
  98.     NEXT
  99.  
  100.     FOR i = ab TO yz: d(i) = a(i): NEXT
  101.  
  102.     IF part < age THEN
  103.         IF abc >= ab THEN CALL RussianSortingHalvesDAV(ab, abc, part + 1, age)
  104.         IF xyz <= yz THEN CALL RussianSortingHalvesDAV(xyz, yz, part + 1, age)
  105.     END IF
  106.  
  107.  
  108. 'QS is DIM SHARED to compare to Danilin's method that needs two DIM SHARED Arrays for his SUB
  109. SUB qSort (start AS LONG, finish AS LONG)
  110.     DIM Hi AS LONG, Lo AS LONG, Middle AS SINGLE
  111.     Hi = finish: Lo = start
  112.     Middle = QS((Lo + Hi) / 2) 'find middle of array
  113.     DO
  114.         DO WHILE QS(Lo) < Middle: Lo = Lo + 1: LOOP
  115.         DO WHILE QS(Hi) > Middle: Hi = Hi - 1: LOOP
  116.         IF Lo <= Hi THEN
  117.             SWAP QS(Lo), QS(Hi)
  118.             Lo = Lo + 1: Hi = Hi - 1
  119.         END IF
  120.     LOOP UNTIL Lo > Hi
  121.     IF Hi > start THEN qSort start, Hi
  122.     IF Lo < finish THEN qSort Lo, finish
  123.  

EDIT: Sorry, in QSort sub, I had Middle dimensioned as _FLOAT, it should be single like the rest of the array items. It made a significant difference to timed test, now QSort compares even better!
« Last Edit: October 28, 2018, 11:35:12 am by bplus »

Offline DANILIN

  • Forum Regular
  • Posts: 128
    • View Profile
    • Danilin youtube
Re: Russian Sorting Halves Danilin
« Reply #13 on: October 28, 2018, 11:42:04 am »
comparisons have long been known:

faster than:
selection insertion binary bubble
gnome comb heap smooth odd-even
cocktail bitonic cyrcle blockmerge

slower than:
merge quick shell radix tim

faster than human natural sorts
slower than machine sorts understandable <1% of people
Russia looks world from future. big data is peace data.
https://youtube.com/playlist?list=PLBBTP9oVY7IagpH0g9FNUQ8JqmHwxDDDB
i never recommend anything to anyone and always write only about myself

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Russian Sorting Halves Danilin
« Reply #14 on: October 28, 2018, 12:15:11 pm »
Hi Danilin,

What's with all the file crap in your demo? It makes no sense. Sorry to be blunt.