Задание 4. Быстрая сортировка и схемы разбиения
Рассматривается задача сортировки заказов интернет-магазина по стоимости. Для каждого заказа задана сумма, и необходимо отсортировать эти значения по возрастанию. Требуется реализовать быструю сортировку в двух вариантах разбиения: с использованием схемы Хоара и с использованием схемы Ломуто.
Для исследования используйте два массива:
orders_random = [57, 14, 83, 29, 61, 45, 72, 10, 34, 98, 21, 66, 39, 50, 7, 66, 28, 64, 72, 62, 66, 26, 8, 29, 89, 35, 15, 32, 27, 55, 3, 59, 100, 21, 56, 85, 36, 23, 75, 18, 49, 18, 78, 44, 59, 59, 96, 68, 23, 81, 89, 4, 25, 90, 92, 72, 8, 82, 89, 44, 82, 55, 49, 23, 49, 80, 22, 84, 67, 21, 88, 65, 73, 99, 88, 49, 92, 39, 83, 66, 83, 26, 53, 75, 56, 94, 59, 89, 71, 37, 64, 99, 96, 73, 83, 30, 79, 78, 29, 7]
orders_many_duplicates = [5, 3, 5, 2, 5, 1, 5, 4, 5, 0, 5, 3, 5, 2, 5, 1, 9, 7, 0, 10, 4, 8, 2, 6, 3, 10, 5, 1, 9, 0, 4, 7, 2, 8, 3, 6, 10, 5, 1, 9, 4, 0, 7, 2, 8, 6, 3, 10, 5, 1, 9, 0, 4, 7, 8, 2, 6, 3, 10, 5, 1, 9, 0, 4, 7, 2, 8, 6, 3, 10, 5, 1, 9, 0, 4, 7, 2, 8, 6, 3, 10, 5, 1, 9, 0, 4, 7, 2, 8, 6, 3, 10, 5, 1, 9, 0, 4, 7, 2, 8]
Необходимо реализовать обе схемы разбиения и дополнительно исследовать влияние способа выбора опорного элемента на поведение алгоритма. Для каждой схемы разбиения требуется рассмотреть не менее трёх способов выбора опорного элемента: выбор первого элемента подпоследовательности, выбор среднего элемента подпоследовательности и выбор случайного элемента подпоследовательности.
Для каждого массива и для каждого сочетания схемы разбиения и способа выбора опорного элемента программа должна вывести исходную последовательность, отсортированную последовательность, число сравнений, число обменов, число вызовов процедуры разбиения и максимальную глубину рекурсии.
Дополнительно необходимо показать, как выполняется разбиение для первых трёх шагов рекурсии. Для каждого из этих первых разбиений следует указывать границы текущей подпоследовательности, выбранное значение опорного элемента, результат разбиения и возвращаемое значение процедуры разбиения.
При выполнении задания необходимо учитывать, что схема Хоара и схема Ломуто работают по-разному. Схема Ломуто возвращает индекс, на котором оказывается опорный элемент после завершения разбиения. Схема Хоара в классическом виде не возвращает окончательную позицию опорного элемента, а возвращает границу, разделяющую левую и правую части подпоследовательности. В связи с этим ниже вам предоставлен псевдокод этих двух схем.
Функция Разбиение_Хоара(A, левая_граница, правая_граница): опорный = A[левая_граница] i = левая_граница - 1 j = правая_граница + 1
пока истина: повторять: i = i + 1 пока A[i] < опорный
повторять: j = j - 1 пока A[j] > опорный
если i >= j: вернуть j
обменять A[i] и A[j]
|
Функция разбиение Хоара
Функция Разбиение_Ломуто(A, левая_граница, правая_граница): опорный = A[правая_граница] i = левая_граница - 1
для j от левая_граница до правая_граница - 1: если A[j] <= опорный: i = i + 1 обменять A[i] и A[j]
обменять A[i + 1] и A[правая_граница] вернуть i + 1
|
Функция разбиение Ломуто
Важное замечание по схеме Хоара:
Функция разбиения возвращает индекс j, который разделяет массив на две части:
1) элементы с индексами левая_граница .. j не больше опорного;
2) элементы с индексами j+1 .. правая_граница не меньше опорного.
Сам опорный элемент после разбиения не обязательно находится на позиции j.
Рекурсивные вызовы должны быть:
qsort(A, left, j)
qsort(A, j+1, right)
Не j-1 и j+1, как в схеме Ломуто.
Задание 5. Исследование устойчивости алгоритмов сортировки
При сортировке записей важен не только итоговый порядок по ключу, но и сохранение относительного порядка элементов с одинаковыми ключами. Необходимо исследовать устойчивость алгоритмов сортировки на наборе записей вида (идентификатор, ключ).
Используйте следующий набор данных:
records1 = ("A1", 4), ("A2", 2), ("A3", 4), ("A4", 1), ("A5", 3), ("A6", 2), ("A7", 4), ("A8", 1), ("A9", 3), ("A10", 2)]
records2 = [("B1", 5), ("B2", 5), ("B3", 5), ("B4", 2), ("B5", 2), ("B6", 3), ("B7", 3), ("B8", 3), ("B9", 1), ("B10", 1)]
records3 = [("C1", 3), ("C2", 1), ("C3", 3), ("C4", 2), ("C5", 3), ("C6", 1), ("C7", 2), ("C8", 3), ("C9", 1), ("C10", 2), ("C11", 3), ("C12", 1)]
Требуется исследовать не менее четырёх алгоритмов сортировки, причём в исследование обязательно должны входить:
не менее двух алгоритмов, являющихся устойчивыми;
не менее двух алгоритмов, являющихся неустойчивыми.
Рекомендуется использовать следующий набор алгоритмов:
сортировка пузырьком;
сортировка вставками;
сортировка выбором;
быстрая сортировка.
Допускается дополнительно включить сортировку слиянием, сортировку перемешиванием или другой алгоритм, реализованный в рамках лабораторной работы.
Для каждого набора данных требуется отсортировать записи по второму полю, то есть по ключу сортировки, и проверить, сохраняется ли относительный порядок элементов с одинаковыми ключами. Программа должна выводить:
исходную последовательность записей;
результат сортировки каждым алгоритмом;
информацию о том, сохранился ли относительный порядок элементов с одинаковыми ключами;
вывод о том, является ли алгоритм устойчивым на основе проведённого эксперимента.
Так же необходимо выполнить небольшое исследование многокритериальной сортировки. Для этого требуется:
сначала отсортировать записи по идентификатору;
затем выполнить сортировку по ключу;
сравнить результат устойчивого и неустойчивого алгоритма.
Необходимо показать, что при использовании устойчивой сортировки относительный порядок элементов с одинаковым значением второго ключа сохраняет результат первой сортировки, тогда как при использовании неустойчивого алгоритма этот порядок может нарушаться.
После выполнения необходимо объяснить, что означает устойчивость сортировки, в каких прикладных задачах это свойство имеет принципиальное значение. Также необходимо сделать вывод о том, почему устойчивость особенно важна при многокритериальной сортировке записей, когда один этап сортировки должен сохранять результат предыдущего этапа.
