Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Структуры и алгоритмы обработки данных. Часть 1. Учебное пособие
.pdf
31
Единственной характеристикой сортировки Шелла является приращение -
Начальное состояние массива
8 23 5 65 44 33 1 6
Фаза 1 (сортируются элемен-
ты, расстояние между кото-
рыми четыре)
8 23 5 65 44 33 1 6
8 23 5 65 44 33 1 6
8 23 1 65 44 33 5 6
8 23 1 6 44 33 5 65
Фаза 2 (сортируются элемен-
ты, расстояние между кото-
рыми два)
1 23 8 6 44 33 5 65
1 23 8 6 44 33 5 65
1 23 8 6 5 33 44 65
1 23 5 6 8 33 44 65
1 6 5 23 8 33 44 65
1 6 5 23 8 33 44 65
1 6 5 23 8 33 44 65
расстояние между сортируемыми элементами в зависимости от прохода. В конце приращение всегда равно единице - метод завершается обычной сортиров-
кой вставками, но именно последовательность приращений определяет рост
эффективности. Вначале Шеллом было предложено n/2, затем каждый раз шаг
делится на 2. Но есть и другие подходы к вычислению расстояния.
Пусть число элементов в сортируемом массиве является степенью числа 2.
Для массива с 2
n
элементами алгоритм работает следующим образом. На пер-
вой фазе производится сортировка включением всех пар элементов массива,
расстояние между которыми есть 2
(n-1)
. На второй фазе производится сортиров-
ка включением элементов полученного массива, расстояние между которыми
есть 2
(n-2)
. И так далее, пока не дойдем до фазы с расстоянием между элемента-
ми, равным единице, и не выполним завершающую сортировку с включениями.
Пример сортировки методом Шелла показан в табл. 5.
Таблица 5
Сортировка методом Шелла

32
Окончание табл. 5
Фаза 3 (сортируются элемен-
ты, расстояние между кото-
рыми один)
1 6 5 23 8 33 44 65
1 5 6 23 8 33 44 65
1 5 6 23 8 33 44 65
1 5 6 8 23 33 44 65
1 5 6 8 23 33 44 65
1 5 6 8 23 33 44 65
1 5 6 8 23 33 44 65
2.5. Сортировка разделением (быстрая сортировка)
Метод сортировки разделением предложен Чарльзом Хоаром в 1962 г.
Этот метод является развитием метода простого обмена и настолько эффекти-
вен, что его стали называть "методом быстрой сортировки - Quicksort".
Основная идея алгоритма состоит в том, что случайным образом выбира-
ется некоторый элемент массива x, после чего массив просматривается слева,
пока не встретится элемент a[i] такой, что a[i] > x, а затем массив просматрива-
ется справа, пока не встретится элемент a[j] такой, что a[j] < x. Эти два элемен-
та меняются местами, и процесс просмотра, сравнения и обмена продолжается,
пока не дойдем до элемента x. В результате массив окажется разбитым на две
части - левую, в которой значения ключей будут меньше x, и правую со значе-
ниями ключей, большими x. Далее процесс рекурсивно продолжается для левой
и правой частей массива до тех пор, пока каждая часть не будет содержать в
точности один элемент. Как обычно, рекурсию можно заменить итерациями,
если запоминать соответствующие индексы массива. Пример алгоритма пока-
зан в табл. 6.

33
Алгоритм быстрой сортировки
Начальное состояние массива
8 23 5 65 |44| 33 1 6
Шаг 1 (в качестве x выбира-
ется a[5])
|--------|
8 23 5 6 44 33 1 65
|---|
8 23 5 6 1 33 44 65
Шаг 2 (в подмассиве a[1] ...
a[5] в качестве x выбирается
a[3])
8 23 |5| 6 1 33 44 65
|--------|
1 23 5 6 8 33 44 65
|--|
1 5 23 6 8 33 44 65
Шаг 3 (в подмассиве a[3] ...
a[5] в качестве x выбирается
a[4])
1 5 23 |6| 8 33 44 65
|----|
1 5 8 6 23 33 44 65
Шаг 4 (в подмассиве a[3] ...
a[4] выбирается a[4])
1 5 8 |6| 23 33 44 65
|--|
1 5 6 8 23 33 44 65
Таблица 6
Для алгоритма оценкой числа сравнений и обменов является O(n*log n).
2.6. Сортировка двоичными включениями
Алгоритм сортировки с помощью двоичного включения является улуч-
шением алгоритма сортировки включением. Элементы массива делятся на отсортированную последовательность a[1]..a[i-1] и неотсортированную a[i]...a[n].
Так как первая последовательность является на данный момент уже упорядо-

