Snippet The QSort Algorithm

SerraAvenger

Cuz I can
Reaction score
234
The QuickSort Algorithm

requires:
- JassPack NewGen
- Jass Knowledge


This code sorts the ToSort array and the ParallelSort one at the same time.
It works quite fast, for the smaller subarrays it uses insert sort to keep the stack lower and for the bigger sorting it uses QSort with some sort of "median of two". Simply copy this in your map header, and then copy the array you want to sort in the ToSort array, run QSort on the fields you want to sort ( like from 2 to 700, use QSort( 2 , 700 ) ) and then copy the data back.

JASS:
//*********************************************************************
// The Quicksort Algorithm                                            *
//   - Median of two ; Insertsort for arrays of 4 and less-           *
// Expected efficiency  : O( n * log n )                              *
// Worst case efficiency: O( n² )                                     *
//**********************************************************************************************************************
//* !!! All array members that will be sorted need to have a value! All Parallelsort fields need to have a value too!  *
//* !!! The Tosort Variable needs to be of Type Integer!                                                               *
//* !!! To use it, write //! runtextmacro QSORT( the array to be sorted, the array to be parallely sorted, and the     *
//*     type of the array that is sorted parallely. Example:                                                           *
//*     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    *
//      globals                                                                                                        
//          integer array HeroLevel                                                                                    
//          unit    array Heroes                                                                                       
//          integer       NumHeroes                                                                                    
//      endglobals                                                                                                     
//                                                                                                                     
//      //! runtextmacro QSORT( HeroLevel , Heroes, unit )                                                             
//                                                                                                                     
//      function DisplayMaxHeroLevel takes nothing returns nothing                                                         
//          call QSortHeroLevel( 0 , NumHeroes )
//          call DisplayTextToPlayer( GetLocalPlayer() , 0 , 0 , "|cffffcc00The highest-level Hero is " + GetUnitName( Heroes[ NumHeroes ] ) )                                                                                *
//      endfunction
//     
//*    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -    *
//*    So to make the array sortable, run the textmacro. Then to actually sort it, use                                 *
//*           
//          call QSort[the array to be sorted]( lower sorting bound , upper sorting bound )
//*
//*    Not difficult at all, is it?                                                                                    *
//*    Only bad thing: You allways need a filled parallelsort for it, which needs to be different from the array to be *
//*    sorted. Most probably you would've needed it anyway, but not allways.                                           *
//**********************************************************************************************************************
//* Coded by Cpt.DaveyJones/SerraAvenger, invented by C. A. R. Hoare

library QuickSort

//! textmacro QSORT takes TOSORT , PARALLELSORT , PARALLELTYPE

    
    function InsertSort$TOSORT$ takes integer lowerbound, integer upperbound returns nothing
        local integer outerLoop = lowerbound + 1
        local integer innerLoop
        local integer key                                                    
        local $PARALLELTYPE$ lock      
        loop
            exitwhen outerLoop > upperbound
            set innerLoop = outerLoop

            set key  = $TOSORT$      [ outerLoop ]
            set lock = $PARALLELSORT$[ outerLoop ]
            loop
                exitwhen innerLoop <= lowerbound
                exitwhen $TOSORT$ [ innerLoop - 1 ] < key
                set $TOSORT$      [ innerLoop ] = $TOSORT$      [ innerLoop - 1 ]
                set $PARALLELSORT$[ innerLoop ] = $PARALLELSORT$[ innerLoop - 1 ]
                set innerLoop     = innerLoop - 1
            endloop
            set $TOSORT$      [ innerLoop ] = key
            set $PARALLELSORT$[ innerLoop ] = lock
            
            set outerLoop = outerLoop + 1
        endloop
        //if not ("$PARALLELTYPE$" == "integer" or "$PARALLELTYPE$" == "real"  ) then
        //    set lock = null
        //endif 
    endfunction
    

    function QSort$TOSORT$ takes integer lowerbound, integer upperbound returns nothing
        local integer pivot          = ( $TOSORT$[ lowerbound ] + $TOSORT$[ upperbound ] + $TOSORT$[ GetRandomInt( lowerbound, upperbound ) ] ) / 3
        local integer leftIndicator  = lowerbound
        local integer rightIndicator = upperbound
        local integer tempValue
        local $PARALLELTYPE$ tempParallelValue 
        if upperbound - lowerbound > 8 then

            loop

                loop
                    exitwhen $TOSORT$[ rightIndicator ] < pivot
                    exitwhen rightIndicator == leftIndicator 
                    set rightIndicator = rightIndicator - 1
                endloop
                loop
                    exitwhen $TOSORT$[ leftIndicator ] >= pivot
                    exitwhen leftIndicator == rightIndicator
                    set leftIndicator = leftIndicator + 1
                endloop
                exitwhen leftIndicator > rightIndicator
                
                set tempValue                  = $TOSORT$[ rightIndicator ]
                set $TOSORT$[ rightIndicator ] = $TOSORT$[ leftIndicator  ]
                set $TOSORT$[ leftIndicator  ] = tempValue


                set tempParallelValue                = $PARALLELSORT$[ rightIndicator ]
                set $PARALLELSORT$[ rightIndicator ] = $PARALLELSORT$[ leftIndicator  ]
                set $PARALLELSORT$[ leftIndicator  ] = tempParallelValue
            endloop
            call QSort$TOSORT$( lowerbound         , leftIndicator )                                                                        
            call QSort$TOSORT$( rightIndicator + 1 , upperbound    )

        else
            call InsertSort$TOSORT$( lowerbound, upperbound )
        endif
        
    endfunction
    
