Results 1 to 27 of 27

Thread: Sort Routine?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    299

    Arrow Easy Sort Routine

    I want a sort routine that runs quick and is efficient. I don't mind if its a bubble sort, or quick sort. Just something that is quick.
    What i have is a type structure array:
    Code:
    Type stuff
        aString as String * 12
        aMaxVal as long
        aMinVal as long
    end type
    
    public stuffArray() as stuff
    
    Private Sub Form_Load()
        variableNumber = Int((rnd * 20)+1)
        redim stuffArray(1 to variableNumber)
    end sub
    Ok, now thats a little clearer. I have that array, that is variably sized. I now want a sort routine, to sort on the percentage made by:
    Code:
        percentage = int((aMinVal / aMaxVal) * 100)
    and then place the sorted array into another array to be passed back from the sub, ie
    Code:
    Private Sub sortArray(incomingArray() as stuff, sortedArray() as stuff)
    That way i can pass the array in, and get the ubound and lbound of it and send one of the same size back.

    Any ideas? It seems fairly simple and i have a sort routine at the moment, but it seems to bulky. I know it can be done better.
    Cheers
    BW

    [Edited by But_Why on 09-21-2000 at 04:28 PM]

  2. #2
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Okay, dunno the quickest way to sort but one I usually use is a selection sort - go through the array and pick out the next highest/lowest a number of times equal to the number of elements.

    Don't quite remember but I think arrays are always passed ByRef.

    Code:
    Private Sub sortArray(incomingArray() as stuff, sortedArray() as stuff)
    Redim sortedArray(Ubound(incomingArray)) 'dunno if you need this
    Dim max As Integer
    Dim maxPercentage As Integer you want
    For x = 1 To Ubound(incomingArray)
      max = x
      maxPercentage = 0
      For y = x To Ubound(incomingArray)
        With incomingArray(y)
          If Int((.aMinVal / .aMaxVal) * 100) > maxPercentage Then
            maxPercentage = Int((.aMinVal / .aMaxVal) * 100)
            max = x)
          End If
        End With
      Next y
      sortedArray(x) = incomingArray(max)
    Next x
    End Sub
    I haven't tested it but so far as I can tell that code is a selection sort, customised for what you need.

    [Edited by HarryW on 09-21-2000 at 05:09 PM]
    Harry.

    "From one thing, know ten thousand things."

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    299

    Smile If you put ....

    Code:
    dim upBound as long
    upBound = Ubound(incomingArray)
    and replace Ubound(incomingArray) with upBound whereever you have used it, i have heard its quicker, cos it doesn't have to recalculate it everytime.
    But i could be wrong, and thanks for the quick reply.
    Will try it out.
    Cheers
    BW

    Originally posted by HarryW
    Okay, dunno the quickest way to sort but one I usually use is a selection sort - go through the array and pick out the next highest/lowest a number of times equal to the number of elements.

    Don't quite remember but I think arrays are always passed ByRef.

    Code:
    Private Sub sortArray(incomingArray() as stuff, sortedArray() as stuff)
    Redim sortedArray(Ubound(incomingArray)) 'dunno if you need this
    Dim max As Integer
    Dim maxPercentage As Integer you want
    For x = 1 To Ubound(incomingArray)
      max = x
      maxPercentage = 0
      For y = x To Ubound(incomingArray)
        With incomingArray(y)
          If Int((.aMinVal / .aMaxVal) * 100) > maxPercentage Then
            maxPercentage = Int((.aMinVal / .aMaxVal) * 100)
            max = x)
          End If
        End With
      Next y
      sortedArray(x) = incomingArray(max)
    Next x
    End Sub
    I haven't tested it but so far as I can tell that code is a selection sort, customised for what you need.

    [Edited by HarryW on 09-21-2000 at 05:09 PM]

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    299

    Unhappy Nope its no good.

    i have heard that a selection sort is good, as its quick for small arrays, which i have, but the code you gave me is a no go.
    It simply prints out the exact same order as before.
    And if i change max = x in the if statement to max = y i only get all the same value (as one of the lower items in the array has the largest percentage)
    Any ideas how i need to change this to fix it?
    BW
    (knowing my luck its something bloody obvious, but i can't for the life of me see it yet !!!)

  5. #5
    Fanatic Member
    Join Date
    Mar 2000
    Location
    That posh bit of England known as Buckinghamshire
    Posts
    658
    Here is a quicksort that i picked up off the web and have modified because it was for VBA.

    Simply change the type, and which property of the type to sort on.

    Code:
    'to call it
    Quicksort apiArray, LBound(apiArray), UBound(apiArray)
    
    Sub Quicksort(values() As APIType, _
                  ByVal min As Long, _
                  ByVal max As Long)
    
      Dim med_value As APIType
      Dim hi As Long
      Dim lo As Long
      Dim i As Long
    
      ' If the list has only 1 item, it's sorted.
      If min >= max Then Exit Sub
    
      ' Pick a dividing item randomly.
      Randomize
      i = min + Int((max - min) \ 2)
      
      med_value = values(i)
    
      ' Swap the dividing item to the front of the list.
      values(i) = values(min)
    
      ' Separate the list into sublists.
      lo = min
      hi = max
      Do
        ' Look down from hi for a value < med_value.
        Do While StrComp(values(hi).Name, med_value.Name, vbTextCompare) >= 0
          hi = hi - 1
          If hi <= lo Then Exit Do
        Loop
    
        If hi <= lo Then
          ' The list is separated.
          values(lo) = med_value
          Exit Do
        End If
    
        ' Swap the lo and hi values.
        values(lo) = values(hi)
    
        ' Look up from lo for a value >= med_value.
        lo = lo + 1
        Do While StrComp(values(lo).Name, med_value.Name, vbTextCompare) <= 0
        lo = lo + 1
          If lo >= hi Then Exit Do
        Loop
    
        If lo >= hi Then
          ' The list is separated.
          lo = hi
          values(hi) = med_value
          Exit Do
        End If
    
        ' Swap the lo and hi values.
        values(hi) = values(lo)
      Loop ' Loop until the list is separated.
    
      ' Recursively sort the sublists.
      Quicksort values, min, lo - 1
      Quicksort values, lo + 1, max
    
    End Sub
    A heap sort would be even quicker, but i do not have the code for it, and i am not about to write it when i already have a quicksort.

    [Edited by Iain17 on 09-21-2000 at 06:22 PM]
    Iain, thats with an i by the way!

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    299

    Unhappy No more ideas?

    No-one can see what is wrong with this one???
    Megatron, you seem to be good at finding things. Any Ideas?
    Anyone? I have seen that quicksort, and i would prefer the selection sort. Anyone see why it doesn't work. I can see why? but not how to fix it.
    BW :COOL:

  7. #7
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    I'll take a look at it, sorry it didn't work first time

    Oh I just realised, it's meant to sort an array, not copy to a new array. I'll modify it.
    Harry.

    "From one thing, know ten thousand things."

  8. #8
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Code:
    Private Sub sortArray(incomingArray() As stuff, sortedArray() As stuff)
    For x = LBound(sortedArray) To UBound(sortedArray)
        sortedArray(x) = incomingArray(x)
    Next x
    Dim max As Integer
    Dim maxPercentage As Integer
    Dim temp As stuff
    For x = 1 To UBound(sortedArray)
      max = x
      maxPercentage = 0
      For y = x To UBound(sortedArray)
        With sortedArray(y)
          'If Int((.aMinVal / .aMaxVal) * 100) < maxPercentage Then 'for ascending order use this line
          If Int((.aMinVal / .aMaxVal) * 100) > maxPercentage Then 'for descending order use this line
            maxPercentage = Int((.aMinVal / .aMaxVal) * 100)
            max = y
          End If
        End With
      Next y
      'swap
      temp = sortedArray(max)
      sortedArray(max) = sortedArray(x)
      sortedArray(x) = temp
    Next x
    End Sub
    There that should do it Choose a line for the if statement depending on whether you want ascending or descending order.
    Harry.

    "From one thing, know ten thousand things."

  9. #9
    _______ HeSaidJoe's Avatar
    Join Date
    Jun 1999
    Location
    Canada
    Posts
    3,946

    <?>

    Code:
    'this is an example of bubble sort
    'it will pass you back your array sorted.
    
    Option Explicit
    
    Sub SortNumbers(iArray As Variant)
         
         Dim lLoop1 As Long
         Dim lLoop2 As Long
         Dim lTemp As Long
         
         For lLoop1 = UBound(iArray) To LBound(iArray) Step -1
           For lLoop2 = LBound(iArray) + 1 To lLoop1
    
             If iArray(lLoop2 - 1) > iArray(lLoop2) Then
               lTemp = iArray(lLoop2 - 1)
               iArray(lLoop2 - 1) = iArray(lLoop2)
               iArray(lLoop2) = lTemp
             End If
           Next lLoop2
         Next lLoop1
       End Sub
    
    Private Sub Command1_Click()
       ' make your array
       ' whatever else
       Call SortNumbers(yourarray)
       'do whatever..insert the array into next whatevers
       
    End Sub
    "A myth is not the succession of individual images,
    but an integerated meaningful entity,
    reflecting a distinct aspect of the real world."

    ___ Adolf Jensen

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    299

    Talking Thanks Harry!!!

    Its all go! Excellent.

    Thanks for that.
    BW

  11. #11
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Happy to help
    Harry.

    "From one thing, know ten thousand things."

  12. #12
    Guest

    Cool

    Hello guys,

    This code works well, except for 1 minor thing,
    maxPercentage should be initialized to sortedArray(x) instead of 0.
    0 works fine for descending order, but will not work for ascending. Also first For.. Next loop is not needed as sort can be done on incoming array, don't really need output array.



    Private Sub sortArray(incomingArray() As stuff, sortedArray() As stuff)
    For x = LBound(sortedArray) To UBound(sortedArray)
    sortedArray(x) = incomingArray(x)
    Next x
    Dim max As Integer
    Dim maxPercentage As Integer
    Dim temp As stuff
    For x = 1 To UBound(sortedArray)
    max = x
    maxPercentage = 0
    For y = x To UBound(sortedArray)
    With sortedArray(y)
    'If Int((.aMinVal / .aMaxVal) * 100) < maxPercentage Then 'for ascending order use this line
    If Int((.aMinVal / .aMaxVal) * 100) > maxPercentage Then 'for descending order use this line
    maxPercentage = Int((.aMinVal / .aMaxVal) * 100)
    max = y
    End If
    End With
    Next y
    'swap
    temp = sortedArray(max)
    sortedArray(max) = sortedArray(x)
    sortedArray(x) = temp
    Next x
    End Sub

  13. #13
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    The element sortedArray(x) isn't an integer, it's of type stuff. Perhaps you mean the percentage given in that array element. Other than that it's fair comment, but the function still needs editing to change it to work in ascending order.

    Secondly, on the subject of the first For...Next loop: it is necessary given the Sub prototype specified, which has an input array and an output array as parameters. I said this in the post before my second block of code. A selection sort works by sorting an existing array, not creating a new, sorted array.
    Harry.

    "From one thing, know ten thousand things."

  14. #14
    Guest

    Smile

    "element sortedArray(x) isn't an integer, it's of type stuff. Perhaps you mean the percentage given in that array element."
    Yes, that's what I meant. Off course you still need to use either < or > for ascending or descending order.

    "For...Next loop"
    You need just one array, you don't need to pass 2 of them, unless you need one unsorted and one sorted.
    Anyway code works fine, I'm using it, thanks.

  15. #15
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221

    Sort shell

    Ok, this is supposed to be fastest (or is it? I haven't seen any one like Harrys before
    Code:
    Sub Sort_shell(a() As String)
    Dim n&, i&, j&, k&, h
     
        n = UBound(a)
        k = n \ 2
        While k > 0
            For i = 0 To n - k
                j = i
                While (j >= 0) And (a(j) > a(j + k))
                h = a(j)
                a(j) = a(j + k)
                a(j + k) = h
                If j > k Then
                    j = j - k
                Else
                    j = 0
                End If
                Wend
            Next i
            k = k \ 2
        Wend
    End Sub
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  16. #16
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Aostrowski: I am well aware that only one array is needed for a selection sort but if you read the function prototype you will see that it specifies an input and an output array. Thus that is what I provided.

    Kedaman: is that a binary sort, or a bisection sort or whatever it's called? Is it faster than selection sort? A selection sort always requires n²/4 passes through the loop I think, where n is the number of elements. Any idea how much quicker yours is?
    Harry.

    "From one thing, know ten thousand things."

  17. #17
    Fanatic Member
    Join Date
    Mar 2000
    Location
    That posh bit of England known as Buckinghamshire
    Posts
    658
    I give up, take a look at the quicksort if you want speed. Alternativley, go for a heap sort as i said.
    Iain, thats with an i by the way!

  18. #18
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    well shellsort isn't the fastest, i just heard there was something like radix sort or something, way too advanced to be beaten.
    But shell sort is amazing fast anyway: n
    in other words proportional to the amount of items
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  19. #19
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    I did some comparing between the sorting routines i know (I added Kedaman's Sort_Shell method, I didn't know that one yet).
    I sorted an array of 10000 strings which were all 50 characters long.
    These are the results:
    Bubble sort : 83.77213 secs
    Selection sort : 50.87294 secs
    Sort Shell : 0.9384375 secs
    Quick sort : 0.2765 secs

    So I would go for quick sort.

    P.S. I used my PII 400 MHz and the compiled vb app.

  20. #20
    Fanatic Member
    Join Date
    Jul 2000
    Location
    Manchester NH
    Posts
    833
    ok Kedaman..

    I need to sort election results

    candidate(0) = "Bush"
    Votes(0) = "1000"
    Candidate(1) = "Gore"
    Votes(1)= "1200"


    now I know how to sort the votes but how can I get Candidates to follow.

    What about a multidementional array
    Candidate(0,0) = "Bush"
    Votes(0,1) = "1000"
    Candidate(1,0) = "Gore"
    Votes(1,1) = "1200"

    what do I do or How Should I store my data differently
    Kurt Simons
    [I know I'm a hack but my clients don't!]

  21. #21
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Thumbs up

    With the quicksort function above, I got an average time of 4.5 seconds with the following specs:

    266mhz cpu
    vba 6 (word 2000)
    10,000 items (every item out of order)
    no interface updates at all during sorting

    Please note that I could not test this in stand alone vb as I lost it in my housefire. If anybody knows of a good download site or a place I can get vb cheap, it would be much appreciated.

  22. #22
    Guest
    hi kurtsimons,
    You can do array of types and sort on whatever you like.

  23. #23
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    Yeah, Quicksorts quicker than ever!
    Now kurtsimons, it would be faster to sort an UDT array but if you nessesary need two arrays, pass the array you want to sort by and then swap both arrays with the same indexes
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  24. #24
    Fanatic Member
    Join Date
    Jul 2000
    Location
    Manchester NH
    Posts
    833
    Oh Ya, simple questions get simple answers!
    Kurt Simons
    [I know I'm a hack but my clients don't!]

  25. #25
    Fanatic Member
    Join Date
    Mar 2000
    Location
    That posh bit of England known as Buckinghamshire
    Posts
    658
    Ok, sorry, but I thought I would stick my nose in again.

    While the quicksort is indeed very quick, you need to use a bit of caution if you want to implement it. While I have not had a problem with it recently, I did have a problem with it on an older machine at work which did not have much memory.

    Because the quicksort is recursive, you can of course run out of stack space. While you will probably need an extremely big list for this to happen on a modern computer, keep it in mind. If you have any doubts, use Kedaman’s shells sort.
    Iain, thats with an i by the way!

  26. #26
    Hyperactive Member
    Join Date
    Nov 2000
    Location
    Mexico City
    Posts
    306
    Hey Kedaman, I think your code has a tiny bug: when I pass a two-record array, it doesn´t sort it. I noticed ´cause I´m using it on a new sort I´m doing. It is recursive and it allows you to make a multi-field sort. Each field could be ordered ascendent or descendent. The best part of it: you could change the sort part to use another method just changing one line. If someone is interested, let me know and I´ll post it here.
    If things were easy, users might be programmers.

  27. #27
    Addicted Member RCharlton's Avatar
    Join Date
    Mar 2000
    Location
    London, UK
    Posts
    202

    StringSwap

    is also a useful way of speeding it up - you swap the pointers and not the values:


    Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" _
    (Dest As Any, Src As Any, ByVal cb As Long)

    Public Sub StringSwap(strOne As String, strTwo As String)

    Dim lngTemp As Long

    'Store a copy of the pointer to first string
    lngTemp = StrPtr(strOne)

    'Replace pointer to strOne with pointer to strTwo
    CopyMem ByVal VarPtr(strOne), ByVal VarPtr(strTwo), 4

    'Replace pointer to strTwo with stored pointer
    CopyMem ByVal VarPtr(strTwo), lngTemp, 4

    End Sub

    -- many many times faster
    Richard Charlton

    VB 6.0, Java 2.0, C++, PHP, Perl, HTML, Javascript

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width