Это не так сложно. Рассмотрим рекурсивное слияние:
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
/ \ split
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
/ \ / \ split
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
/ \ / \ / \ / \ split
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
| | | | | | | | | | | | | | | |
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
\ / \ / \ / \ / merge
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
\ / merge
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
Если вы замечаете, что когда вы разделяетесь, вы ничего не делаете. Вы просто указываете рекурсивной функции частично отсортировать массив. Сортировка массива состоит в том, чтобы сначала отсортировать обе половинки, а затем объединить их. Итак, в основном, что у вас есть это:
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
| | | | | | | | | | | | | | | |
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
\ / \ / \ / \ / merge
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
\ / merge
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
Теперь это должно быть очевидно. Сначала вы объединяете элементы массива 2 на 2, затем 4 на 4, затем 8 на 8 и т. Д. То есть внешний for
дает вам 2, 4, 8, 16, 32, ... (то, что он называет размер сегмента , потому что i
цикла содержит это число), а внутренний for
(скажем, с итератором j
) проходит по массиву, i
путем i
слияния array[j...j+i/2-1]
с array[j+i/2..j+i-1]
.
Я бы не стал писать код, так как это домашняя работа.
Редактировать: изображение того, как работает внутренний for
Представьте себе, если i
равно 4, значит, вы находитесь на этом этапе:
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
у вас будет for
, который однажды даст вам 0
(что составляет 0*i
) как j
, а затем 4
(что 1*i
) как j
. (если бы i
было 2, вы бы получили j
, как 0, 2, 4, 6)
Теперь, когда вам нужно объединить array[0..1]
с array[2..3]
(который сформулирован как array[j..j+i/2-1]
и array[j+i/2..j+i-1]
с j = 0
), а затем array[4..5]
с array[6..7]
(который сформулирован тем же формулы array[j...j+i/2-1]
и array[j+i/2..j+i-1]
потому что сейчас j = 4
) То есть:
i = 4:
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | |
/ / / / \ \ \ \
(j = 0) (j = 4)
| | | | | | | |
j | | | j | | |
| | | j+i-1 | | | j+i-1
| | j+i/2 | | j+i/2
| j+i/2-1 | j+i/2-1
| | | | | | | |
| | | | | | | |
\ / \ / \ / \ /
v v v v
merge merge
Надеюсь, это хоть немного понятно.
Боковая помощь: Просто подсказка, если вы действительно не знаете, как for
работает:
for (statement1; condition; statement2)
{
// processing
}
все равно что писать
statement1;
while (condition)
{
// processing
statement2;
}
Итак, если вы всегда писали
for (int i = 0; i < 10; ++i)
это означало начинаться с 0, в то время как i
меньше 10, сделать что-то с i
и затем увеличить его. Теперь, если вы хотите, чтобы i
изменился по-другому, просто измените statement2
, например:
for (int i = 1; i < 1024; i *= 2)
(Попытайтесь понять, как работает этот окончательный for
на основе его эквивалента while
, который я вам написал)