Сортировка бинарным деревом - VBA

Узнай цену своей работы

Формулировка задачи:

Подсмотрел я тут методы и подумал - а почему бы не написать на VBA сорировку методом бинарного дерева? Общий алгоритм сортировки был на википедии, так что оставалось всего лишь написать код. В ходе кровь из носу потребовалось ознакомиться с такой штукой как классы, о которой я ранее не имел ни малейшего представления. По итогам длительных мучений: сортировать этот зверь, конечно, сортирует, но уже на 100k чисел типа Double у него уходит немалое время (порядка нескольких секунд на моем не самом резвом рабочем компьютере). К тому же в коде есть ряд шероховатостей - 1) метод Retrieve, получающий значения из уже сформированного дерева, как я с ним не бился, оставляет пустую строчку в начале или в конце массива. Работать со счетчиками он при этом решительно отказывается, так что пришлось плюнуть и просто после его отработки делать еще один Redim Preserve 2) тот же многострадальный метод Retrieve работает с внешней переменной, получаемой ByRef. В нее он записывает значения, что, насколько я знаю, не очень хорошо. Возможно, есть еще какие-то ошибки, которые я не заметил. Просьба к уважаемым форумчанам покритиковать решение. Здесь привожу код самого класса и процедур, с ним работающих.

Решение задачи: «Сортировка бинарным деревом»

textual
Листинг программы
 '::: Пирамидальная сортировка (Главная процедура)
 
Sub HeapSort(X() As Double)
Dim Heap() As Double
Dim N&
Dim HeapSize&
Dim I&
    N& = UBound(X, 1)
    
    ReDim Heap(1 To N) As Double
    
    '::: Занесение в пирамиду
    
    HeapSize& = 1
    Heap(1) = X(1)
    
    For ii& = 2 To N
        HeapSize& = HeapSize& + 1
        Heap(HeapSize&) = X(ii&)
        ptr& = HeapSize&
        pUp Heap(), ptr&
    Next ii&
    
    '::: Вывод отсортированного
    
    o& = N
    
    Do
       If HeapSize& = 0 Then Exit Do
       X(o&) = Heap(1)
       o& = o& - 1
       Swap Heap(1), Heap(HeapSize&)
       HeapSize& = HeapSize& - 1
       pDown Heap(), 1, HeapSize&
    Loop
 
End Sub
 
':::: Просеивание вверх
 
Sub pUp(Heap() As Double, p As Long)
    If p = 1 Then Exit Sub
    Par& = p \ 2
    If Heap(p) <= Heap(Par&) Then Exit Sub
    Swap Heap(p), Heap(Par&)
    pUp Heap(), Par&
End Sub
 
':::: Просеивание вниз
 
Sub pDown(Heap() As Double, p As Long, HeapSize As Long)
    If (2 * p) >= HeapSize Then Exit Sub
    ZL# = Heap(2 * p)
    ZR# = Heap(2 * p + 1)
    If (Heap(p) >= ZL#) And (Heap(p) >= ZR#) Then Exit Sub
    If (ZL# >= ZR#) Then
       Swap Heap(p), Heap(2 * p)
       pDown Heap(), 2 * p, HeapSize
    Else
       Swap Heap(p), Heap(2 * p + 1)
       pDown Heap(), 2 * p + 1, HeapSize
    End If
End Sub
 
':::: Обменять два элемента
 
Sub Swap(a As Double, B As Double)
    tmp# = a
    a = B
    B = tmp#
End Sub
 
':::: Стартовая процедура
 
Sub Test()
Dim I&, t!
Dim H(1 To 800000) As Double, Q(1 To 800000) As Double
 
For I = 1 To UBound(H)
  H(I) = Rnd
  Q(I) = H(I)
Next I
t = Timer
HeapSort H()
Debug.Print "HeapSort t="; Timer - t
 
t = Timer
QuickSort Q(), LBound(Q), UBound(Q)
Debug.Print "QuickSort t="; Timer - t
 
'и проверить решил на всякий случай
For I = 1 To UBound(H)
 If H(I) <> Q(I) Then Stop
Next I
 
End Sub
 
Sub QuickSort(a() As Double, ByVal L As Long, ByVal U As Long)
Dim I As Long, J As Long, X As Double, Y As Double
I = L: J = U: X = a((L + U) \ 2)
Do
  While a(I) < X: I = I + 1: Wend: While X < a(J): J = J - 1: Wend 'по возрастанию
'  While A(I) > X: I = I + 1: Wend: While X > A(J): J = J - 1: Wend 'по убыванию
  If I <= J Then
    Y = a(I): a(I) = a(J): a(J) = Y:    I = I + 1: J = J - 1
  End If
Loop Until I > J
If L < J Then QuickSort a, L, J
If I < U Then QuickSort a, I, U
End Sub

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4 из 5
Похожие ответы