Таким образом, на самом деле вы можете всегда рефакторировать функцию, чтобы она была хвостовой рекурсивной ... Большинство людей, программирующих на других языках, будут использовать продолжение для его эффективного кодирования. Но мы смотрим здесь на язык C / C ++ более конкретно, поэтому я предполагаю избавиться от этого, просто кодируя саму функцию (я имею в виду, не добавляя в язык универсальную инфраструктуру продолжения).
Предположим, что у вас есть итерационная версия вашей функции, которая должна выглядеть следующим образом:
void iterative() {
while (cond)
dosomething()
}
Затем, чтобы превратить его в хвостовую рекурсивную функцию, достаточно написать:
void tailrecursive() {
if (!cond)
return;
dosomething();
tailrecursive();
}
Большую часть времени вам необходимо передать '1011 * состояние ' рекурсивному вызову, который добавляет некоторые дополнительные параметры, которые раньше были бесполезны. В вашем конкретном случае у вас есть обход дерева предзаказа:
void recursive_preorder(node n) {
if (n == visited)
return;
dosomething(n);
foreach child_node in n.getChildren() {
recursive_preorder(child_node);
}
}
Итеративному эквиваленту необходим ввод стека для запоминания узлов проводника (поэтому мы добавляем операции push / pop):
void iterative_preorder(node n) {
if (n == visited)
return;
stack worklist = stack().push(n);
while (!worklist.isEmpty()) {
node n = worklist.pop()
dosomething (n);
foreach child_node in n.getChildren() {
worklist.push(child_node);
}
}
}
Теперь, взяв эту итеративную версию обхода дерева предзаказов и превратив ее в хвостовую рекурсивную функцию, получим:
void tail_recursive_preorder_rec(stack worklist) {
if (!worklist.isEmpty()) {
node n = worklist.pop()
dosomething (n);
foreach child_node in n.getChildren() {
worklist.push(child_node);
}
}
tail_recursive_preorder_rec(worklist)
}
void tail_recursive_preorder (node n) {
stack worklist = stack().push(n);
tail_recursive_preorder_rec(worklist);
}
И это дает вам хвостовую рекурсивную функцию, которая будет приятно оптимизирована компилятором. Наслаждайтесь!