Рекурсивна функція

Функція яка викликає (використовує) сама себе називається рекурсивною.

    
            #include <iostream>

            void fun(int a)
            {
                std::cout << a << std::endl;
                a++;
                //функція "fun" викликає сама себе
                fun(a);
            }

            int main()
            {
                fun(3);
                return 0;
            }
        
    

Як помітно, функція «fun» викликає сама себе. Тому, така функція буде називатися рекурсивною.

Якщо ви запустите дану програму, то побачите, що вона виводить безперестанку числа. Все виглядатиме як безкінечний цикл. На справді це так і є. Наша програма не має умови завершення (зупинки). Тому, функція буде постійно викликати сама себе ж.

Рекурсивну функцію варто сприймати як цикл

Умову зупинки ми можемо записати за допомогою оператора

Наприклад:

    
            #include <iostream>

            void fun(int a)
            {
                std::cout << a << std::endl;
                a++;
                //зауважте, що рядок виводу значення
                //змінної "а" знаходиться перед
                //додаванням до неї "1"
                //тому реальне значення змінної
                //є більшим на цю одиницю

                //ми будемо викликати функцію лише
                //за умови коли "а" є меншим
                //за "7". це і буде умова зупинки
                if(a < 7)
                {
                    //функція "fun" викликає сама себе
                    fun(a);
                }
            }

            int main()
            {
                fun(3);
                return 0;
            }
        
    

Коли ми вчили функції, то розбиралися, що програма зупиняється (переривається) на виконання функції, а потім повертається до попереднього місця та продовжує своє виконання.

Рекурсивна функція працює за тим же принципом.

    
            #include <iostream>

            void fun(int a)
            {
                std::cout << "start\n";
                std::cout << "a = " << a << std::endl;
                if(a < 7)
                {
                    a++;
                    fun(a);
                }
                std::cout << "a = " << a << std::endl;
                std::cout << "end\n";
            }

            int main()
            {
                int a = 3;
                fun(a);
                return 0;
            }
        
    

Зверніть увагу. Значення змінної з першу йдуть у порядку зростання а потім у порядку спадання Якщо із зростанням все зрозуміло. Ми до змінної додаємо одиницю і лише тоді передаємо її (змінну) далі. Тому, ми і бачимо збільшення. А зі спаданням уточнимо. У функцію ми передаємо копію змінної, тому оригінал залишається з тим же значенням, що і був до передачі. Тому, коли ми в перше викликаємо функцію, то значення змінної є Далі ми додаємо до неї ще одиницю і її значення стає Далі викликаємо ще раз функцію. Відповідно, коли рекурсія закінчується (не виконується умова ми повертаємося до старих значень змінної Тобто, при першому виклику змінна була зі значенням тому і виводиться в кінці.

Рекурсивні функції в реальності використовуються не часто але знати про них варто.

Наприклад, за допомогою рекурсії ми можемо знаходити перші «n» члени арифметичної чи геометричної прогресії.

    
            #include <iostream>

            //a - значення члена арифметичної прогресії
            //d - різниця прогресії
            //n - кількість членів прогресії
            //i - номер члена прогресії
            void aref(float a, float d, int n, int i = 1)
            {
                std::cout << "a" << i << " = " << a << std::endl;
                if(i < n)
                {
                    i++;
                    a += d;
                    aref(a, d, n, i);
                }
            }

            int main()
            {
                float a = 3.2;
                float d = 0.4;
                int n = 5;
                aref(a, d, n);
                return 0;
            }
        
    

Ви можете без проблем зробити щоб ваша рекурсивна функція повертала якесь значення. Для цього необхідно як у звичайній функції вказати «тип функції (тип значення яке вона має повернути)» та за допомогою ключового слова «return» повернути це значення. Але будьте обережні. Функція буде повертати значення не з кінцевої рекурсії, а з початкової!

    
            #include <iostream>

            int fun(int a)
            {
                if(a < 5)
                {
                    a++;
                    //тепер в початковій рекурсії
                    //значення змінної "а" є "3"
                    fun(a);
                }

                //тому, функція поверне значення 3*10 = 30
                return a*10;
            }

            int main()
            {
                int a = 2;
                int b;
                b = fun(a);
                std::cout << "b = " << b;
                return 0;
            }
        
    

Якщо ви хочете отримати значення з кінцевої рекурсії, то використовуйте вказівники в якості параметрів функції.

    
            #include <iostream>

            //передаємо параметр через вказівник
            int fun(int *a)
            {
                if(*a < 5)
                {
                    //ми на пряму змінюємо значення параметра "а"
                    //тому, при повернені у початкову функцію
                    //ми будемо мати таке ж значення як і в кінцевій.
                    *a = *a + 1;
                    fun(a);
                }
                //тому, функція поверне значення 5*10 = 50
                return *a*10;
            }

            int main()
            {
                int a = 2;
                int b;

                //оскільки вказівники приймають адресу пам'яті,
                //то не забуваємо поставити символ "&"
                //перед ім'ям змінної
                b = fun(&a);
                std::cout << "b = " << b;

                return 0;
            }
        
    

Враховуючи, що це все сприймати буває доволі складно, то краще уникати використання рекурсивних функцій.