34
ченной, то поиск нужной позиции для вставки нового элемента производится с
Начальное состояние массива
8 23 5 65 44 33 1 6
Шаг 1 (вычисленная точка
включения a[2])
8 23 5 65 44 33 1 6
Шаг 2 (вычисленная точка
включения a[1])
8 5 23 65 44 33 1 6
5 8 23 65 44 33 1 6
Шаг 3 (вычисленная точка
включения a[4])
5 8 23 65 44 33 1 6
Шаг 4 (вычисленная точка
включения a[4])
5 8 23 44 65 33 1 6
Шаг 5 (вычисленная точка
включения a[4])
5 8 23 44 33 65 1 6
5 8 23 33 44 65 1 6
Шаг 6 (вычисленная точка
включения a[1])
5 8 23 33 44 1 65 6
5 8 23 33 1 44 65 6
5 8 23 1 33 44 65 6
5 8 1 23 33 44 65 6
5 1 8 23 33 44 65 6
1 5 8 23 33 44 65 6
помощью двоичного поиска, при котором делается попытка сравнения с сере-
диной отсортированной последовательности, после этого процесс деления пополам идет до тех пор, пока не будет найдена точка включения. Алгоритм про-
иллюстрирован в табл. 7, серым помечена еще неотсортированная часть масси-
ва по итогам шага.
Таблица 7
Алгоритм сортировки двоичными включениями

35
Окончание табл. 7
Шаг 7 (вычисленная точка
включения a[3])
1 5 8 23 33 44 6 65
1 5 8 23 33 6 44 65
1 5 8 23 6 33 44 65
1 5 8 6 23 33 44 65
1 5 6 8 23 33 44 65
2.7. Сортировка со слиянием
Сортировки со слиянием, как правило, применяются в тех случаях, когда
требуется отсортировать последовательный файл, не помещающийся целиком в
основной памяти. Существуют эффективные методы внутренней сортировки,
основанные на разбиениях и слияниях.
Один из популярных алгоритмов внутренней сортировки со слияниями
основан на следующих идеях (в примере число элементов в массиве является
степенью числа 2).
Пусть имеются два отсортированных в порядке возрастания массива p[1],
p[2], ..., p[n] и q[1], q[2], ..., q[n] и имеется пустой массив r[1], r[2], ..., r[2n], ко-
торый можно заполнить значениями массивов p и q в порядке возрастания. Для
слияния выполняются следующие действия: сравниваются p[1] и q[1], и мень-
шее из значений записывается в r[1]. Пусть это значение p[1]. Тогда p[2] срав-
нивается с q[1] и меньшее из значений заносится в r[2]. Предположим, что это
значение q[1]. Тогда на следующем шаге сравниваются значения p[2] и q[2] и
т.д., пока не будет достигнута граница одного из массивов. Тогда остаток дру-
гого массива просто дописывается в "хвост" массива r. Пример слияния двух
массивов показан на рис. 2.

36
Рис. 2. Сортировка со слиянием

37
Для сортировки со слиянием массива a[1], a[2], ..., a[n] заводится парный
Начальное состояние массива
8 23 5 65 44 33 1 6
Шаг 1
6 8 1 23 5 33 44 65
Шаг 2
5 8 44 65 1 5 23 33
Шаг 3
1 5 6 8 23 33 44 65
массив b[1], b[2], ..., b[n]. На первом шаге производится слияние a[1] и a[n] с
размещением результата в b[1], b[2], слияние a[2] и a[n-1] с размещением ре-
зультата в b[3], b[4], ..., слияние a[n/2] и a[n/2+1] с помещением результата в
b[n-1], b[n]. На втором шаге производится слияние пар b[1], b[2] и b[n-1], b[n] с
помещением результата в a[1], a[2], a[3], a[4], слияние пар b[3], b[4] и b[n-3],
b[n-2] с помещением результата в a[5], a[6], a[7], a[8], ..., слияние пар b[n/2-1],
b[n/2] и b[n/2+1], b[n/2+2] с помещением результата в a[n-3], a[n-2], a[n-1], a[n].
И т.д. На последнем шаге, например (в зависимости от значения n), произво-
дится слияние последовательностей элементов массива длиной n/2 a[1], a[2], ...,
a[n/2] и a[n/2+1], a[n/2+2], ..., a[n] с помещением результата в b[1], b[2], ..., b[n].
Пример применения алгоритма показан в табл. 8.
Таблица 8
Алгоритм сортировки со слиянием
При применении сортировки со слиянием число сравнений ключей и чис-
ло пересылок оценивается как O(n*log n). При этом для выполнения алгоритма
для сортировки массива размера n требуется 2
n
элементов памяти.

