Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке сортування вставками (insertion sorts)?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Сортування вставками (Insertion Sort)** - простий, стабільний і «внутріпроцедурний» (in-place) алгоритм, який формує відсортовану частину масиву, послідовно вставляючи кожен наступний елемент на своє місце. У гіршому і середньому випадках працює за O(n²), у найкращому випадку (майже відсортовані дані) - за O(n). Підходить для малих масивів, майже відсортованих даних і як частина гібридних алгоритмів. **Ключове:** найкращий випадок дає O(n), а не завжди O(n²) - адаптивність до майже відсортованих даних є головною перевагою цього алгоритму.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь **Сортування вставками (Insertion Sort)** - це простий, стабільний і «внутріпроцедурний» (in-place) алгоритм, який формує відсортовану частину масиву, послідовно вставляючи кожен наступний елемент на своє місце. У гіршому і середньому випадках працює за O(n²), у найкращому випадку (майже відсортовані дані) - за O(n). Підходить для малих масивів, майже відсортованих даних і як частина гібридних алгоритмів. ## Детальний розбір ### Ідея алгоритму Уявіть, що ви розкладаєте карти за зростанням у руці: берете нову карту і вставляєте її у вже відсортовану частину так, щоб порядок зберігався. Так само алгоритм проходить масив зліва направо, підтримуючи зліва відсортований префікс і вставляючи в нього поточний елемент. ### Покроковий алгоритм 1. Вважаємо, що підмасив з одного елемента (перший) уже відсортований. 2. Беремо наступний елемент (ключ) і порівнюємо його з елементами відсортованої частини справа наліво. 3. Зсуваємо елементи, більші за ключ, на одну позицію вправо, щоб звільнити місце. 4. Вставляємо ключ на звільнену позицію. 5. Повторюємо для всіх елементів. ### Приклад коду (JavaScript) ``` function insertionSort(arr) { for (let i = 1; i < arr.length; i++) { const key = arr[i]; let j = i - 1; // Зсуваємо елементи вправо, поки вони більші за key while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } // Вставляємо key на свою позицію arr[j + 1] = key; } return arr; } // Оптимізація: бінарна вставка (менше порівнянь, зсуви ті самі) function binaryInsertionSort(arr) { for (let i = 1; i < arr.length; i++) { const key = arr[i]; let left = 0; let right = i; // напівінтервал [left, right) // Знаходимо позицію вставки бінарним пошуком while (left < right) { const mid = (left + right) >> 1; // <= ставить key після рівних - зберігає стабільність if (arr[mid] <= key) left = mid + 1; else right = mid; } // Зсув блоку вправо на 1, щоб вставити key for (let j = i; j > left; j--) arr[j] = arr[j - 1]; arr[left] = key; } return arr; } // Демонстрація const nums = [5, 2, 4, 6, 1, 3]; console.log(insertionSort([...nums])); // [1,2,3,4,5,6] console.log(binaryInsertionSort([...nums])); // [1,2,3,4,5,6] ``` ### Складність і властивості - Час: у гіршому/середньому випадках O(n²), у найкращому - O(n) при майже відсортованих даних (мало інверсій). - Пам'ять: O(1) додаткової (in-place). - Стабільність: стабільне сортування (рівні елементи зберігають відносний порядок). - Адаптивність: швидше працює на майже відсортованих масивах; фактично час залежить від кількості інверсій. - Онлайн-властивість: можна підтримувати відсортовану структуру, вставляючи елементи, що надходять, по одному. ### Коли використовувати - Малі масиви (зазвичай до 20-50 елементів) - низькі константи й простота. - Майже відсортовані дані - близько до O(n). - У гібридних сортуваннях: як «доведення» для малих підмасивів після розбиття (наприклад, після швидкого сортування). - Онлайн-оновлення відсортованих колекцій, коли елементи надходять поступово. ### Варіанти та оптимізації - Бінарна сортування вставками: зменшує кількість порівнянь з O(n²) до O(n log n), але зсувів усе одно O(n²). - Сентинел: заздалегідь ставлять мінімальний елемент на початок, щоб прибрати перевірки меж у циклі. - Зсуви замість обмінів: використовувати зсув блоку і одиничний запис ключа - менше операцій запису. - Зв'язні списки: вставки можуть бути O(1) за відомої позиції, але пошук позиції все одно O(n). - Зв'язок із Shell sort: Shell - це узагальнення вставок зі спадними «кроковими» інтервалами для зменшення кількості зсувів. ### Порівняння з бульбашковим сортуванням і сортуванням вибором - Бульбашкове сортування vs вставки: обидва O(n²), але вставки зазвичай роблять менше зайвих обмінів і швидші на майже відсортованих масивах; бульбашкове можна оптимізувати до O(n) на відсортованому масиві, але константи вищі. - Вибір vs вставки: вибір робить O(n) обмінів, але завжди O(n²) порівнянь і не є стабільним (у класичному вигляді); вставки - стабільні й адаптивні. ### Інваріант і коректність Інваріант: після i-ї ітерації підмасив [0..i) відсортований. Вставка i-го елемента зберігає інваріант, оскільки всі елементи, більші за key, зсуваються, а key потрапляє на єдину відповідну позицію. Після завершення для i = n масив відсортований. ### Часті помилки на співбесіді - Використання обмінів замість зсувів - більше записів і гірша продуктивність. - Помилки меж: не вставляють key після завершення циклу порівняння (потрібно arr[j + 1] = key). - Втрата стабільності: неправильно обрана умова порівняння при бінарній вставці. - Нерозуміння адаптивності: у найкращому випадку O(n), а не завжди O(n²).Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.