Вопрос можно обобщить:
void f()
{
f() // 0
f() // 1
// ...
f() // n
}
Если мы рисуем граф вызовов из, мы (конечно) получаем древовидную структуру:
f()
/ / \
/(0) /(1) .... \(n)
f() f() f()
Каждая дальнейшая рекурсивнаявызов будет повторяться над деревом под соответствующим родительским вызовом.Дерево не должно быть сбалансированным, т.е. пути от корня до разных листьев могут различаться по длине.Если рекурсивные вызовы находятся внутри условной ветви, даже не у всех не-оставленных узлов должно быть одинаковое количество дочерних элементов.
Теперь, если у нас есть два произвольных вызова функции f(); g();
, следующих друг за другом, g
может быть вызван только когда f()
возвращается.Это, конечно, относится и к двум последующим рекурсивным вызовам, что, в свою очередь, подразумевает, что дерево вызовов обязательно обходит, как при поиске в глубину.
Возвращаясь к вашему примеру быстрой сортировки (и игнорируя дляпростота в том, что разделение не должно приводить к двум половинкам одинакового размера), тогда вторая половина каждого подмассива будет отсортирована только после завершения предыдущей половины.Рассматривается глобально:
sort first half
sort first quarter
sort first eighth
sort second eighth
sort second quarter
sort third eighth
sort fourth eighth
sort second half
sort third quarter
// ...
sort fourth quarter
// ...