10.20 Рекурсия

Форма для сдачи

Backtrace

Вызов функции:

   1 #include <execinfo.h>
   2 #include <stdio.h>
   3 
   4 void dump() {
   5         void* buffer[128];
   6         int frames = backtrace(buffer, 128);
   7         backtrace_symbols_fd(buffer, frames, 1);
   8 }
   9 
  10 void second() {
  11         dump();
  12 }
  13 
  14 void first() {
  15         second();
  16 }
  17 
  18 int main(void) {
  19         printf("%p %p %p %p\n", main, first, second, dump);
  20         first();
  21         return 0;
  22 }

Рекурсия в Си

Рекурсия в Си — это просто ситуация, когда функция в конце концов вызывает себя же.

void rec(int a, int b) {
        printf("%d %d\n", a, b);
        if(a)
                rec(0, a);
        else
                b=0;
        printf("%d %d\n", a, b);
}

void main(void) {
        rec(1, 2);
        return 0;
}

Алгоритмическая рекурсия

:)) Сколько проходов цикла в примере выше? Что является основанием рекурсии?

Принцип уместности рекурсии

Критерий уместности: вложенность рекурсивных вызовов при обработке n элементов данных не должна превышать log(n)(строго говоря — O(log(n)), то есть логарифм, умноженный на константу).

Указатели на функцию

Как мы уже видели, имена функций — это их адреса, а значит, это указатели. И их можно передавать как параметры! Только тип указать.

Д/З (предварительное!)


  1. Написать неуместно рекурсивную функцию, которая считает количество чисел, превосходящих последнее введённое число, не храня их явно в массиве. Можно пользоваться глобальными переменными.
    15
    8
    43
    29
    1
    50
    36
    22
    →
    4
  2. Ввести натуральное N, вывести все перестановки чисел 0…N-1 (порядок не важен)
    4
    →
    0 1 2 3
    0 1 3 2
    0 2 1 3
    0 2 3 1
    0 3 2 1
    0 3 1 2
    1 0 2 3
    1 0 3 2
    1 2 0 3
    1 2 3 0
    1 3 2 0
    1 3 0 2
    2 1 0 3
    2 1 3 0
    2 0 1 3
    2 0 3 1
    2 3 0 1
    2 3 1 0
    3 1 2 0
    3 1 0 2
    3 2 1 0
    3 2 0 1
    3 0 2 1
    3 0 1 2
  3. Уберпалиндромным называется массив, если он сам палиндромом длины ⩾ 3 (в нём n ⩾ 3 элементов, и array[i] == array[n-1-i] ∀ i), или если его можно разбить на несколько уберпалиндромных массивов. Ввести N, затем целочисленный массив на N элементов. Ввести "YES", если массив уберпалиндромичен, и "NO" в противном случае.

    12 1 2 1 7 6 4 4 6 7 5 6 6 5

    → 1 2 1 | 7 6 4 4 6 7 | 5 6 6 5

    YES
  4. Ввести в строке и вычислить формулу без пробелов (правильность ввода, как всегда, гарантируется и проверять её не надо); <число> — целое (scanf() сам разберётся).

    <формула> :: = <число> | ("max" | "min") "(" <формула> "," <формула> ")"
    Пример:
    max(min(123,234),max(1,min(777,3)))
    →
    123

LecturesCMC/AL/Prac/14_Recursion (последним исправлял пользователь FrBrGeorge 2026-10-21 19:22:02)