//! endtextmacro                             
endlibrary

If anyone requests a demo map I'll add one, but I don't think that sorting would need demonstration : /

Hf with your faster sorting
Davey

EDIT: Uploaded Demo map. Simply open it with Grimoire running and enter -test XXXX , with XXXX being the integer on your choice. It will then fill the first XXXX fields of the ToSort array with random integers between 1 and XXXX, and then apply quicksort. After the sorting has finished, all the numbers will be shown in sorted order. After 740 it will most probably hit the op limiter.

Demo map and attached text file currently out of date! Please do not use.
 

Attachments

  • QSortTest.w3x
    20 KB · Views: 230
  • QSort.txt
    4.7 KB · Views: 261

Cohadar

master of fugue
Reaction score
209
wow nice one :)

I see someone has been paying attention at school ;)

Try making heapsort after this, I believe it will work faster than qsort in jass.
It is easier to code anyways.

heh, you just made my day with this, +rep.
 

SerraAvenger

Cuz I can
Reaction score
234
Hm I thought of making Binary search first, and then I still can do other sorting algorithms.

@Flare: It sorts an array from the lowest to the highest number. Helps when you want to use bsearch lateron, or if you want to sort players after their kills, ( bit overkill there, you might aswell just use the integrated Insert Sort ), to sort units for their hitpoints, to sort ... Basically any integer / real, just need to change the variable.
 

SerraAvenger

Cuz I can
Reaction score
234
so for example, i have a leaderboard measuring kills. with this, i can arrange the kills of each player, and then list them from highest to lowest on the leaderboard? if so, fair enough, seems like a useful enough reason :D

Yes, although leaderboards can sort themselves. It would be better used on multiboards. Simply use the ParallelSort for the PlayerIds, and QSort then.
Greetings Davey
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> like from 2 to 12414

12000+ ?


How many values, on average, can this sort before hitting the operation limit?
How many values do you need at least for this to be faster than bubble sort?

And, to sort a multiboard, I definitely recommend a leaderboard.
Sorting is instant, and you get the players for free.
 

SerraAvenger

Cuz I can
Reaction score
234
> like from 2 to 12414

12000+ ?


How many values, on average, can this sort before hitting the operation limit?
How many values do you need at least for this to be faster than bubble sort?

And, to sort a multiboard, I definitely recommend a leaderboard.
Sorting is instant, and you get the players for free.

Sorting works in JASS for arround 740 integers before hitting the op limit, 700 is recommended. Sorting works instantly for 740 integers. Especially for long multiboards, I recommend this ; P

That's why I use Insertion sort on partitions of 5 or less, right ; ) Thus Bubblesort is never faster than this.
 

SerraAvenger

Cuz I can
Reaction score
234
Bump

wow nice one :)

I see someone has been paying attention at school ;)

Try making heapsort after this, I believe it will work faster than qsort in jass.
It is easier to code anyways.

heh, you just made my day with this, +rep.

Got a better Idea. Let's use bogosort!


j/k
 

SerraAvenger

Cuz I can
Reaction score
234
BUMP
1. why did this get into Graveyard?^^
2. I tested with an optimized Bubblesort, and it raised expetions at 100 items in the best case. So allready this version was 7 times better, and it ahd a small bug: I forgot a tiny > ^^
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top