maybe so but not into one line of code.
Dim JpgByteArray As Byte() = My.Computer.FileSystem.ReadAllBytes(FN)
Printable View
maybe so but not into one line of code.
Dim JpgByteArray As Byte() = My.Computer.FileSystem.ReadAllBytes(FN)
Your going to sort all the bytes? Then use heap or bit based sortQuote:
Originally Posted by Lord Orwell
No problem on the Library sort; it is now officially dropped.Quote:
Originally Posted by Logophobic
The Gnome sort description was taken from a combination of the wikipedia entry for Gnome sort plus an external link in the wikipedia entry. While it is conceptually similar to insertion sort, the implementation is noticeably different.Are you saying the core algorithm already exists, and the only optimization is API memory trickery? If so, then I wouldn't consider it a separate sort. (A great idea, just not relevent for what I'm trying to accomplish.)Quote:
Originally Posted by leinad31
The basic goal here is to set up a repository of generic implementations for as many unique sorting algorithms as possible. Some may lend themselves to a particular optimization, but that's up to the end programmer. I'm just looking to provide the basic frameworks in as simple a form as possible.
All sorts now in and functional except for Merge sort (which calls bubblesort, annoying me to no end) and leinad's method. Should I bother incorporating that, leinad, or does it just boil down to an "off the rack" sorting algorithm?
Off to watch the French Open Finals...Go Roger!
I'm saying its where the most speed boost comes from, its not trickery, the number of swaps is as important as the number of comparisons. That was the point of using linked lists in languages that supports linked lists, reduce number of swaps. Will you narrow mindedly label that too as OS related trcikery?
Forget it, use whatever metric you please as its your thread. Our POV on the matter is too differentiated, such as you believe that stability doesn't matter among other things that should matter.
No offense was intended by the term trickery. This thread is about algorithms, not implementations. I'm quite confused as to why you seem so angry.
As far as stability, it is a widely accepted fact that stability is not a requirement in sorting algorithms. You yourself even admitted as much when you said this:If stability is one of the criteria, then by definition it is not required. If stability were required, then all sorting algorithms would be stable and therefore it wouldn't be a criteria in the first place, but rather part of the definition. Also of note is that stability is wholly irrelevent for single dimension arrays.Quote:
Originally Posted by leinad31
The fact that you equate "not a requirement" with "doesn't matter" boggles my mind. And as far as your claim (in post 19) that heapsort and quicksort are stable, you may want to update wikipedia; they are both listed as unstable.
I offer you Odd-Even Sort (similar to Cocktail Sort and Bubble Sort) and a Shaker Sort.I haven't done any benchmarking with them.Code:Option Explicit
Public Function ArrayInit(ByVal NotValue As Long) As Boolean
ArrayInit = Not (NotValue = -1&)
If App.LogMode <> 0 Then Exit Function
On Error Resume Next
Debug.Assert 0.1
On Error GoTo 0
End Function
Public Function OddEvenSort(ByRef LongArray() As Long) As Long()
Dim lngLB As Long, lngUB As Long, lngOut() As Long, NoSwap As Boolean
Dim lngA As Long, lngTemp As Long
If ArrayInit(Not LongArray) Then
lngLB = LBound(LongArray) - 1
lngUB = UBound(LongArray) - 1
If lngLB < lngUB Then
lngOut = LongArray
Do Until NoSwap
NoSwap = True
lngLB = lngLB + 1
For lngA = lngLB To lngUB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
If Not NoSwap Then
NoSwap = True
lngUB = lngUB - 1
For lngA = lngUB To lngLB Step -1
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
End If
Loop
OddEvenSort = lngOut
Else
OddEvenSort = LongArray
End If
End If
End Function
Public Function ShakerSort(ByRef LongArray() As Long) As Long()
Dim lngLB As Long, lngUB As Long, lngOut() As Long, NoSwap As Boolean
Dim lngA As Long, lngB As Long, lngC As Long, lngTemp As Long
If ArrayInit(Not LongArray) Then
lngLB = LBound(LongArray)
lngUB = UBound(LongArray)
If lngLB < lngUB Then
lngOut = LongArray
lngA = lngUB \ 2
Do While lngA > 0
lngB = lngA
Do While lngB > 0
For lngC = 0 To lngUB - lngB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
End If
Next lngC
lngB = lngB \ 2
Loop
lngA = lngA \ 2
Loop
lngUB = lngUB - 1
Do Until NoSwap
NoSwap = True
For lngA = lngLB To lngUB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
If Not NoSwap Then
NoSwap = True
lngUB = lngUB - 1
For lngA = lngUB To lngLB Step -1
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
lngLB = lngLB + 1
End If
Loop
ShakerSort = lngOut
Else
ShakerSort = LongArray
End If
End If
End Function
Site that might be of an interest: http://cg.scs.carleton.ca/~morin/misc/sortalg/
Sweet, thanks much Merri. The Odd-Even sort looks identical to the Cocktail sort; you mentioned that it's similar but I suspect they are just different names for the same algorithm. That shaker sort looks cool and wholly unique. (Holy nested loops, Batman! heh.) I'll toss it in in place of library sort.
It isn't entirely identical: see the details in the second loop. Cocktail uses - 1, Odd-Even uses + 1.
Ah yes. It's funny, I ended up implementing the cocktail sort as an odd-even sort. That was one I didn't bother googling, but instead just freehanded it based on the wiki pseudocode.Quote:
Originally Posted by Merri
Using the - 1 technique in C is great, but converting it to VB doesn't quite work right, since vb doesn't have a clean way to write the for loop:I could have done it like this:vb Code:
for(i = top; i > bottom; i = i - 1)But that introduces a needless calculation in an inner loop. The odd-even implementation is much better for vb.vb Code:
For i = top To bottom + 1 Step -1
I just noticed your link, btw. I sat here for like ten solid minutes just watching the little lines getting arranged. Too cool.
That link shows a kickass algorithm called JSort. Do you know what that is? I'd love to add it.
http://en.wikipedia.org/wiki/Categor...ing_algorithms
http://en.wikipedia.org/wiki/JSort
And the page I linked to in my earlier post also has links to Java source.
JSort implemented:Code:Option Explicit
Public Function ArrayInit(ByVal NotValue As Long) As Boolean
ArrayInit = Not (NotValue = -1&)
If App.LogMode <> 0 Then Exit Function
On Error Resume Next
Debug.Assert 0.1
On Error GoTo 0
End Function
Public Function JSort(ByRef LongArray() As Long) As Long()
Dim lngLB As Long, lngUB As Long, lngOut() As Long, NoSwap As Boolean
Dim lngA As Long, lngB As Long, lngTemp As Long
If ArrayInit(Not LongArray) Then
lngLB = LBound(LongArray)
lngUB = UBound(LongArray)
If lngLB < lngUB Then
lngOut = LongArray
For lngA = lngUB To lngLB Step -1
JSort_ReHeap lngOut, lngUB, lngA
Next lngA
For lngA = lngUB To lngLB Step -1
JSort_InvReHeap lngOut, lngUB, lngA
Next lngA
For lngB = lngLB + 1 To lngUB
lngTemp = lngOut(lngB)
lngA = lngB - 1
Do While lngA >= lngLB And lngOut(lngA) > lngTemp
lngOut(lngA + 1) = lngOut(lngA)
lngA = lngA - 1
Loop
lngOut(lngA + 1) = lngTemp
Next lngB
JSort = lngOut
Else
JSort = LongArray
End If
End If
End Function
Public Sub JSort_InvReHeap(ByRef LongArray() As Long, ByVal UpBound As Long, ByVal Current As Long)
Dim lngTemp As Long, lngParent As Long, lngChild As Long, blnDone As Boolean
lngTemp = LongArray(UpBound - Current)
lngParent = Current
lngChild = 2 * (Current + 1) - 1
Do While lngChild <= UpBound And Not blnDone
If lngChild < UpBound Then
If LongArray(UpBound - lngChild) >= LongArray(UpBound - lngChild + 1) Then
lngChild = lngChild + 1
End If
If lngTemp > LongArray(UpBound - lngChild) Then
blnDone = True
Else
LongArray(UpBound - lngParent) = LongArray(UpBound - lngChild)
lngParent = lngChild
lngChild = 2 * (lngParent + 1) - 1
End If
End If
Loop
LongArray(UpBound - lngParent) = lngTemp
End Sub
Public Sub JSort_ReHeap(ByRef LongArray() As Long, ByVal UpBound As Long, ByVal Current As Long)
Dim lngTemp As Long, lngParent As Long, lngChild As Long, blnDone As Boolean
lngTemp = LongArray(Current)
lngParent = Current
lngChild = 2 * (Current + 1) - 1
Do While lngChild <= UpBound And Not blnDone
If lngChild < UpBound Then
If LongArray(lngChild) >= LongArray(lngChild + 1) Then
lngChild = lngChild + 1
End If
If lngTemp < LongArray(lngChild) Then
blnDone = True
Else
LongArray(lngParent) = LongArray(lngChild)
lngParent = lngChild
lngChild = 2 * (lngParent + 1) - 1
End If
End If
Loop
LongArray(lngParent) = lngTemp
End Sub
The fact that your writing source code, and making selective decisions about which language feature to use or applies, makes it an implementation.Quote:
Originally Posted by Ellis Dee
I finished the benchmark and added it to the CodeBank here. I ended up deciding to only include native algorithms, excluding hybrids like JSort. (JSort's performance was awful, btw.) Mostly because including hybrids opens up an ocean of additional possibilities, but also because I never found a hybrid that outperformed the "better" native function.
For example, no matter how I hybridized (?) merge sort, none of them were as fast as a pure merge sort. And JSort was nowhere near the speed of a native heap sort. Maybe that's a quirk of the VB6 compiler; I don't know.
A couple bug reports:
Code Doc, Jump Sort fails if there are only two elements, because (UBound() - LBound()) \ 2 = 0, so it compares (i) with (i+0), which isn't very helpful. It doesn't hang or throw a runtime error or anything, rather it just leaves the array unsorted. I added a check to handle this issue.
Merri, there is a bug in your JSort implementation in both the Heap and InvHeap functions. The Do lines......should use "<" instead of "<=", otherwise the loops hang when lngChild = UpBound.Code:Do While lngChild <= UpBound And Not blnDone
There appears to be two different versions of JSort, the other being under the name J sort. A writer claims it can be up to 30 times faster than quicksort; guess that can only be tested by writing the function, but this far I haven't found a code example (and don't have the time right now to do so).
That sounds intriguing. If you run across some code and don't have time, post a link here and I'll take a crack at it. Doesn't much matter to me what language the code is in. (Oddly enough, I've become fairly adept at sorting logic in the past week.)
About the international separator character, I have a couple questions if you have a second. Assuming your separator character is a comma (,)...
- Wouldn't/shouldn't Str(1/2) return "0,5"?
- Is CStr(1/2) <> Str(1/2)? (Assuming they're Trim'ed, if that matters.)
- How does Format(1/2, "0.0") behave? "0,5" or "0.5"? Thinking about it, should it instead be Format(1/2, "0,0")?
- Any other tips or points of interest that you can think of?
Str$() always uses dots. It's return value is " 0.5" for positive and "-0.5" for negative numbers. Val() always uses dots.
CStr() always uses current locale. All datatype conversion/coersion functions are like this.
Format$() always uses current locale. Logic in this is that you can use Format$ to date formatting for an example, so you can get the name of the date or default date formatting in current locale settings.
In the other hand, imo using database for a simplish benchmarking program is an overkill. You wouldn't have a problem with locale if you didn't use database.
Then, some more reading for you:
http://groups.google.com/group/fido7...084cdb04008ab3
http://www.nist.gov/dads/HTML/jsort.html
http://www.softpanorama.org/Algorithms/sorting.shtml
Overkill? Me? hehheh.
I decided to go with a database for two reasons. First, all the long text displays called for Memo fields instead of hardcoded literal strings. (The strings were too long to fit on a single line in the IDE, and editing them when I had them as underscore-chained assignments was a major PITA. Much easier to edit Memo fields.) The other is because I didn't want to have to hold a copy of the unsorted array in memory while the algorithms were doing their thing; I wanted to leave all the memory available to the algorithms themselves.
Thanks much for the locale info, I appeciate it.
Ellis Dee said, "Code Doc, Jump Sort fails if there are only two elements, because (UBound() - LBound()) \ 2 = 0, so it compares (i) with (i+0), which isn't very helpful. It doesn't hang or throw a runtime error or anything, rather it just leaves the array unsorted. I added a check to handle this issue."
-----------------
Thanks for finding this one.:thumb:
For some unknown reason, I neglected to check this code with a sample of size 2. It's rather amazing that you found it in such a short period of time. Perhaps I never found it because there is a 50:50 chance that the two items are already sorted when generated randomly. Please forgive me for this oversight.:blush:
I am somewhat surprised that you converted my While...Wend loops to Do...Loop Until loops for the code bank. I suppose you had a reason for doing this, but I tend to lean toward simplicity whenever possible. Most of the microprocessors tend to like this also.
Historically, I wrote this code initially back in the 1980's by looking at a deck of cards. I took 10 playing cards from the same suit from a deck, shuffled them, and laid them face down. Then I compared the first with the sixth, the second with the seventh and so on. When I found two that were out of sequence, I swapped them and repeated until no swaps occurred.
Then I cut the jump interval in half and compared the first with the third, the second with the fourth, etc., swapping as needed. The last possible comparison is the first with the second, the second with the third, etc.
Then I turned the cards over. All were in sequence and I seldom had to repeat the last sequence twice, even if a swap was detected. The worst case scenario is when all are in reverse order before you start. The best case scenario occurs when the items are almost already in correct sequence. That's when my jump sort beats the Quicksort and stays at least even with the Shell. At that point, I wrote the source code, and it's been with my applications for over two decades.
Perhaps a third variable could be added that somehow checks the sequence on a given jump interval so that even if a swap has just occurred, a passthrough check for a swap is unnecesary at that same jump interval level, the sort would then run even faster because redundant passthroughs would vanish. However, any check that you make adds time and defeats the purpose.
I wasn't actually looking for it. When I first implemented merge sort -- which I wrote from scratch -- it kept coming up blank in the results window. A blank time (as opposed to N/A) means that it failed the verification check. So I dropped the array size down to two to see if it would work occasionally, but it still failed every time. It then became obvious that I had reversed the comparison, using < instead of >. But while I was doing this, I noticed that jump sort also came up blank a few times. Armed with the advance knowledge that it sometimes failed with an array size of two -- but never any other size -- it wasn't hard to identify the problem.Quote:
Originally Posted by Code Doc
As for the While...Wend conversion, the main reason was that I am irrationally averse to initializing the flag variable before the loop starts. (None of the implementations do any initialization.) This is a very bad VB habit, but I've made my peace with that.
Is While...Wend faster than Do...Loop?This intrigues me, but I can't quite follow it. Could you elaborate?Quote:
Perhaps a third variable could be added that somehow checks the sequence on a given jump interval so that even if a swap has just occurred, a passthrough check for a swap is unnecesary at that same jump interval level, the sort would then run even faster because redundant passthroughs would vanish. However, any check that you make adds time and defeats the purpose.
Your description of the genesis of jump sort gives me an idea for a non-recursive quicksort, which I'm sure would be much faster and less memory-intensive without the hundreds or thousands of recursive calls.
Now that I'm looking more closely at jump sort, there's still optimization to be had. Consider what happens when the jump value gets to 1: it runs through the inner loop, and then because it's non-zero, the outer loops runs again. This (final) iteration integer halves the jump value, and since 1 \ 2 = 0, the inner loop fires with a jump value of zero. That means that in every sort, the final pass compares every element against itself. Thus, n comparisons are wasted each call.
This behavior happens in both my implementation as well as the original code you posted. To correct it is simple: you need to change "While Jump" to "While Jump > 1", and I need to change "Loop Until lngJump = 0" to "Loop Until lngJump = 1".
This won't have a huge impact on performance, but hey, every little bit helps.
Ellis Dee said, "To correct it is simple: you need to change "While Jump" to "While Jump > 1", and I need to change "Loop Until lngJump = 0" to "Loop Until lngJump = 1"."
-----------------------
Terrific! You would not believe how much that improved the speed of the Jump Sort! Now after 20,000 elements or more, Jump Sort is faster than the VB sorted list box. Your simple yet ingenious improvement eliminated N comparisons.:thumb:
You asked if While...Wend is faster than Do...Loop Until. I believe it makes no difference in execution speed. I checked it by modifying my code for both the inner and outer loops. In either case, I can sort 60,000 random 9-character stings in less than 9 seconds. I used "Loop Until Jump < 2" rather than "Loop Until Jump = 1" on the outer loop and "Loop Until Not Swapped" on the inner loop. Years ago I read that inequality tests run faster than equality tests, but that may be nonsense these days.
You may now have to raise the grade you bestowed on the Jump Sort in the Code Bank from B- to B+.;)
The difference between While ... Wend and Do ... Loop is that Do allows for both While and Until conditions, and it allows you to control when the condition is checked: at the beginning of execution of the loop or at the end of it.
Speed difference is what one could call "non-existant".Code:Do While False
MsgBox "One"
Loop
Do
MsgBox "Two"
Loop While False
Merri, could you help me fix the Shaker Sort you posted? The initial loops don't actually do anything except waste an inordinate amount of time.
I noticed this yesterday and today, which is when I finally got around to implementing graphical sorts like that java page. (It's amazing how helpful graphical displays are for pinpointing faulty algorithms.)
Here's the original code you posted. I've highlighted the faulty comparisons:I think the other two comparisons are fine.Code:Public Function ShakerSort(ByRef LongArray() As Long) As Long()
Dim lngLB As Long, lngUB As Long, lngOut() As Long, NoSwap As Boolean
Dim lngA As Long, lngB As Long, lngC As Long, lngTemp As Long
If ArrayInit(Not LongArray) Then
lngLB = LBound(LongArray)
lngUB = UBound(LongArray)
If lngLB < lngUB Then
lngOut = LongArray
lngA = lngUB \ 2
Do While lngA > 0
lngB = lngA
Do While lngB > 0
For lngC = 0 To lngUB - lngB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
End If
Next lngC
lngB = lngB \ 2
Loop
lngA = lngA \ 2
Loop
lngUB = lngUB - 1
Do Until NoSwap
NoSwap = True
For lngA = lngLB To lngUB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
If Not NoSwap Then
NoSwap = True
lngUB = lngUB - 1
For lngA = lngUB To lngLB Step -1
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
lngLB = lngLB + 1
End If
Loop
ShakerSort = lngOut
Else
ShakerSort = LongArray
End If
End If
End Function
Replace lngA with lngC.
Yep, that seemed to improve it quite a bit, though it's still doing more comparisons than bubblesort. That in and of itself doesn't concern me, though.
If you look at the java page you linked upthread, they show a ShakerSort and a ShakerSortTwo. Both show the initial loops as comparing elements more than one position apart. The Shaker sort logic that you posted looks like it's intended to do something similar, though it always compares an element with one right next to it.
Is that what you intended?
Attached is a standalone form that demonstates exactly what the Shakersort is doing.
This is obviously a work in progress; ignore the comparison and exchange totals. (And mergesort is still not implemented properly.) But it will clarify what the algorithm is doing, at least.
Humm, reread the code now, I did the sort code quickly when I did it so I copied the + 1 idea from the wrong lines :)Quote:
Originally Posted by Ellis Dee
Now it should replicate ShakerSortTwo more or less accurately.Code:Public Function ShakerSort(ByRef LongArray() As Long) As Long()
Dim lngLB As Long, lngUB As Long, lngOut() As Long, NoSwap As Boolean
Dim lngA As Long, lngB As Long, lngC As Long, lngTemp As Long
If ArrayInit(Not LongArray) Then
lngLB = LBound(LongArray)
lngUB = UBound(LongArray)
If lngLB < lngUB Then
lngOut = LongArray
lngA = lngUB \ 2
Do While lngA > 0
lngB = lngA
Do While lngB > 0
For lngC = 0 To lngA - lngB
If lngOut(lngC) > lngOut(lngC + lngB) Then
lngTemp = lngOut(lngC)
lngOut(lngC) = lngOut(lngC + lngB)
lngOut(lngC + lngB) = lngTemp
End If
Next lngC
lngB = lngB \ 2
Loop
lngA = lngA \ 2
Loop
lngUB = lngUB - 1
Do Until NoSwap
NoSwap = True
For lngA = lngLB To lngUB
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
If Not NoSwap Then
NoSwap = True
lngUB = lngUB - 1
For lngA = lngUB To lngLB Step -1
If lngOut(lngA) > lngOut(lngA + 1) Then
lngTemp = lngOut(lngA)
lngOut(lngA) = lngOut(lngA + 1)
lngOut(lngA + 1) = lngTemp
NoSwap = False
End If
Next lngA
lngLB = lngLB + 1
End If
Loop
ShakerSort = lngOut
Else
ShakerSort = LongArray
End If
End If
End Function
Yep, perfect. Thanks for the help.