Задачі: Алгоритми сортування¶
Практичні задачі на тему алгоритмів сортування з використанням шаблонного vector<T>.
Формат задач
У кожній задачі дано сигнатуру функції. Потрібно написати реалізацію замість ....
Всі функції — вільні шаблонні функції, що працюють з vector<T> з лекції.
Bubble Sort¶
Задача 1: Сортування за спаданням
Модифікуйте bubble sort так, щоб він сортував за спаданням (від більшого до меншого).
Приклад: [5, 3, 8, 4, 2] → [8, 5, 4, 3, 2]
Задача 2: Підрахунок обмінів
Напишіть варіант bubble sort, який повертає кількість виконаних обмінів.
Приклад: [5, 3, 8, 4, 2] → повертає кількість swap-ів
Задача 3: Сортування частини масиву
Напишіть bubble sort, який сортує лише елементи від індексу left до right включно.
Приклад: [9, 5, 3, 8, 4, 2, 7], left=2, right=5 → [9, 5, 2, 3, 4, 8, 7]
Задача 4: Перевірка відсортованості
Напишіть функцію, що перевіряє, чи вектор відсортований за зростанням.
Приклад: [1, 2, 3, 5] → true, [1, 3, 2] → false
Insertion Sort¶
Задача 5: Вставка в відсортований вектор
Дано вже відсортований вектор. Вставте нове значення на правильну позицію, зберігши порядок. Вектор вже має достатньо capacity.
Приклад: [2, 4, 6, 8], value=5 → [2, 4, 5, 6, 8]
Задача 6: Insertion sort за спаданням
Модифікуйте insertion sort для сортування за спаданням.
Задача 7: Кількість зсувів
Напишіть варіант insertion sort, який повертає загальну кількість зсувів (присвоєнь v[j+1] = v[j]).
Підказка: кількість зсувів дорівнює кількості інверсій у масиві (пар елементів, що стоять у неправильному порядку).
Задача 8: Binary insertion sort
В insertion sort пошук місця для вставки можна прискорити за допомогою бінарного пошуку. Реалізуйте цей варіант.
Підказка: бінарний пошук знаходить позицію за \(O(\log n)\), але зсув елементів все одно \(O(n)\). Загальна складність залишається \(O(n^2)\), але кількість порівнянь зменшується.
Quicksort¶
Задача 9: Partition з іншим pivot
Модифікуйте partition так, щоб pivot був першим елементом, а не останнім.
Задача 10: Підрахунок рекурсивних викликів
Напишіть quicksort, який підраховує та повертає загальну кількість рекурсивних викликів.
Підказка: передавайте лічильник за посиланням у рекурсивну функцію.
Задача 11: Пошук k-го елемента (quickselect)
Використовуючи ідею partition з quicksort, знайдіть k-й за величиною елемент без повного сортування масиву.
Приклад: [5, 3, 8, 4, 2], k=2 → 3 (другий за величиною)
Підказка: після partition pivot стоїть на позиції pi. Якщо pi == k, відповідь знайдена. Якщо k < pi, шукаємо зліва. Якщо k > pi, шукаємо справа.
Задача 12: Three-way partition
Модифікуйте partition для випадку, коли масив містить багато однакових елементів. Після partition масив має три зони: менші за pivot, рівні pivot, більші за pivot.
Merge Sort¶
Задача 13: Злиття двох відсортованих векторів
Дано два відсортовані вектори. Створіть новий вектор, що містить всі елементи обох у відсортованому порядку.
Приклад: [1, 3, 5] і [2, 4, 6] → [1, 2, 3, 4, 5, 6]
Задача 14: Підрахунок інверсій через merge sort
Інверсія — це пара індексів \((i, j)\), де \(i < j\), але \(a[i] > a[j]\). Модифікуйте merge sort, щоб підрахувати кількість інверсій у масиві.
Приклад: [5, 3, 8, 4, 2] → 7 інверсій
Підказка: під час злиття, коли беремо елемент з правої половини, він менший за всі елементи, що залишилися в лівій половині. Кількість цих елементів — це кількість нових інверсій.
Задача 15: Bottom-up merge sort
Реалізуйте merge sort без рекурсії (ітеративний варіант). Починаємо з блоків розміру 1 і поступово зливаємо сусідні блоки.
Підказка: зовнішній цикл збільшує розмір блоку (1, 2, 4, 8, ...). Внутрішній цикл зливає сусідні пари блоків.
Задача 16: Natural merge sort
Модифікуйте merge sort так, щоб він спочатку знаходив вже відсортовані ділянки (runs) у масиві, а потім зливав їх.
Приклад: [1, 3, 5, 2, 4, 6] має два runs: [1, 3, 5] і [2, 4, 6] — достатньо одного злиття.
Порівняння та аналіз¶
Задача 17: Емпіричне порівняння
Напишіть програму, яка:
- Генерує випадковий вектор з
nелементів - Сортує його кожним з 4 алгоритмів (окремі копії!)
- Вимірює час кожного алгоритму
Порівняйте результати для n = 100, n = 1000, n = 10000.
Підказка: для вимірювання часу використовуйте <chrono>:
Задача 18: Найгірший випадок quicksort
Створіть масив, на якому quicksort (з pivot = останній елемент) працює за \(O(n^2)\). Поясніть, чому це відбувається.
Кастомні компаратори¶
Задача 19: Сортування студентів
Дано структуру student. Відсортуйте вектор студентів:
- a) за оцінкою (grade) за спаданням
- b) за віком (age) за зростанням
Задача 20: Сортування точок за відстанню
Відсортуйте вектор точок за відстанню від початку координат \((0, 0)\).
Підказка: відстань від \((0,0)\) — це \(\sqrt{x^2 + y^2}\). Але для порівняння достатньо порівнювати \(x^2 + y^2\) без кореня (корінь — монотонна функція).
Лекція: Алгоритми сортування