Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры данных и алгоритмы. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
1 Мб
Скачать

ГЛАВА 5 АЛГОРИТМЫ УПОРЯДОЧЕНИЯ ДАННЫХ

Понятие операции упорядочения

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

Алгоритмы внутренней сортировки упорядочивают данные, хранимые в оперативной памяти, алгоритмы внешней сортировки обрабатывают данные, хранимые во внешней памяти. В данной теме будем рассматривать алгоритмы внутренней сортировки данных, хранимых в статических таблицах.

Если таблица представлена множеством элементов a1, a2, ... , an, тогда сортировка есть перестановка элементов ak1, ak2, ... , akn, в которой над элементами установлено отношение порядка:

f(ak1) f(ak2) ... f(akn) или f(ak1) f(ak2) ... f(akn)

или какое-то другое отношение порядка (здесь f – упорядочивающая функция).

В простом случае f задается явно как компонент элемента таблицы, обычно этот компонент – ключ элемента. В таком случае говорят об упорядочении по ключам.

Множество называется отсортированным, если оно не содержит ни одной инверсии. Инверсия (при отношении порядка по возрастанию значений ключа) – это пара индексов i и j такая, что i < j, а ключ (i-й элемент) > ключ (j-й элемент).

Сравнительная оценка сложности алгоритмов внутренней сортировки осуществляется по следующим параметрам:

число просмотров множества элементов;

число сравнений ключей элементов;

число перемещений элементов.

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

106

этому алгоритмы сортировки производят перегруппировку элементов в исходном множестве. Алгоритм сортировки n данных, оперирующий сравнениями, имеет минимальную сложность n или выше (т. к. должно быть выполнено минимально n - 1 сравнений), максимальная сложность алгоритма, оперирующего сравнениями, не меньше n log n.

Алгоритмы упорядочения

В данных алгоритмах таблица T определена следующим образом:

struct table

{

type elem[N]; int n;

} table T;

Здесь поле n определяет фактическое число элементов в таблице, а N – максимальное число элементов в таблице. Рассматривая алгоритмы сортировки, считаем, что упорядочение осуществляется по возрастанию значений ключа элементов таблицы.

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

Разбиваем множество на две равные половинки. Упорядочиваем каждую половину отдельно аналогичным образом, т. е. делим пополам. Деление продолжается до тех пор, пока множество в результате деления не достигнет размера равного единицы – множество размером 1 считается упорядоченным. После упорядочения две части сливаются в одну упорядоченную часть, так продолжается пока не будут слиты все части. Проиллюстрируем алгоритм на примере, в котором ключи задаются целыми числами, будем в примере задавать только значения ключей.

107

 

Исходные данные:

 

 

 

 

 

 

 

 

 

44

55

12

42

94

18

06

67

1

шаг

1)

44

55

12

42

 

 

 

 

2

шаг

1)

44

55

 

 

 

 

 

 

3

шаг

1)

44 2) 55

 

 

 

 

 

 

4

шаг

1)

44

55

 

 

 

 

 

 

5

шаг

 

 

 

1) 12

2) 42

 

 

 

 

6

шаг

 

 

 

2) 12

42

 

 

 

 

7

шаг

1)

12

42

44

55

 

 

 

 

8

шаг

 

 

 

 

 

1) 94

18 2) 06

67

9

шаг

 

 

 

 

 

1) 94

2) 18

 

 

10

шаг

 

 

 

 

 

1) 18

94

 

 

11

шаг

 

 

 

 

 

 

 

1) 06 2) 67

12

шаг

 

 

 

 

 

 

 

2) 06

67

13

шаг

 

 

 

 

 

2) 06

18

67

94

14

шаг

 

06

12

18

42

44

55

67

94

Рекурсивное описание алгоритма сортировки слиянием:

void mergesort(T, l, r)

{

if (l < r)

c = (l + r) / 2; mergesort(T, l, c); mergesort(T, c + 1, r); merge(T, l, c, r);

}

Здесь l и r соответственно левая и правая границы упорядочиваемой части множества. При первом вызове l – равно индексу первого элемента, т. е. 0, r равно индексу последнего элемента, т. е. T.n - 1, merge – функция слияния двух упорядоченных частей: 1-я часть задается границами l и c, 2-я часть границами c и r.

108

Основные алгоритмы сортировки посредством сравнений

1) Сортировка включением (вставками - by insertion)

