Злиття відсортованих ділянок
Для розуміння алгоритму почнемо його розбір з кінця – з механізму злиття відсортованих блоків.
Уявімо, що у нас є два будь-яким способом відсортованого масиву чисел, які необхідно об’єднати один з одним так, щоб сортування не порушилася. Для простоти будемо впорядковувати числа за зростанням.
Елементарний приклад: обидва масиви складаються з одного елемента кожен.
int[] arr1 = {31};
int[] arr2 = {18};
Щоб злити їх, потрібно взяти нульовий елемент першого масиву (не забудьте, що нумерація починається з нуля) і нульовий елемент другого масивів. Це, відповідно, 31 і 18. За умовою сортування число 18 має йти першим, так як воно менше. Просто розставляємо числа в правильному порядку:
int[] result = {18, 31};
Звернемося до прикладу складніше, в якому кожен масив складається з декількох елементів:
int[] arr1 = {2, 17, 19, 45};
int[] arr2 = {5, 6, 21, 30};
Алгоритм злиття буде полягати в послідовному порівнянні менших елементів і розміщення їх у результуючому масиві в правильному порядку. Для відстеження поточних індексів введемо дві змінні – index1 і index2. Спочатку приравняем їх до нуля, так як масиви відсортовані, і найменші елементи стоять на початку.
int index1 = 0;
int index2 = 0;
Розпишемо по кроках весь процес злиття:
На першому витку ситуація буде виглядати так:
index1 = 0;
index2 = 0;
arr1[0] = 2;
arr2[0] = 5;
arr1[0] < arr2[0];
index1++;
result[0] = arr1[0]; // result = [2]
На другому витку:
index1 = 1;
index2 = 0;
arr1[1] = 17;
arr2[0] = 5;
arr1[1] > arr2[0];
index2++;
result[1] = arr2[0]; // result = [2, 5]
На третьому:
index1 = 1;
index2 = 1;
arr1[1] = 17;
arr2[1] = 6;
arr1[1] > arr2[1];
index2++;
result[2] = arr2[1]; // result = [2, 5, 6]
І так далі, поки в результаті не вийде повністю результуючий масив відсортований: {2, 5, 6, 17, 21, 19, 30, 45}.
Певні складності можуть виникнути, якщо зливаються масиви з різними довжинами. Що робити, якщо один з поточних індексів досяг останнього елемента, а у другому масиві ще залишаються члени?
int[] arr1 = {1, 4};
int[] arr2 = {2, 5, 6, 7, 9};
// 1 step
index1 = 0, index2 = 0;
1 2
result = {1, 2};
// 3 step
index1 = 1, index2 = 1;
4 < 5
result = {1, 2, 4};
//4 step
index1 = 2, index2 = 1
??
Змінна index1 досягла значення 2, проте масив arr1 не має елемента з таким індексом. Тут все просто: достатньо перенести залишилися елементи другого масиву в результуючий, зберігши їх порядок.
result = {1, 2, 4, 5, 6, 7, 9};
Ця ситуація вказує нам на необхідність зіставляти поточний індекс перевірки з довжиною сливаемого масиву.
Схема злиття упорядкованих послідовностей (A і B) різної довжини:
- Якщо довжина обох послідовностей більше 0, порівняти A[0] і B[0] і перемістити менший з них в буфер.
- Якщо довжина однієї з послідовностей дорівнює 0, взяти залишилися елементи другої послідовності і, не змінюючи їх порядок, перенести в кінець буфера.