Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Билеты на зачет.docx
Скачиваний:
51
Добавлен:
01.06.2015
Размер:
554.66 Кб
Скачать

1 2 3 4 5 6 7

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

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

Хоар предложил два способа улучшить выбор опорного элемента y:

  1. выбирать случайным образом элемент массива,

  2. искать медиану трех случайно взятых элементов массива (средний по величине).

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

Запишем теперь общий алгоритм, рекурсивно вызывая процедуру сортировки:

procedureQuickSort(varx : vector);procedureSort( l, r : integer);Vari, j : integer; y, z: integer;begini := l; j := r; y := x[(l + r) div 2];repeatwhilex[i] < ydoi := i + 1;whilex[j] > ydoj := j – 1;ifi <= jthenbeginz := x[i]; x[i] := x[j]; x[j] := z; i := i + 1; j := j – 1end;untili > j;ifl < jthenSort (l, j);ifi < rthenSort(i, r)end;

beginSort(1, n)end; {quicksort}

Исключение рекурсии в этом алгоритме достигается использованием стека, в который запоминается запрос на сортировку одной из частей (для простоты – правой).

procedureQuickSort(varx : Vector);vari, j, l, r : integer; y, z: integer; S : Stack;beginPush(s, 1, n);repeatR := Pop(S); L := Pop(S);repeati := l; j := r; y := x[(l + r) div 2];repeatwhilex[i] < ydoi := i + 1;whilex[j] > ydoj := j – 1;ifi<=jthenbeginz := x[i]; x[i] := x[j]; x[j] := z i := i + 1; j := j – 1end;untili > j;ifi < rthenPush( S, i, r) r := j;untill >= r;untilEmpty(S);end; {quicksort}

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

ifj – l < r – ithenbeginifi < rthenPush(S, i, r) r := j;endelse beginifl < jthenPush(S, l, j); l := i;end;

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

Алгоритм является самым полезным алгоритмом внутренней сортировки, так как требует мало памяти и опережает другие алгоритмы по среднему времени выполнения.

Характеристики алгоритма «быстрой сортировки» зависят от удачного выбора элемента Yдля разбиения. В хорошем случае число сравнений,. Таким образом, быстрая сортировка эффективна лишь в среднем – время работы пропорционально, в худшем случае она может работать очень медленно, пропорционально. Быстрая сортировка не является устойчивой, в отличии, например от простых вставок, слияния списков, простого выбора.

36. Пирамидальная сортировка Пирамидальная сортировка

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

1. Организация турнирной таблицы происходит следующим образом: в первом туре участники разбиты на пары и играют между собой, победители проходят в следующий тур и играют между собой и т.д. В полуфинале участвует 4 участника, в финале 2 и определяется победитель.

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

Рассмотрим организацию турнира на примере «участников» - элементов массива (5, 2, 8. 9, 3, 1, 7. 2).

9

9

7

5

9

3

7

5

2

8

9

3

1

7

2

Победителем является «участник» 9. Выведем его из турнира, заменив на «чрезвычайно слабого игрока» -.

8

8

7

5

8

3

7

5

2

8

3

1

7

2

Победителем является «участник» 8. Выведем его из турнира, заменив на «чрезвычайно слабого игрока» -.

7

5

7

5

3

7

5

2

3

1

7

2

5

5

3

5

3

2

5

2

3

1

2

И т.д. Таким образом, происходит сортировка посредством выбора из дерева – выбирается максимальный элемент, находящийся в корне дерева.

2. Корпоративная система выдвижения заключается в следующем: из группы простых исполнителей на верхний уровень поднимаются лучшие (например, из группы программистов выдвигаются старшие программисты). Среди старших программистов отбирают руководителей лаборатории. Среди руководителей лаборатории отбирают руководителей отделов и т.д. При этом, когда участник поднимается с самого нижнего уровня, его заменяют «человеком с улицы» (-), а если выдвижение идет с очередного уровня, то его заменяют на лучшего из его подчиненных.

9

9 8

7

5

9 8

3

7 2

5

2

8

9

3

1

7

2

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

9

8

7

5

3

2

2

1

Интуитивно второй способ более удобен – он позволяет избежать лишних сравнений -с -, на которые мы будет то и дело натыкаться в турнирной таблице на поздних стадиях.

Пронумеруем теперь элементы пирамиды по уровням сверху-вниз и слева-направо:

X1

X2

X3

X4

X5

X6

X7

X8

X9

X10

X11

X12

X13

X14

X15

Заметим, что отцом k-го узла является узел с номером (kdiv2), а потомками - узлы с номерами 2kи 2k+1. В пирамиде выполнено условие

Xk div 1

Xk

X2k

X2k+1

Очевидным недостатком рассмотренного метода является большое число бесполезных дыр, содержащих -. Было бы очень хорошо организовать пирамиду наNячейках (в нашем случае на 8, а не на 15). Эта цель была реализована Дж. У. Дж. Уильямсом (JohnWilliamJosephWilliams) в 1964 году, разработавшим алгоритм «пирамидальной» сортировки (heap-sort).

Будем называть массив X1,X2,X3 …Xnпирамидой, если выполнено условие:Xj div 2 Xj , при 1jdiv2 <jN.

Тогда X1 X2, X1 X3,X2 X4,X2 X5,и т.д. В частности, наибольший ключ лежит на вершине пирамиды:X1 =max(X1 ,X2,…Xn).

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

procedureDownHeap( k : integer);vari, j, t : integer;beginT := x[k];whilek <= Countdiv2dobeginj := k + k;ifj < Countthenifx[j] < x[j+1]thenj := j + 1;ift >= x[j]thenbreak; x[k] := x[j]; k := j;end; x[k] := t;end;

Нисходящая процедура дляk-го элемента кучи, состоящей изCountэлементов приведена справа:

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

Например, для массива 5, 2, 8, 9, 3, 1, 7, 2 алгоритм будет выглядеть следующим образом:

Изобразим массив в виде кучи:

5

2

8

9

3

1

7

2

Последовательно применим нисходящую процедуру ко всем элементам, имеющим дочерние начиная с конца. Первым будет обработан узел 9 (с индексом 4). При этом никаких изменения в куче не произойдет, так как поддерево 9–2 удовлетворяет условию кучи. Далее обработаем узлы с индексами 3, 2 и 1. Последовательно получаем:

5

9

8

2

3

1

7

2

5

9

8

2

3

1

7

2

9

5

8

2

3

1

7

2

Получим массив [9, 5. 8, 2. 3, 1, 7, 1], который является кучей.

Обменяем местами корень 9 и последний элемент 2, получим массив 2, 5. 8, 2, 3, 1, 7, 9. При этом 9 стоит уже на своем месте.

2

5

8

2

3

1

7

9

Уменьшим размер кучи на 1 и применим нисходящую процедуру к корню 2, получим массив 8, 5, 7, 2, 3, 1, 2, 9.

8

5

7

2

3

1

2

9

Обменяем корень с последним элементом, получим массив 2, 5, 7, 2, 3, 1, 8, 9. И т.д.

2

5

7

2

3

1

8

9

7

5

2

2

3

1

8

9

procedureHeapSort(varx : Vector);vark, t : integer; count : integer;begincount := N;fork := Ndiv2downto1doDownHeap(k);repeatt := x[1]; x[1] := x[count]; x[count] := t; Dec(count); HeapDown(1);untilcount <=1;end;

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

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