Исходное множество элементов делят на две части: уже упорядоченную и неупорядоченную. Вначале упорядоченная часть состоит, как правило, из одного элемента – первого элемента, а все остальные элементы находятся в неупорядоченной части. Из неупорядоченной части берут очередной элемент и включают его в упорядоченную часть, помещая (вставляя) на нужное место (т. е. так, чтобы выполнялось отношение порядка). Так продолжают до тех пор, пока последний элемент из неупорядоченной части не будет включен в упорядоченную часть. Простой вариант сортировки включением – это метод прямого включения, улучшенный – сортировка методом Шелла.

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

for (i = 1; i < T.n; i++)

{

x = T.elemi;

c = ключ(T.elemi);

for (j = i - 1; j >= 0 && ключ(T.elemj) > c; j--) T.elemj + 1 = T.elemj;

T.elemj + 1 = x;

}

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

Число просмотров (упорядоченной части) равно n - 1.

Наилучший вариант для алгоритма прямого включения – уже упорядоченное множество, здесь:

число сравнений n - 1;

число перемещений (в дополнительную память и из нее) 2(n - 1). Наихудший вариант для алгоритма прямого включения – множе-

ство, упорядоченное в противоположном порядке, здесь:

109

число сравнений 1 + 2 + 3 + … + (n - 1) и таких слагаемых n - 1. По формуле арифметической прогрессии получаем n (n - 1) / 2;

число перемещений элементов в упорядоченной части 1 + 2 + 3

+ (n - 1);

число перемещений элементов в дополнительную память 2(n - 1)

всего перемещений 2(n - 1) + n(n - 1) / 2 = (n2 +3n - 4) / 2.

Таким образом, оценка сложности алгоритма прямого включения

O(n2).

2) Сортировка выбором (by selection)

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

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

for (i = 0; i < T.n - 1; i++)

{

min = T.elemi; k = i;

for (j = i + 1; j < T.n; j++)

if (ключ(T.elemj) < ключ(min))

{

min = T.elemj; k = j;

}

T.elemk = T.elemi;

110

T.elemi = min;

}

Число просмотров таблицы (неупорядоченной части) равно n – 1. Число сравнений (при поиске нужного элемента) является посто-

янной величиной – (n - 1) + (n - 2) + … + 3 + 2 + 1 = n (n - 1) / 2. Число перемещений (для обмена найденного элемента с минимальным значением и элемента стоящего на очередном месте в упорядоченной части)

– 3(n - 1).

Число перемещений элемента в дополнительную память при поиске нужного элемента равно 0, если исходное множество уже упорядочено или равно n2 / 4, если исходное множество упорядочено в противоположном порядке.

Общее число перемещений в наихудшем случае – 3 (n - 1) + n2 /4. Таким образом, оценка сложности алгоритма прямого выбора

O(n2).

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

3) Сортировка обменом (by exchange):

Висходном множестве элементов рассматриваются пары элементов. Если пара содержит инверсию, то она устраняется выполнением обмена этих элементов. Таким образом, после каждого просмотра хотя бы один элемент окажется на своем месте. Просмотры продолжаются до тех пор, пока в множестве не останется ни одной инверсии. Простой вариант сортировки обменом – метод прямого обмена («пузырьковая» сортировка), улучшенный вариант – быстрая сортировка.

Валгоритме прямого обмена сравниваются пары соседних элемен-

тов.

Вариант 1:

for (i = 0; i < T.n - 1; i++)

for (j =0; j < T.n - 1 - i; j++)

if (ключ(T.elemj) > ключ(T.elemj + 1))

{

x = T.elemj;

111

T.elemj = T.elemj + 1; T.elemj + 1 = x;

}

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

Число просмотров таблицы (неупорядоченной части) равно n - 1. Число сравнений (при сравнении пар соседних элементов) является

постоянной величиной – ( n - 1) + (n - 2) + … + 3 + 2 + 1 = n(n - 1) / 2.

Наилучший вариант для алгоритма прямого обмена по числу перемещений – уже упорядоченное множество, здесь:

– число перемещений (при обмене элементов в паре) равно 0. Наихудший вариант для алгоритма прямого обмена – множество,

упорядоченное в противоположном порядке, здесь:

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

3n(n - 1)/2.

Таким образом, оценка сложности алгоритма прямого обмена

O(n2).

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

Вариант 2:

инверсия = 1; j = 0; while (инверсия)

{

инверсия = 0;

for (i = 0; i < T.n - 1 - j; i++)

if (ключ(T.elemi) > ключ(T.elemi + 1)

{

r = Ti;

Ti = Ti + 1; Ti + 1 = r;

инверсия = 1;

112

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]