Commit 5f8ec801 authored by João Denis Rodrigues's avatar João Denis Rodrigues

Merge branch 'master' of gitlab.c3sl.ufpr.br:pet/apostila_c

parents 6ac003c4 1bdd7022
......@@ -2,232 +2,116 @@
\begin{document}
Recursividade
Recursividade é uma t'ecnica de programação que envolve utilizar defini,cões recursivas de modo a simplificar vários algoritmos.
\chapter{RECURSIVIDADE}
Uma definição recursiva é uma defini,c~ao que utiliza a si mesmo para se definir. A princípio, a id'eia
\emph{Recursividade} é uma técnica de programação que envolve utilizar definições recursivas de modo a simplificar vários algoritmos.
Uma definição recursiva é uma definição que utiliza a si mesma para se definir. A princípio, a ideia
pode parecer confusa e obscura, mas na realidade é um conceito relativamente simples.
Por exemplo, é possível definir uma exponenciação dessa maneira:
Seja n, k 2 N,
n
0
= 1
n
k
= n:n
k\Gamma 1
Observe que, no exemplo acima, a exponenciação nk está sendo definida através de uma outra exponencia,c~ao (n
k\Gamma 1
), ou seja, este é um caso em que a exponenciação 'e definida atrav'es dela mesma (o que
é uma definição recursiva ou tamb'em chamada de recorr^encia).
Analisando um pouco melhor o exemplo acima, n
k\Gamma 1
também 'e uma exponenciação, portanto poderia
utilizar a mesma definição para se definir, ou seja, se tomamos n
k\Gamma 1
= n:n
k\Gamma 2
ê assim podemos definir
n
k\Gamma 2
, nk \Gamma 3, etc.
Note que deveria haver um momento em que a definição termina, pois sen~ao seria impossível calcular
n
k
. Por isso, toda definição recursiva deve ser acompanhada de um caso trivial que será o final da
definição. No exemplo apresentado, n
0
= 1 é o caso trivial e determina o final da recursividade sobre n
k
.
Assim, seria possível calcular, por exemplo 3
3
:
Seja n, k \in N,
3
n^0 = 1
3
n^k = n.n^{k-1}
= 3:3
2
Observe que, no exemplo acima, a exponenciação n^k está sendo definida através de
uma outra exponenciação (n^{k-1}), ou seja, este é um caso em que a exponenciação
é definida através dela mesma (o que é uma definição recursiva ou também chamada de recorrência).
, 3
Analisando um pouco melhor o exemplo acima, n^{k-1} também é uma exponenciação,
portanto poderia utilizar a mesma definição para se definir, ou seja, se tomamos
n^{k-1} = n.n^{k-2} e assim podemos definir, n^{k-3}, etc.
2
Note que deveria haver um momento em que a definição termina, pois senão seria
impossível calcular n^k. Por isso, toda definição recursiva deve ser acompanhada
de um caso trivial que será o final da definição. No exemplo apresentado, n^0 = 1
é o caso trivial e determina o final da recursividade sobre n^k.
= 3:3
Assim, seria possível calcular, por exemplo 3^3:
1
3^3 = 3.3^2, 3^2 = 3.3^1, 3^1=3.3^0, 3^0 = 1 \Rightarrow 3^1 = 3.1, 3^2 = 3.3, 3^3 = 3.3.3
, 3
1
= 3:3
0
, 3
0
= 1 ) 3
1
= 3 3
2
= 3:3 e 3
3
= 3:3:3
Na linguagem C, funções podem chamar a si próprias, ou seja, fun,c~oes podem ser recursivas também,
Na linguagem C, funções podem chamar a si próprias, ou seja, funções podem ser recursivas também,
já que podem ser definidas através delas mesmas.
Para uma linguagem permitir recursividade, uma função deve estar apta a chamar a si própria. Um
êxemplo clássico de recursividade em programação é a fun,c~ao que calcula o fatorial de um número.
êxemplo clássico de recursividade em programação é a função que calcula o fatorial de um número.
\begin{lstlisting}
-Exemplo 1: Duas versões de fatorial -
/* não recursiva */
/* não recursiva */
int fat (int n)
f int t, resp;
{
int t, resp;
resp = 1;
for (t = 1; t <= n; t++)
resp = resp*t;
return resp;
}
resp = 1;
for (t=1; t!=n; t++)
resp = resp*t;
return resp;
g
/* recursiva */
int fat (int n)
f int resp;
if (n!2) return 1;
resp = fat(n-1)*n;
return resp;
g
85
86 AP
^
êNDICE E. RECURSIVIDADE
O funcionamento da função fat n~ao recursiva deve estar claro. Ela usa uma repeti,c~ao come,cando
{
int resp;
if (n < 2) return 1;
resp = fat(n-1)*n;
return resp;
}
\end{lstlisting}
O funcionamento da função \emph{fat} não recursiva deve estar claro. Ela usa uma repetição começando
com 1 e terminando com o valor objetivado e multiplica progressivamente cada número pelo produto
acumulado.
A operação da fun,c~ao fat recursiva é um pouco mais complexa. Quando a fun,c~ao fat 'e chamada
com um argumento 1, a função retorna 1 (esse é o caso trivial da defini,c~ao recursiva do fatorial), caso
contrário, ela retorna o produto de fat(n-1)*n.
Para avaliar essa expressão, fat é chamada com n-1. Isso acontece at'e que n seja igual a 1, quando as
chamadas `a função come,cam a retornar. O exemplo abaixo ilustra a configura,c~ao da pilha na memória
durante cada passo da sequ^encia de execução da fun,c~ao fat(4).
)
resp/n
)
resp/n
resp/n
A operação da função fat recursiva é um pouco mais complexa. Quando a função \emph{fat} é chamada
com um argumento 1, a função retorna 1 (esse é o caso trivial da definição recursiva do fatorial), caso
contrário, ela retorna o produto de \emph{fat(n-1)*n}.
)
Para avaliar essa expressão, fat é chamada com n-1. Isso acontece até que n seja igual a 1, quando as
chamadas à função começam a retornar. O exemplo abaixo ilustra a configuração da pilha na memória
durante cada passo da sequ^encia de execução da função \emph{fat(4)}.
resp/n
resp/n
resp/n
% FIXME: Inserir a imagem
)
resp/n
resp/n
)
resp/n
)
Figura E.1: Estágios da pilha na chamada recursiva de fat(4)
Quando uma função chama a si própria, as novas variáveis locais e os par^ametros s~ao alocados na
pilha (que é uma região da memória) e o c'odigo da funç~ao 'e executado com esses novos valores a partir do
início. Uma chamada recursiva não faz uma nova cópia da funç~ao. Somente os argumentos e as variáveis
Quando uma função chama a si própria, as novas variáveis locais e os parâmetros são alocados na
pilha (que é uma região da memória) e o código da função é executado com esses novos valores a partir do
início. Uma chamada recursiva não faz uma nova cópia da função. Somente os argumentos e as variáveis
são novas.
Quando cada chamada recursiva retorna, as antigas variáveis locais e os par^ametros são removidos da
pilha e a execução recome,ca no ponto de chamada da fun,c~ao dentro da fun,c~ao.
Quando cada chamada recursiva retorna, as antigas variáveis locais e os parâmetros são removidos da
pilha e a execução recomeça no ponto de chamada da função dentro da função.
A principal vantagem das funções recursivas é que elas podem ser usadas para criar vers~oes mais claras
A principal vantagem das funções recursivas é que elas podem ser usadas para criar versões mais claras
ê mais simples de muitos algoritmos complexos do que os seus equivalentes iterativos.
Por exemplo, o algoritmo de ordenação rápida é bastante difícil de ser implementado pelo modo
iterativo. Também, alguns problemas, especialmente os relacionados com IA (intelig^encia artificial),
levam a si próprios a soluções recursivas. Finalmente, muitas defini,c~oes são naturalmente recursivas, o
que torna muito mais fácil implement'a-las utilizando recursividade.
iterativo. Também, alguns problemas, especialmente os relacionados com IA (inteligência artificial),
levam a si próprios a soluções recursivas. Finalmente, muitas definições são naturalmente recursivas, o
que torna muito mais fácil implementá-las utilizando recursividade.
Na criação de fun,cões recursivas é muito importante que seja definido um caso trivial que determina
quando a função deverá come,car a retornar valores. Se n~ao houver um caso que obrigue a fun,c~ao a parar
de chamar a si mesma, o programa certamente irá entrar estourar a pilha, j'a que a memória não é infinita.
Na criação de funções recursivas é muito importante que seja definido um caso trivial que determina
quando a função deverá começar a retornar valores. Se não houver um caso que obrigue a função a parar
de chamar a si mesma, o programa certamente irá entrar estourar a pilha, já que a memória não é infinita.
ê.1 Exercícios
\section{Exercícios}
1. Crie uma definição recursiva para as seguintes opera,cões:
1. Crie uma definição recursiva para as seguintes operações:
a) soma de dois números a e b;
b) multiplicação de dois números a e b ;
c) cálculo do n-ésimo número de uma PA de razão r;
d) cálculo do n-ésimo número de uma PG de razão q;
2. Implemente a função soma pa (int x, int r, int n) que retorna a soma dos n termos de uma PA de
2. Implemente a função soma_pa (int x, int r, int n) que retorna a soma dos n termos de uma PA de
termo inicial x e razão r.
3. Desenhe um diagrama da memória para a seguinte chamada de soma pa:
soma pa(1,3,4);
\end{document}
3. Desenhe um diagrama da memória para a seguinte chamada de soma_pa:
\begin{verbatim}
soma pa(1,3,4):
\end{verbatim}
\end{document}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment