- •1. Инструментальные средства разработки программного обеспечения сапр
- •2. Абстрактные типы данных. Примеры и варианты реализации.
- •3. Прямые методы сортировки массивов
- •4. Быстрая сортировка
- •5. Сортировка Шелла
- •6. Пирамидальная сортировка.
- •7. Алгоритмы внешней сортировки (вс)
- •8. Бинарный поиск и поиск по бинарному дереву
- •9. Алгоритмы обхода бинарных деревьев и их применение в трансляции программ и обработке данных
- •10. Машинное представление деревьев.
- •11. Машинное представление графов
- •12. Процедура поиска в глубину и ее применение в задачах обработки данных
- •13. Формальные грамматики и языки. Классификация грамматик.
- •14. Синтаксические диаграммы
- •15. Фазы трансляции программ и варианты организации языковых процессоров
- •16. Лексический анализ программ. Организация работы сканера
- •17. Нисходящий грамматический разбор с возвратом.
- •18 Восходящий грамматический разбор программ.
- •19 Формы внутреннего представления программ в языковых процессорах сапр.
- •2. Польская запись.
- •20 Семантический анализ. Примеры организации семантических программ.
- •21. Машинно-независимая оптимизация программ
- •22 . Генерация кода в языковых процессорах сапр (Генерация кода в компиляторах)
- •23 Машинно-зависимая оптимизация программ
- •24 Организация информационных таблиц транслятора с хеш-адресацией
- •25 Методы разрешения коллизий в информационных таблицах с хэш-адресацией
- •Метод повторного хеширования (рехеширование)
- •Линейное рехеширование
- •Случайное рехеширование
- •Квадратичное рехеширование
- •Рехеширование – сложение
- •Метод цепочек
4. Быстрая сортировка
Быстрая сортировка (или обменная сортировка с разделением)
Этот метод основан на сравнениях ключей и обменах пар элементов, расположенных не в соседних позициях , а удалённых друг от друга в сортируемом массиве.
Быстрая сортировка позволяет сократить количество необходимых операций от величины O(n2) в среднем до величины O(n*log2(n)). Но в худшем случае, если сортируются данные … то быстрая сортировка имеет O(n2).
В основе быстрой сортировки лежит процедура разделения сортируемого массива на две части следующим образом:
A = (a1, a2, …, an) –сортируемый массив
Для его разделения на две части выбирается некоторый элемент x данного массива, называемый разделяющий элемент.
Пусть x = a1.
После выбора x элементы массива переупорядочиваются следующим образом
1. Разделяющий элемент размещается в некоторой позиции j: aj := x.
2. Все элементы первой части массива A1 = (a1, a2, …, aj-1) должны удовлетворять условию
f(ai)≤f(aj), i = 1, 2, .., j-1.
3. Все элементы второй части массива A2 = (aj+1, aj+2, …, an) должны удовлетворять условию
f(aj)≤f(ai), i = j+1, j+2, .., n.
Если такое разделение выполнено, то исходный массив A можно представить следующим образом:
A = (a1, a2, …, aj-1) aj (aj+1, aj+2, …, an).
В этом массиве разделяющий элемент занимает такое место, в котором он должен находиться после полного упорядочивания. Далее чтобы построить алгоритм сортировки в целом нужно рекуррентно повторить процедуру разделения для вновь полученных массивов A1 и A2, а также для всех подмассивов, созданных при последнем разделении.
Рассмотрим процедуру разделения подробно.
Пусть A – исходный неупорядоченный массив. Введём два счётчика: i = 1, j = n для просмотра элементов слева и справа. Примем в качестве разделяющего x = ai.
1. Просматриваются элементы массива справа и их ключи сравниваются с ключами разделяющего элемента.
Если f(aj)≤f(ai), то выбирается следующий элемент, т.е. j = j – 1. иначе производится обмен местами элементов ai и aj; переменная i увеличивается на единицу i = i + 1; x=aj .
2. Выполняется аналогично, но просматриваются элементы массива слева и их ключи сравниваются с ключами разделяющего элемента.
3. Шаги 1 и 2 повторяются до тех пор, пока после некоторого из них не будет получено равенство значений i = j. Это означает что разделение закончено и разделяющий элемент находится в позиции i = j, x = ai = aj.
Покажем на примере по шагам.
Исходный массив: (25, 57, 48, 37, 12, 92, 86, 33).
Шаг |
Элементы |
Действие |
|||||||
0 |
25 |
57 |
48 |
37 |
12 |
92 |
86 |
33 |
i = 1, j = 8, x = a1 |
1 |
25 |
|
|
|
|
|
|
33 |
j = j – 1 = 7 |
2 |
25 |
|
|
|
|
|
86 |
|
j = j – 1 = 6 |
3 |
25 |
|
|
|
|
92 |
|
|
j = j – 1 = 5 |
4 |
25 |
|
|
|
12 |
|
|
|
Обмен |
5 |
12 |
|
|
|
25 |
|
|
|
i = i + 1 = 2, x = a5 |
6 |
|
57 |
|
|
25 |
|
|
|
Обмен |
7 |
|
25 |
|
|
57 |
|
|
|
j = j – 1 = 4 |
8 |
|
25 |
|
37 |
|
|
|
|
j = j – 1 = 3 |
9 |
|
25 |
48 |
|
|
|
|
|
j = j – 1 = 2 |
В итоге после выполнения процедуры разделения получим:
(12), 25, (48, 37, 57, 92, 86, 33).
Следовательно, исходная задача разбита на две задачи. Применяя процедуру разделения далее, получим:
12, 25, (33, 37), 48, (92, 86, 57)
12, 25, 33, 37, 48, (57, 86), 92
12, 25, 33, 37, 48, 57, 86, 92.
Алгоритм быстрой сортировки не является минимальным по памяти, так как для выполнения рекуррентной процедуры при её моделировании с помощью стека, требуются дополнительные затраты памяти в объёме O(log2n).
Рассмотрим реализацию алгоритма быстрой сортировки с помощью рекуррентной процедуры с именем SORT(L,R:integer), которая упорядочивает элементы одного массива с индексами от L до R.
a[1..N]
a[L], a[L+1], …, a[R]
Определим процедуру перестановки двух элементов.
procedure SW(I,j:integer);
var x:integer;
begin
x := a[i];
a[i] := a[j];
a[j] := x
end;
Быстрая сортировка является наиболее эффективным алгоритмом из всех известных методов сортировки, но все усовершенствованные методы имеют один общий недостаток – невысокую скорость работы при малых значениях n.
Рекурсивная реализация быстрой сортировки позволяет устранить этот недостаток путём включения прямого метода сортировки для частей массива с небольшим количеством элементов.
Анализ вычислительной сложности таких алгоритмов показывает, что если подмассив имеет девять или менее элементов, то целесообразно использовать прямой метод (сортировку простыми вставками).
