Похоже, у вас возникла проблема с пониманием концепции области действия с помощью рекурсии. Как правило, проще всего думать о рекурсии как о дереве / стеке.
Stack:
Допустим, n = 5 для упрощенного примера.
Up (5) помещается в стек.
Затем вы объявляете, что x внутри этой области видимости функции UP (3).
Теперь UP (3) помещается в стек, а UP (5) ожидает возврата Up (3).
Заказ стека:
Up(3)
Up(5)
Теперь Up (3) объявляет x внутри этой функции как UP (1) и терпеливо ждет возврата Up (1). Поскольку x объявлен внутри функции, они являются локальными переменными, доступными только внутри функции, которая их объявила. Это означает, что X внутри Up (3) хранится в совершенно другом месте в памяти, как X внутри Up (5). Вы определенно узнаете больше об этом, когда будете исследовать адресные пространства и то, как хранятся локальные переменные и тому подобное. Но продолжаем вперед!
Stack:
Up(1)
Up(3)
Up(5)
Up (1) возвращает 1, и поэтому мы выталкиваем его из стека! Это означает, что Up (3) может продолжить работу.
Стек:
Up(3)
Up(5)
Up (3) теперь имеет x = 1 (возврат Up (1) и желает вернуть x + Up (2). Для этого мы помещаем Up (2) в стек.
Stack:
Up(2)
Up(3)
Up(5)
Продолжая этот пример, Up (2) добавит Up (0) в стек. Up (0) вернет 0, поэтому x внутри области видимости для Up (2) будет установлено в 0. Up (2) добавит Up (1) в стек, что вернет 1. Up (2) вернет (0 + 1). Теперь мы можем вернуться к Up (3), вытолкнув Up (2) из стека. Up (3) имеет x = 1 и желает вернуться (1 + 1). Подняв вверх (3) со стека, мы остаемся с Up (5) в стеке. X теперь установлен в 2 из-за возврата Up (3). Теперь мы добавляем Up (4) в стек, который добавляет Up (2), Up (0), Up (1), Up (3), Up (2), Up (0), Up (1) в этом порядке Примечание (многие из этих вызовов отменяются до добавления новых).
Я рекомендую прочитать о глобальной области действия и области действия функции. Понимание этих концепций очень важно для основ понимания рекурсии. Однако вы уже можете видеть, что этот тип рекурсии довольно грубый и совсем не оптимизирован. Например, вы вычисляете Up (2) несколько раз для каждого созданного рекурсивного вызова. Это приводит к проблеме масштабируемости при работе с большими числами, поскольку вы повторяете одну и ту же операцию несколько раз для одного и того же номера. Эту проблему можно решить с помощью массива памятки и немного большей логики для меньшего времени выполнения Big O, но это может быть слишком подробно для этого вопроса.