Скачиваний:
79
Добавлен:
02.05.2014
Размер:
248.32 Кб
Скачать

Блочная сортировка на основе массива

Блочную сортировку также можно реализовать в массиве, используя идеи подобные тем, которые используются при сортировке подсчетом. При каждом вызове алгоритма, вначале подсчитывается число элементов, которые относятся к каждому блоку. Потом на основе этих данных рассчитываются смещения во временном массиве, которые затем используются для правильного расположения элементов в массиве. В конце концов, блоки рекурсивно сортируются, и отсортированные данные перемещаются обратно в исходный массив.

Public Sub ArrayBucketSort(List() As Long, Scratch() As Long, _

min As Long, max As Long, NumBuckets As Long)

Dim counts() As Long

Dim offsets() As Long

Dim i As Long

Dim Value As Long

Dim min_value As Long

Dim max_value As Long

Dim value_scale As Double

Dim bucket_num As Long

Dim next_spot As Long

Dim num_in_bucket As Long

' Если в списке не более чем CutOff элементов,

' закончить сортировку процедурой SelectionSort.

If max - min + 1 < CutOff Then

Selectionsort List(), min, max

Exit Sub

End If

' Найти значения min и max.

min_value = List(min)

max_value = min_value

For i = min + 1 To max

Value = List(i)

If min_value > Value Then min_value = Value

If max_value < Value Then max_value = Value

Next i

' Если min_value = max_value, значит, есть единственное

' значение, и список отсортирован.

If min_value = max_value Then Exit Sub

' Создать пустой массив с отсчетами блоков.

ReDim counts(l To NumBuckets)

value_scale = _

CDbl (NumBuckets - 1) / _

CDbl (max_value - min_value)

' Создать отсчеты блоков.

For i = min To max

If List(i) = max_value Then

bucket_num = NumBuckets

Else

bucket_num = _

Int((List(i) - min_value) * _

value_scale) + 1

End If

counts(bucket_num) = counts(bucket_num) + 1

Next i

' Преобразовать отсчеты в смещение в массиве.

ReDim offsets(l To NumBuckets)

next_spot = min

For i = 1 To NumBuckets

offsets(i) = next_spot

next_spot = next_spot + counts(i)

Next i

' Разместить значения в соответствующих блоках.

For i = min To max

If List(i) = max_value Then

bucket_num = NumBuckets

Else

bucket_num = _

Int((List(i) - min_value) * _

value_scale) + 1

End If

Scratch (offsets (bucket_num)) = List(i)

offsets(bucket_num) = offsets(bucket_num) + 1

Next i

' Рекурсивная сортировка блоков, содержащих

' более одного элемента.

next_spot = min

For i = 1 To NumBuckets

If counts(i) > 1 Then ArrayBucketSort _

Scratch(), List(), next_spot, _

next_spot + counts(i) - 1, counts(i)

next_spot = next_spot + counts(i)

Next i

' Скопировать временный массив назад в исходный список.

For i = min To max

List(i) = Scratch(i)

Next i

End Sub

Из‑за накладных расходов, которые требуются для работы со связными списками, эта версия блочной сортировки работает намного быстрее, чем версия с использованием связных списков. Тем не менее, используя методы работы с псевдоуказателями, описанные во 2 главе, можно улучшить производительность версии с использованием связных списков, так что обе версии станут практически эквивалентными по скорости.

Новую версию также можно сделать еще быстрее, используя функцию API MemCopy для копирования элементов из временного массива обратно в исходный список. Эта усовершенствованную версию алгоритма демонстрирует программа FastSort.

Резюме

В таб. 9.4 приведены преимущества и недостатки алгоритмов сортировки, описанных в этой главе, из которых можно вывести несколько правил, которые могут помочь вам выбрать алгоритм сортировки.

Эти правила, изложенные в следующем списке, и информация в табл. 9.4 может помочь вам подобрать алгоритм, который обеспечит максимальную производительность:

  • если вам нужно быстро реализовать алгоритм сортировки, используйте быструю сортировку, а затем при необходимости поменяйте алгоритм;

  • если более 99 процентов списка уже отсортировано, используйте пузырьковую сортировку;

  • если список очень мал (100 или менее элементов), используйте сортировку выбором;

  • если значения находятся в связном списке, используйте блочную сортировку на основе связного списка;

  • если элементы в списке — целые числа, разброс значений которых невелик (до нескольких тысяч), используйте сортировку подсчетом;

  • если значения лежат в широком диапазоне и не являются целыми числами, используйте блочную сортировку на основе массива;

  • если вы не можете тратить дополнительную память, которая требуется для блочной сортировки, используйте быструю сортировка

Если вы знаете структуру данных и различные алгоритмы сортировки, вы можете выбрать алгоритм, наиболее подходящий для ваших нужд.

29