|
-
Sep 21st, 2000, 03:25 PM
#1
Thread Starter
Hyperactive Member
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]
-
Sep 21st, 2000, 04:03 PM
#2
Frenzied Member
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."
-
Sep 21st, 2000, 04:19 PM
#3
Thread Starter
Hyperactive Member
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]
-
Sep 21st, 2000, 05:07 PM
#4
Thread Starter
Hyperactive Member
-
Sep 21st, 2000, 05:19 PM
#5
Fanatic Member
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!
-
Sep 21st, 2000, 07:54 PM
#6
Thread Starter
Hyperactive Member
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:
-
Sep 21st, 2000, 08:39 PM
#7
Frenzied Member
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."
-
Sep 21st, 2000, 08:51 PM
#8
Frenzied Member
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."
-
Sep 21st, 2000, 08:53 PM
#9
_______
<?>
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
-
Sep 21st, 2000, 09:07 PM
#10
Thread Starter
Hyperactive Member
Thanks Harry!!!
Its all go! Excellent.
Thanks for that.
BW
-
Sep 21st, 2000, 10:55 PM
#11
Frenzied Member
Happy to help
Harry.
"From one thing, know ten thousand things."
-
Sep 25th, 2000, 03:09 PM
#12
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
-
Sep 25th, 2000, 06:23 PM
#13
Frenzied Member
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."
-
Sep 26th, 2000, 07:30 AM
#14
"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.
-
Sep 26th, 2000, 07:44 AM
#15
transcendental analytic
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.
-
Sep 26th, 2000, 05:49 PM
#16
Frenzied Member
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."
-
Sep 26th, 2000, 06:25 PM
#17
Fanatic Member
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!
-
Oct 6th, 2000, 10:31 AM
#18
transcendental analytic
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.
-
Oct 6th, 2000, 12:47 PM
#19
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.
-
Oct 9th, 2000, 02:52 PM
#20
Fanatic Member
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!]
-
Oct 9th, 2000, 04:09 PM
#21
Fanatic Member
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.
-
Oct 10th, 2000, 07:26 AM
#22
hi kurtsimons,
You can do array of types and sort on whatever you like.
-
Oct 10th, 2000, 07:35 AM
#23
transcendental analytic
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.
-
Oct 10th, 2000, 08:15 AM
#24
Fanatic Member
Oh Ya, simple questions get simple answers!
Kurt Simons
[I know I'm a hack but my clients don't!]
-
Oct 10th, 2000, 06:58 PM
#25
Fanatic Member
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!
-
May 18th, 2001, 03:06 PM
#26
Hyperactive Member
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.
-
Jul 26th, 2001, 09:24 AM
#27
Addicted Member
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|