Code: Select all
Sub siftdown(hs() As Long, start As ULong, end_ As ULong)
Dim As ULong root = start
Dim As Long lb = LBound(hs)
While root * 2 + 1 <= end_
Dim As ULong child = root * 2 + 1
If (child + 1 <= end_) AndAlso (hs(lb + child) < hs(lb + child + 1)) Then
child = child + 1
End If
If hs(lb + root) < hs(lb + child) Then
Swap hs(lb + root), hs(lb + child)
root = child
Else
Return
End If
Wend
End Sub
Sub heapsort(hs() As Long)
Dim As Long lb = LBound(hs)
Dim As ULong count = UBound(hs) - lb + 1
Dim As Long start = (count - 2) \ 2
Dim As ULong end_ = count - 1
While start >= 0
siftdown(hs(), start, end_)
start = start - 1
Wend
While end_ > 0
Swap hs(lb + end_), hs(lb)
end_ = end_ - 1
siftdown(hs(), 0, end_)
Wend
End Sub
- test for elements<2 (no sense for sorting)
- Up/Down direction
- Tagged array (just for my old PowerBasic styled app code compatibility - sort one array by another)
- array hs() - 'long' changed to 'integer' for my needs
Changes are easy to find and adaptable for your own intent.
In my old app with new Multisort feature I slowly replace old CombSort routines with HeapSort.
In previous days no problem, it works Ok.
Happy New Year 2020
Code: Select all
Sub siftdownIntegr(hs() As integer, start As ULong, end_ As ULong,TaggedA() As Integer,direction As string)
Dim As ULong root = start
Dim As Long lb = LBound(hs)
While root * 2 + 1 <= end_
Dim As ULong child = root * 2 + 1
If (child + 1 <= end_) AndAlso (hs(lb + child) < hs(lb + child + 1)) Then
child = child + 1
End If
If hs(lb + root) < hs(lb + child) Then
Swap hs(lb + root), hs(lb + child)
Swap TaggedA(lb + root), TaggedA(lb + child) 'tagged - new
root = child
Else
Return
End If
Wend
End Sub
Sub siftUpIntegr(hs() As integer, start As ULong, end_ As ULong,TaggedA() As Integer,direction As string)
Dim As ULong root = start
Dim As Long lb = LBound(hs)
While root * 2 + 1 <= end_
Dim As ULong child = root * 2 + 1
If (child + 1 <= end_) AndAlso (hs(lb + child) > hs(lb + child + 1)) Then
child = child + 1
End If
If hs(lb + root) > hs(lb + child) Then
Swap hs(lb + root), hs(lb + child)
Swap TaggedA(lb + root), TaggedA(lb + child) 'tagged - new
root = child
Else
Return
End If
Wend
End Sub
Sub heapsortInt(hs() As integer,TaggedA() As Integer,direction As string)
Dim As Long lb = LBound(hs)
Dim As ULong count = UBound(hs) - lb + 1
Dim As Long start = (count - 2) \ 2
Dim As ULong end_ = count - 1
'no sense of sorting for elements<2 (log this incident)
if count<2 then ? " heapsortInt .. <2 elements .. ended (press key)":sleep: exit sub 'just change this as file write log
Select Case direction 'ascend - descend
Case "ascend"
While start >= 0
siftdownIntegr(hs(), start, end_, TaggedA(), direction)
start = start - 1
Wend
While end_ > 0
Swap hs(lb + end_), hs(lb)
Swap TaggedA(lb + end_), TaggedA(lb) 'tagged - new
end_ = end_ - 1
siftdownIntegr(hs(), 0, end_, TaggedA(), direction)
Wend
Case "descend"
While start >= 0
siftUpIntegr(hs(), start, end_, TaggedA(), direction)
start = start - 1
Wend
While end_ > 0
Swap hs(lb + end_), hs(lb)
Swap TaggedA(lb + end_), TaggedA(lb) 'tagged - new
end_ = end_ - 1
siftUpIntegr(hs(), 0, end_, TaggedA(), direction)
Wend
Case Else
? "heapSortInt ascend - descend bad parameter .. (press key)":sleep
End Select
End Sub
Code: Select all
dim a(1234567) as integer
dim b(1234567) as integer
'...fill arrays with values
heapsortInt(a(),b(),"descend") 'sort a() array in "down" direction AND ALSO sort tagged b() array by a() array