Материал: Глава 14. Алгоритмы сортировки

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

оценки среднего числа сравнений, то она чуть лучше, чем у других методов.

Многочисленные эксперименты показывают, что метод вставок дает

наименьшее время сортировки среди всех простейших методов.

Метод выбора, как это и следовало ожидать, имеет лучшие показатели по числу пересылок, особенно – для общего случая, где оценка О(n*log2n)

заметно лучше оценки O(n2). Поэтому его можно рекомендовать к использованию из всех простейших методов в том случае, если именно число перестановок является наиболее важным.

§14.5 Улучшенные методы сортировки: метод Шелла

Метод Шелла является улучшенным вариантом метода вставок.

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

Алгоритм метода Шелла состоит в многократном повторении двух основных действий:

объединение нескольких элементов исходного массива по некоторому правилу

сортировка этих элементов обычным методом вставок

Более подробно, на первом этапе группируются элементы входного набора с достаточно большим шагом. Например, выбираются все 1000-е

элементы, т.е. создаются группы:

группа 1: 1, 1001, 2001, 3001 и т.д.

группа 2: 2, 1002, 2002, 3002 и т.д.

группа 3: 3, 1003, 2003, 3003 и т.д.

. . . . . . . . . . . . . . . . . . . . .

группа 1000: 1000, 2000, 3000 и т.д.

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

11

На втором этапе выполняется группировка уже с меньшим шагом,

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

На третьем этапе элементы группируются с еще меньшим шагом,

например – все десятые элементы. Выполняется сортировка, группировка с еще меньшим шагом и т.д.

На последнем этапе сначала выполняется группировка с шагом 1,

создающая единственный набор данных размерности n, а затем - сортировка

практически отсортированного набора.

Пример. Исходный набор: 15 – 33 – 42 – 07 – 12 - 19

Выполняем группировку с шагом 3, создаем три группы по 2 элемента и сортируем каждую из них отдельно:

группа 1: 15 – 07 => 07 – 15 (1 сравнение, 1 пересылка)

группа 2: 33 – 12 => 12 – 33 (1 сравнение, 1 пересылка)

группа 3: 42 – 19 => 19 – 42 (1 сравнение, 1 пересылка)

Новый набор чисел: 07 – 15 – 12 – 33 – 19 – 42

Группировка с меньшим шагом 2 дает 2 группы по 3 элемента, которые сортируются отдельно:

группа 1: 07 – 12 – 19 => уже упорядочена (2 сравнения, 0 пересылок)

группа 2: 15 – 33 – 42 => уже упорядочена (2 сравнения, 0 пересылок)

Новый набор чисел: 07 – 12 – 19 – 15 – 33 – 42

Последняя группировка с шагом 1 дает сам набор чисел; к нему применяется сортировка вставками с 5-ю сравнениями и только одной пересылкой, после чего получаем искомый результат.

Итого – 12 сравнений и 4 пересылки, что в общем-то не лучше, чем у простых методов. Однако, здесь надо учесть два фактора.

Фактор 1 (общий). Улучшенные методы показывают свою эффективность именно для больших наборов данных (сотни, тысячи и т.д. элементов). Для

12

очень малых наборов (как в примере) они могут давать даже худшие результаты.

Фактор 2 (специфический). Эффективность метода Шелла существенно зависит от выбора последовательности шагов группировки. Эта последовательность обязательно должна быть убывающей, а последний шаг обязательно равен 1. В настоящее время неизвестна наилучшая

последовательность шагов, обеспечивающая наименьшую трудоемкость. На основе многочисленных экспериментов установлено, что число шагов группировки надо выбирать по формуле [(log 2 n)] – 1, где скобки [ ]

используются для обозначения целой части числа, а в качестве самих последовательностей рекомендуется один из следующих наборов (обращаю внимание: для удобства восприятия шаги даются в обратном порядке):

1, 3, 5, 9, 17, 33, . . . (общая формула: tk = (2* tk-1) –1)

1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 . . . (общая формула: tk = (2* tk-1) +1, а еще проще – (2k – 1)).

В соответствии с этими рекомендациями, в предыдущем примере надо взять лишь 2 шага группировки со значениями 3 и 1. В этом случае потребуется лишь 8 сравнений и 5 пересылок.

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

Оценка трудоемкости метода Шелла выражается соотношением O(n1,2),

что лучше, чем у простейших методов, особенно при больших .

13

 

Пример программной реализации сортировки методом Шелла

представлен в листинге 14.4.

 

 

Листинг 14.4 – Сортировка методом Шелла

 

 

 

 

 

1

void ShellSort(int n, int mass[])

 

 

2

{

 

 

3

int i, j, step;

 

 

4

int tmp;

 

 

5

for (step = n / 2; step > 0; step /= 2)

 

 

6

for (i = step; i < n; i++)

 

 

7

{

 

 

8

tmp = mass[i];

 

 

9

for (j = i; j >= step; j -= step)

 

 

10

{

 

 

11

if (tmp < mass[j - step])

 

 

12

mass[j] = mass[j - step];

 

 

13

else

 

 

14

break;

 

 

15

}

 

 

16

mass[j] = tmp;

 

 

17

}

 

 

18

}

 

 

 

В листинге 14.4 n – количество элементов в массиве, а mass[] –

упорядочиваемый массив элементов.

§14.6 Улучшенные методы сортировки: метод быстрой сортировки

Данный метод в настоящее время считается наиболее быстрым универсальным методом сортировки. Как ни странно, он является обобщением самого плохого из простейших методов – обменного метода. Эффективность метода достигается тем, что перестановка применяется не для соседних элементов, а отстоящих друг от друга на приличном расстоянии.

Более конкретно, алгоритм быстрой сортировки заключается в следующем.

пусть каким-то образом в исходном наборе выделен некий элемент

x, который принято называть опорным. В простейшем случае в качестве

опорного можно взять серединный элемент массива

14

просматривается часть массива, расположенная левее опорного элемента и находится первый по порядку элемент ai > x

после этого просматривается часть массива, расположенная

правее опорного элемента, причем - в обратном порядке, и находится первый по порядку (с конца) элемент aj < x

производится перестановка элементов ai и aj

после этого в левой части, начиная с ai отыскивается еще один элемент, больший x, а в правой части, начиная с aj отыскивается элемент,

меньший х

эти два элемента меняются местами

эти действия (поиск слева и справа с последующим обменом)

продолжаются до тех пор, пока не будет достигнут опорный элемент x

после этого слева от опорного элемента x будут находиться элементы, меньшие опорного, а справа – элементы, большие опорного. При этом обе половины скорее всего не будут отсортированными

после этого массив разбивается на правую и левую части, и

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

Пример. Пусть исходный набор включает 11 чисел:

13-42-28-17-09-25-47-31-39-15-20.

Основные шаги сортировки:

1.Выбор серединного элемента 25 (индекс 6): 13 42 28 17 09 25 47 31

39 15 20

2.поиск слева первого элемента, большего 25: 42 (2 сравнения)

3.поиск справа от конца первого элемента, меньшего 25: 20 (1

сравнение)

4. перестановка элементов 42 и 20: 13 20 28 17 09 25 47 31 39

15 42

15

Источник: https://studfile.net/preview/16573799/