UNIVERSIDADE FEDERAL DE ITAJUBÁ UNIFEI CAMPUS ITABIRA BAC004 TÉCNICAS DE PROGRAMAÇÃO Professores: Claudia, Denílson, Fabiana, Fernando, Juliano, Natália, Raquel, Rodrigo, Sandro e Walter Roteiro Prático Nº 13 Recursividade 1) Objetivos: Definir e apresentar funções recursivas. 2) Livro texto: GUIMARÃES, A. de M., LAGES, N. A. de C. Algoritmos e Estruturas de Dados. 1 ed. Rio de Janeiro: LTC, 2008. 3) Fundamentação Teórica : a) Referência para consulta e estudos: Capítulo 7 do livro texto. b) Definição: (Livro texto seção 7.5) Existem casos em que uma função chama a si própria. Diz-se, então, que a função é recursiva. Por exemplo, o fatorial de um número n pode ser definido recursivamente, ou seja: n! = n (n-1)!, se n 1 1, se n = 0 Pode-se escrever uma função recursiva que traduz essa definição: int fatorial (int n) int fat; if (n == 0 n == 1) // Critério de parada fat = 1; fat = n * fatorial(n-1); // Chamada recursiva return fat; Ilustração 1: Chamadas recursivas iniciando em fatorial(4). Essa representação é chamada de árvore de recursão. Geralmente, o uso da recursividade permite uma descrição mais clara e concisa dos algoritmos, especialmente quando o problema a ser resolvido é de natureza recursiva (Ziviani, 2007). Entretanto, um algoritmo não recursivo equivalente pode ser mais eficaz.
Atenção: Quando uma função chama a si mesma, uma nova cópia da função passa a ser executada. As variáveis locais da segunda cópia são independentes das variáveis locais da primeira; A cada nova chamada da função as anteriores ficam suspensas até está última ser resolvida; Quando a última for resolvida, haverá um retorno sucessivo das chamadas, resolvendo-as uma a uma; Para que uma função recursiva tenha fim, deve-se ter uma condição de parada; Toda função recursiva (ou não) deve possuir pelo menos uma chamada proveniente de um local exterior a ele (chamada externa); Toda função recursiva possui uma correspondente não recursiva; Um algoritmo não recursivo equivalente pode ser mais eficaz. c) Outro exemplo: Sequência de Fibonacci recursiva Na Matemática, Sequência de Fibonacci é uma sequência de números definida recursivamente como: F(n) = 0, se n=0; 1, se n=1; F(n-1) + F(n-2), outros casos. Cada número, a partir do terceiro, é resultado da soma dos outros dois anteriores. int fibonacci (int n) if (n == 0) if (n == 1) return 1; return fibonacci(n-1) + fibonacci(n-2); Ilustração 2: Chamadas recursivas iniciando em fibonacci(3).essa representação é chamada de árvore de recursão. Programa completo em C/C++ com função fibonacci recursiva #include<iostream> using namespace std;
// Protótipos das funções int fibonacci(int); void entrada(int &); int main() int n; entrada(n); cout << "Fibonacci de " << n << "e': " << fibonacci(n); // Chamada à função fibonacci(n) system("pause > null"); void entrada(int &n) cout << "Cálculo de Fibonacci"; do cout << "Entre com valor de n: "; cin >> n; while(n<0); int fibonacci(int n) // Definição da função fibonacci() if (n == 0) // Critério de parada if (n == 1) // Critério de parada return 1; return fibonacci(n-1) + fibonacci(n-2); // Chamada recursiva Programa completo em C/C++ com função fibonacci recursiva INSTRUMENTADA para verificar as chamadas e retornos das funções #include<iostream> using namespace std; // Protótipos das funções int fibonacci(int); void entrada(int &); int main() int n; entrada(n); cout << "\nfibonacci de " << n << "e':" << fibonacci(n); // Chamada à função fibonacci(n) system("pause > null"); void entrada(int &n) // Definição da função entrada() cout << "Cálculo de Fibonacci"; do cout << "\nentre com valor de n: "; cin >> n; while(n<0); int fibonacci(int n) // Definição da função fibonacci() cout << "\nchamando fibonacci(" << n << ")..."; if (n == 0) // Critério de parada
cout << "\nretornando 0..."; // Critério de parada if (n == 1) // Critério de parada cout << "\nretornando 1..."; return 1; // Critério de parada int fib = fibonacci(n-1) + fibonacci(n-2); // Chamada recursiva cout << "\nretornando " << fib << " (fibonacci(" << n-1 << ") + fibonacci(" << n-2 << ")..."; return fib; Ilustração 3: Execução do programa Fibonacci recursivo instrumentado com as mensagens de chamadas e retorno. 4) Roteiro: a ) Digite os exemplos anteriores (Fatorial e Fibonacci), compile-os e execute-os. Nos exemplos com instrumentação de código, faça a árvore de recursão e compare-a com as impressões na tela. b ) O cálculo do M.D.C (Máximo Divisor Comum) pode ser realizado pelo processo das divisões sucessivas. Nesse processo, efetua-se várias divisões até chegar a uma divisão exata. O divisor desta divisão é o M.D.C. Acompanhe o cálculo do M.D.C.(48, 30): Regra prática: 1º) Divide-se o número maior pelo número menor; 48 / 30 = 1 (com resto 18) 2º) Divide-se o divisor 30, que é divisor da divisão anterior, por 18, que é o resto da divisão anterior, e assim sucessivamente; 30 / 18 = 1 (com resto 12)
18 / 12 = 1 (com resto 6) 12 / 6 = 2 (com resto zero - divisão exata) 3º) O divisor da divisão exata é 6. Então M.D.C.(48,30) = 6. Assim, implemente uma função recursiva para o cálculo de M.D.C. Chame essa função na main. Faça também uma função de entrada de dados com sua validação. c ) Sendo: x n = x * x (n-1), n 1 1, n=0 Faça uma função recursiva para o cálculo da potência. Faça também uma função de entrada de dados com validação. d ) Dada a seguinte função recursiva: int X (int n, int m) int y; if (m == n m == 0 n == 0) y = 1; y = X(n-1, m) + X(n-1, m+1); return y; (i) Qual o valor de X(3,2)? Utilize a árvore de recursão para auxiliá-lo. (ii) Quantas chamadas serão realizadas para calcular X(3,2)? e ) Dada a seguinte função recursiva: int X (int n) int y; if (n >= 0 && n <= 2) y = n; y = X(n-1) + X(n-2) + X(n-3); return y; (iii) Qual o valor de X(3)? Utilize a árvore de recursão para auxiliá-lo. (iv) Quantas chamadas serão realizadas para calcular X(3)? (v) Indique a sequência temporal destas chamadas. e ) Escreva uma função não recursiva para a seguinte função: int f (int i) int r;
if (i>1) r = i + f(i-1); r = 1; return r;