Это не так сложно. Рассмотрим рекурсивное слияние:
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
/ \ 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
, который я вам написал)
person
Community
schedule
14.10.2011