Это очень хороший вопрос.
Лучший ответ, который у меня есть, - это факторинг: разделяй и властвуй. Это немного сложно в C ++, потому что он не поддерживает функции высшего порядка, но вы можете сделать это. Самые распространенные процедуры - это карты и сгибы. [C ++ уже имеет cofold, называемый std :: аккумулировать].
Другая вещь, которую вы должны тщательно рассмотреть, - это как структурировать ваш код, чтобы обеспечить хвостовую рекурсию, где это возможно. Вскоре можно распознать хвостовые вызовы и думать о них как о петлях, и это значительно снижает перегрузку мозга от повторяющихся повсюду.
Другая хорошая техника называется trust . Это означает, что вы пишете вызов функции, которую вы, возможно, еще даже не определили, и доверяете , что она будет делать то, что вы хотите, без дальнейших церемоний. Например, вы полагаете, что он будет правильно посещать узлы дерева снизу вверх, даже если ему придется вызывать функцию, которую вы сейчас пишете. Пишите комментарии с указанием предварительных и постусловий.
Другой способ сделать это (и я сожалею об этом) - это сначала использовать настоящий язык программирования, такой как Ocaml или Haskell, а затем попытаться перевести хороший чистый код на C ++. Таким образом, вы сможете легче увидеть структуру, не увязая в подробностях уборки, уродливом синтаксисе, отсутствии локализации и прочем. Если у вас все получилось, вы можете механически перевести его на C ++. (Или вы можете использовать Феликс, чтобы перевести его для вас)
Причина, по которой я сказал, что извините, заключается в том, что .. если вы сделаете это, вам больше не захочется писать на C ++, что затруднит поиск удовлетворительной работы. Например, в Ocaml просто добавьте элементы списка (без использования сгиба):
let rec addup (ls: int list) : int = match ls with
| [] -> 0 (* empty list *)
| h::t -> h + addup t (* add head to addup of tail: TRUST addup to work *)
Это не хвостовая рекурсия, но это:
let addup (ls: int list) : int =
let rec helper ls sum = match ls with
| [] -> sum
| h :: t -> helper t (h+ sum)
in
helper ls 0
Преобразование выше хорошо известно. Вторая процедура на самом деле проще, когда вы понимаете, что она делает. Я слишком ленив, чтобы перевести это на C ++, возможно, вы можете перекодировать это ... (одной только структуры алгоритмов должно быть достаточно, чтобы выяснить синтаксис)