38
3. Алгоритмы внешней сортировки
Внешней сортировкой принято называть сортировку последовательных
файлов, располагающихся во внешней памяти и слишком больших, чтобы
можно было целиком переместить их в основную память и применить один из
рассмотренных в предыдущем разделе методов внутренней сортировки. Наибо-
лее часто внешняя сортировка применяется в системах управления базами дан-
ных при выполнении запросов, и от эффективности применяемых методов су-
щественно зависит производительность СУБД.
Обычно в этом случае речь идет о последовательных файлах, т.е. файлах,
которые можно читать запись за записью в последовательном режиме, а писать
можно только после последней записи. Методы внешней сортировки появи-
лись, когда наиболее распространенными устройствами внешней памяти были
магнитные ленты. Для лент чисто последовательный доступ был абсолютно
естественным. Когда произошел переход к запоминающим устройствам с маг-
нитными дисками, обеспечивающими "прямой" доступ к любому блоку инфор-
мации, казалось, что чисто последовательные файлы потеряли свою актуаль-
ность. Однако это ощущение было ошибочным.
Все дело в том, что большинство используемых в настоящее время дис-
ковых устройств снабжены подвижными магнитными головками. При выпол-
нении обмена с дисковым накопителем выполняется подвод головок к нужному
цилиндру, выбор нужной головки (дорожки), прокрутка дискового пакета до
начала требуемого блока и, наконец, чтение или запись блока. Среди всех этих
действий самое большое время занимает подвод головок. Именно это время
определяет общее время выполнения операции. Единственным доступным при-
емом оптимизации доступа к магнитным дискам является как можно более
"близкое" расположение на накопителе последовательно адресуемых блоков
файла. Но и в этом случае движение головок будет минимизировано только в
том случае, когда файл читается или пишется в чисто последовательном режи-

39
ме. Именно с такими файлами при потребности сортировки работают совре-
менные СУБД.
Несмотря на появление электронных высокоскоростных устройств внеш-
ней памяти методы внешней сортировки не утратили своей актуальности. Во-
первых массивы данных, требующих сортировки могут иметь значительный
объем и все также не помещаться целиком во внутренней памяти ЭВМ, во-
вторых объем памяти электронных накопителей пока несравним с объемом
традиционных дисковых устройств внешней памяти, на которых хранятся су-
ществующие базы данных.
3.1. Прямое слияние
Пусть имеется последовательный файл A, состоящий из записей a1, a2, ..., an
(пусть n представляет собой степень числа 2). Каждая запись состоит из одного
элемента, представляющего собой ключ сортировки. Для сортировки использу-
ются два вспомогательных файла B и C (размер каждого из них будет n/2).
Сортировка состоит из последовательности шагов, в каждом из которых
выполняется распределение состояния файла A в файлы B и C, а затем слияние
файлов B и C в файл A (слияние показано на рис. 2.). На первом шаге для рас-
пределения последовательно читается файл A, и записи a
файл B, а записи a
слияние производится над парами (a
, a4, ..., an - в файл C (начальное распределение). Начальное
2
, a2), (a3, a4), ..., (a
1
, a3, ..., a
1
, a
(n-1)
пишутся в
(n-1)
), и результат запи-
n
сывается в файл A. На втором шаге снова последовательно читается файл A, и в
файл B записываются последовательные пары с нечетными номерами, а в файл C
- с четными. При слиянии образуются и пишутся в файл A упорядоченные чет-
верки записей. И так далее. Перед выполнением последнего шага файл A будет
содержать две упорядоченные подпоследовательности размером n/2 каждая. При
распределении первая из них попадет в файл B, а вторая - в файл C. После слия-

40
ния файл A будет содержать полностью упорядоченную последовательность за-
Начальное состояние файла А
8 23 5 65 44 33 1 6
Первый шаг
Распределение
Файл B
Файл C
Слияние: файл A
8 5 44 1
23 65 33 6
8 23 5 65 33 44 1 6
Второй шаг
Распределение
Файл B
Файл C
Слияние: файл A
8 23 33 44
5 65 1 6
5 8 23 65 1 6 33 44
Третий шаг
Распределение
Файл B
Файл C
Слияние: файл A
5 8 23 65
1 6 33 44
1 5 6 8 23 33 44 65
писей. В табл. 9 показан пример внешней сортировки простым слиянием.
Для выполнения внешней сортировки методом прямого слияния в основ-
ной памяти требуется расположить всего лишь две переменные - для размеще-
ния очередных записей из файлов B и C. Файлы A, B и C будут O(log n) раз
прочитаны и столько же раз записаны.
Таблица 9
Алгоритм внешней сортировки прямым слиянием
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
