Recursividade Na linguagem C, assim como em muitas outras
of 24/24
Na linguagem C, assim como em muitas outras linguagens de programação, uma função pode chamar a si mesma. Uma função que chama a si mesma é chamada função recursiva. Recursividade 455 Muitos problemas são definidos com base nos mesmos, ou seja, podem ser descritos por instâncias do próprio problema. Para estas classes de problemas, o conceito de recursividade torna-se muito útil.
Recursividade Na linguagem C, assim como em muitas outras
Text of Recursividade Na linguagem C, assim como em muitas outras
Na linguagem C, assim como em muitas outras linguagens de
programação, uma função pode chamar a si mesma. Uma função que
chama a si mesma é chamada função recursiva.
Recursividade
455
recursiva.
Muitos problemas são definidos com base nos mesmos, ou seja, podem
ser descritos por instâncias do próprio problema. Para estas
classes de problemas, o conceito de recursividade torna-se muito
útil.
Todo cuidado é pouco ao se fazer funções recursivas. A primeira
coisa a se providenciar é um critério de parada, o qual vai
determinar quando a função deverá parar de chamar a si mesma. Este
cuidado impede que a função se chame infinitas vezes.
Recursividade
456
chame infinitas vezes.
Um exemplo de um problema cuja definição pode ser recursiva é o
cálculo do fatorial de um número natural.
No caso
A * (A - 1)!
no caso, é preciso especificar um critério de parada, qual
seria?
0! = 1
...
...
Ainda podemos definir uma função recursiva que implemente o computo
do fatorial de um número natural:
int fat(int n)
}
/*Exemplo de um programa que se utiliza da função recursiva fat()
*/
#include <stdio.h> int fat(int n); int main() {
int n; printf("\nDigite o numero que voce deseja saber o fatorial:
"); scanf("%d", &n); if (n>=0)
printf("\nO fatorial de %d e' %d", n, fat(n));
460
printf("\nO fatorial de %d e' %d", n, fat(n)); else {
printf("\nNao existe fatorial de numeros negativos!"); return
1;
} return 0;
/* ... */ }
Para uma melhor compreensão dos problemas associados à recursão,
devemos nos recordar do conceito de “registro de ativação”,
estudado na disciplina Introdução a Algoritmos.
O registro de ativação é uma área de memória que guarda informações
referentes ao estado atual de uma função:
Recursividade
461
que guarda informações referentes ao estado atual de uma
função:
- valor dos parâmetros formais; - valor das variáveis locais; -
valor do contador de programa (PC); - etc.
Sempre que uma função chama outra função o registro de ativação da
função invocadora é salvo e um novo registro de ativação é criado
para a função invocada.
Este processo é conhecido como salvamento
Recursividade
462
Este processo é conhecido como salvamento e troca de contexto e,
dependendo da “profundidade” da recursão, consome memória e um
tempo de execução significativos.
Exercício:
Para uma melhor compreensão do conceito de recursividade construa,
na linguagem de programação C, uma função recursiva que
Recursividade
463
programação C, uma função recursiva que receba como parâmetro dados
referentes a um vetor com elementos inteiros e inverta a ordem de
seus elementos.
Um outro exemplo muito utilizado de problema que possui uma
definição recursiva é a geração da série de Fibonacci:
{0,1,1,2,3,5,8,13,21,34, …}
Uma função recursiva que recebe a posição do elemento na série e
retorna seu valor é:
unsigned int fibonacci(unsigned int i)
Recursividade
465
return (fibonacci(i-1) + fibonacci(i-2)) }
Fora o problema do consumo de memória, gerado pela troca de
contexto na recursão, mencionado anteriormente, qual seria outro
problema proveniente da recursão evidenciado na função recursiva
apresentada para o cálculo do valor de um elemento da série de
Fibonacci com base na sua posição?
O cálculo do mesmo valor n vezes.
Recursividade
466
fibonacci(5)
fibonacci(2) + fibonacci(1)
Como vimos, mesmo problemas que possuem uma definição recursiva
sempre podem ser solucionados de forma imperativa. Um exemplo disso
é o cálculo imperativo do valor de um elemento da série de
Fibonacci com base na sua posição, apresentado abaixo: unsigned int
fibonacci(unsigned int i) {
Recursividade
467
return 1; else {
} }
Assim como a série de Fibonacci existem outras sequências definidas
por recorrência, ou seja, onde um valor da sequência é definido em
termos de um ou mais valores anteriores, o que é denominado de
relação de recorrência.
Exercício: Estabeleça a relação de recorrência presente na
Recursividade
468
S = { 1, 2, 6, 24, ... }
Exercício: Com base na relação de recorrência
estabelecida no exercício anterior, considerando o princípio da
modularização, construa um programa que receba uma lista de
inteiros positivos, representando posições de elementos na
sequência e retorne na saída padrão os
Recursividade
470
sequência e retorne na saída padrão os respectivos valores da
sequência. A lista de posições será finalizada pelo valor zero. Não
é necessário validar as entradas. Exemplo de entrada: Exemplo de
saída: 4 24 2 2 0
Tipos de Dados Definidos pelo Usuário
1. Agregados Heterogêneos (Estruturas)
Um agregado heterogêneo agrupa várias variáveis numa só. Sendo
utilizados para agrupar um conjunto de dados não similares formando
um novo tipo de dado.
472
Tipos de Dados Definidos pelo Usuário
1. Agregados Heterogêneos (continuação)
Para se criar um agregado heterogêneo usa-se o comando struct. Sua
forma geral é:
struct nome_do_tipo_da_estrutura {
} variáveis_do_tipo_da_estrutura;
struct nome_do_tipo_da_estrutura {
};
} variáveis_estrutura;
1. Agregados Heterogêneos (continuação)
struct tipo_endereco
1. Agregados Heterogêneos (continuação)
Vamos agora criar uma estrutura chamada ficha_pessoal capaz de
armazenar os dados pessoais de uma pessoa:
476
1. Agregados Heterogêneos (continuação)
Assim como ocorria nos agregados homogêneos (vetores) , nos
agregados heterogêneo também se faz necessário acessar
individualmente seus elementos.
477
Veremos sua utilização no exemplo a seguir.
#include <stdio.h> #include <string.h> /*aqui entrariam
as declarações das struct’s vistas anteriormente na sequência
correta*/ int main () {
struct ficha_pessoal ficha; strcpy (ficha.nome, "Fulano de
Tal");
478
}
2. Definição de tipo
O comando typedef é utilizado para definir um novo tipo de dado.
Ele é utilizado da seguinte forma:
479
480
Exercício:
Construa um programa que manipule um vetor com 5 registros de
alunos, onde cada registro possui informações referentes ao nome,
data de nascimento, número de matricula, CPF e coeficiente de
rendimento do aluno. A manipulação do vetor deve ser feita através
das
481