Buscar

E-book Unidade 1

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 52 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 52 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 52 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

unidade 
1
PROGRAMAÇÃO
Laboratório de
unidade 
1
Funções e Recursividade
Prezado estudante,
Estamos começando uma unidade desta disciplina. Os textos que a compõem foram 
organizados com cuidado e atenção, para que você tenha contato com um conteúdo 
completo e atualizado tanto quanto possível. Leia com dedicação, realize as atividades e 
tire suas dúvidas com os tutores. Dessa forma, você, com certeza, alcançará os objetivos 
propostos para essa disciplina.
OBJETIVO GERAL 
Compreender os conceitos de função e procedimento bem como aplicar o conceito de 
recursão na implementação de programas em linguagem C.
OBJETIVOS ESPECÍFICOS 
• Identificar trechos de códigos que podem ser implementados através de rotinas. 
• Diferenciar variáveis globais e locais.
• Definir recursão.
• Aplicar o conceito de recursão na definição recursiva de funções.
• Identificar as características de funções recursivas 
• Reconhecer problemas que podem ser resolvidos através de soluções recursivas.
• Reconhecer a recursividade e os problemas que podem ser resolvidos por meio de 
soluções recursivas.
• Definir a construção de funções recursivas e as condições de parada.
unidade 
1
O conteúdo deste livro é 
disponibilizado por SAGAH.
Parte 1
Introdução à Modularização.
Variáveis locais Vs
Variáveis globais
LABORATÓRIO DE PROGRAMAÇÃO12
236 Algoritmos e Programação com Exemplos em Pascal e C
A arte de programar consiste na arte de organizar e dominar a complexidade dos sistemas.
— Dijkstra, 1972.
Um aspecto fundamental na programação estruturada é a decomposição de um algoritmo 
em módulos, usando a técnica denominada programação modular (Staa, 2000). O objeti-
vo da programação modular é diminuir a complexidade dos programas, usando a estratégia 
de “dividir para conquistar”: dividir problemas complexos em problemas menores.
Usando essa estratégia, um algoritmo é dividido em partes menores, chamadas de módulos. 
Cada módulo tem um único ponto de entrada, e sua execução termina em um único ponto 
de saída, contendo no seu fluxo de execução: sequências de ações (cap. 3), seleções (cap. 4) e 
iterações (cap. 5). Cada módulo é implementado por um subalgoritmo (subprograma) especí-
fico, passível de ser construído e testado de forma independente. Os diferentes subprogramas 
são posteriormente integrados em um só programa. A modularização tem o objetivo de facili-
tar a compreensão, o desenvolvimento, o teste e a manutenção dos sistemas. Programas que 
utilizam subprogramação resultam mais confiáveis e flexíveis.
Considere que o problema a ser resolvido através do computador é a solução da fórmula que 
calcula as combinações de “n” elementos tomados “p” a “p”:
Para obter o resultado dessa fórmula, por meio de um algoritmo, é necessário fazer três vezes 
o cálculo de um fatorial. O cálculo desses três fatoriais é muito semelhante, só mudando o 
valor limite de cada um. Considerando que tanto o fatorial de 0 quanto o de 1 são iguais a 1 e 
utilizando uma variável inteira contador, esses cálculos podem ser realizados pelos seguintes 
trechos de programa:
{CÁLCULO DO FATORIAL DE N}
fatorial ← 1
para contador de 2 incr 1 até n faça
fatorial ← fatorial * contador
...
{CÁLCULO DO FATORIAL DE (N-P)}
fatorial ← 1
para contador de 2 incr 1 até (n-p) faça
fatorial ← fatorial * contador
...
{CÁLCULO DO FATORIAL DE P}
fatorial ← 1
para contador de 2 incr 1 até p faça
 fatorial ← fatorial * contador
O que muda nos três casos é somente o limite superior do comando para/faça. A repeti-
ção quase igual desses códigos pode ser evitada se for definido um trecho de código inde-
pendente, denominado subprograma, em que o fatorial é calculado. Esse subprograma será 
acionado (chamado) pelo programa em execução cada vez que se quiser calcular um fatorial, 
Edelweiss_09.indd 236 12/03/14 09:02
13 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 237
informando somente para qual valor se quer que o fatorial seja calculado, conforme mostra 
a Figura 9.1.
Este capítulo discute o conceito de subprogramação, analisando dois tipos de subprogramas: 
procedimentos e funções.
9.1 conceito de subprogramação
Um subprograma (às vezes chamado de sub-rotina) consiste de um trecho de código com 
estrutura semelhante à de um programa, que é executado somente quando acionado por 
outro trecho de código. Esse acionamento costuma-se denominar chamada ao subprograma.
Um subprograma deve executar uma única tarefa, claramente definida. Um programa, ao uti-
lizar um subprograma para executar uma tarefa, não deve se preocupar em como essa tarefa 
será executada. A execução correta de um subprograma deve ser assegurada sempre que esse 
seja adequadamente chamado.
A utilização de subprogramas é uma técnica de programação que visa:
 ■ a definição de trechos de código menores, mais fáceis de serem construídos e testados;
 ■ a diminuição do tamanho dos programas, pela eliminação de redundâncias, ao evitar 
que códigos semelhantes sejam repetidos dentro de um programa;
 ■ a construção mais segura de programas complexos, pela utilização de unidades menores 
(os subprogramas) já construídas e testadas;
 ■ a reutilização de código em um programa ou em programas diferentes.
Todo subprograma é identificado através de um nome. Esse nome deve representar clara-
mente a tarefa a ser executada pelo subprograma. Por exemplo, o nome adequado para o 
subprograma da Figura 9.1 é Fatorial.
A chamada a um subprograma é feita pelo seu nome, por um comando específico ou utili-
zando diretamente seu resultado, conforme será visto mais adiante. Um mesmo subprogra-
Algoritmo Combinações
início
...
execute Fatorial (n)
...
execute Fatorial (n 
...
execute Fatorial (p)
...
fim
Fatorial (valor)
Subprograma que faz o 
cálculo do fatorial de 
“valor”
Programa principal
Subprograma
- p)
figura 9.1 Chamadas ao subprograma que calcula o fatorial.
Edelweiss_09.indd 237 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO14
238 Algoritmos e Programação com Exemplos em Pascal e C
ma pode ser chamado e executado diversas vezes, em diferentes pontos de um programa. 
Adicionalmente, um subprograma também pode conter chamadas a outros subprogramas.
9.2 implementação de chamadas a subprogramas
Quando um subprograma é chamado, o fluxo de execução do programa ou subprograma 
que o chamou é interrompido e o subprograma passa a ser executado. Terminada a execução 
do subprograma, o fluxo de execução interrompido é retomado, e o processamento segue a 
partir do ponto imediatamente após a chamada concluída. Na Figura 9.2, é mostrado, por 
meio de setas, o fluxo de execução de um programa que chama o subprograma, o qual cal-
cula o fatorial.
Como já mencionado, um subprograma pode chamar outro subprograma. A forma de exe-
cução é sempre a mesma: o que chamou fica suspenso, esperando o término da execução 
do subprograma chamado, continuando depois sua execução a partir da instrução seguinte à 
instrução de chamada do subprograma.
Na Figura 9.3 é mostrado o fluxo de controle, representado simbolicamente por meio de 
setas, entre um programa e diversos subprogramas. O programa principal, durante sua exe-
cução, chama o subprograma A, ficando suspenso à espera do final da execução de A. O 
subprograma A, por sua vez, chama o subprograma B, ficando também suspenso enquanto 
B não terminar. Em seguida, o subprograma B chama o subprograma C. Durante a execução 
de C (Figura 9.3a), o programa principal e os subprogramas A e B estão suspensos. Quando 
a execução de C termina (Figura 9.3b), o fluxo de controle retorna ao subprograma B, que é 
executado até o fim, devolvendo, então, o controle ao subprograma A. Quando esse último 
termina, devolve o controle ao programa principal, que então continua sendo executado. 
Observar que somente um dos módulos (programa principal ousubprograma) estará sendo 
executado a cada momento.
Cada vez que a execução de um código é interrompida, é necessário que os recursos locais 
(ponto em que o programa fez a chamada, valores de variáveis locais, etc.) de quem fez a 
Algoritmo Combinações
Início
...
execute Fatorial (n)
...
fim
Fatorial (valor)
Programa principal
Subprograma
figura 9.2 Fluxo de execução entre programa e subprograma.
Edelweiss_09.indd 238 12/03/14 09:02
15 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 239
chamada sejam preservados e permaneçam disponíveis até o momento em que seja possível 
retomar essa execução.
Em consequência, a implementação das sucessivas chamadas a subprogramas nas linguagens 
em discussão neste livro implica na criação, pelo sistema, de uma estrutura de pilha, para ar-
mazenamento dos elementos locais das chamadas interrompidas, assim como dos endereços 
dos pontos a partir de onde as execuções devem ser retomadas. À medida que chamadas vão 
sendo feitas e interrompidas, a pilha vai recebendo valores. Quando a condição de término 
das chamadas é atingida, progressivamente as chamadas suspensas vão sendo concluídas e 
seus elementos locais restaurados, a partir da pilha. Embora não seja usual haver limitação 
para o número de níveis de chamadas a subprogramas nas linguagens, o espaço de armaze-
namento reservado para a pilha de elementos locais é finito e, se ultrapassado, pode determi-
nar a ocorrência de erros de processamento.
A execução de um subprograma, considerando a estrutura da pilha associada, compreende 
os seguintes passos:
a início da execução – criação de elementos locais, declarados no subprograma;
b processamento – tentativa de execução do código do subprograma até o seu final. Se 
a execução for interrompida por uma chamada a um subprograma, empilhamento dos 
elementos locais e do endereço de retorno, antes de ativação de nova chamada;
Execute A
Programa 
principal
Subprograma
A
Execute B
Subprograma
B
Execute C
Subprograma
C
(a)
(b)
Execute A
Programa 
principal
Subprograma
A
Execute B
Subprograma
B
Execute C
Subprograma
C
figura 9.3 Vários níveis de chamadas a subprogramas.
Edelweiss_09.indd 239 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO16
240 Algoritmos e Programação com Exemplos em Pascal e C
c final da execução de uma chamada do subprograma – liberação das áreas de memória 
locais e retorno ao ponto de onde o subprograma foi chamado. O ponto da chamada 
pode integrar outra chamada em suspenso, que só então poderá ser concluída;
d retomada de uma execução interrompida – elementos locais são restaurados, a partir da 
pilha gerida pelo sistema, e o processamento é retomado a partir do endereço também 
retirado da pilha.
9.3 parâmetros
Os valores que um subprograma necessita receber para poder realizar sua tarefa, ou os valo-
res que produz e que devem ser visíveis externamente após concluída sua execução, devem 
ser sempre armazenados em parâmetros. Parâmetros são espaços de armazenamento que 
permitem a comunicação do subprograma com o mundo externo. No subprograma que cal-
cula o fatorial, tanto o número para o qual deve ser realizado esse cálculo, quanto o resulta-
do produzido, são valores que potencialmente devem ser armazenados em parâmetros. Um 
subprograma que não utiliza parâmetros e não utiliza informação do mundo exterior para 
seu acionamento, produzirá sempre o mesmo resultado, não importa de onde seja chamado.
9.3.1 parâmetros formais e reais
Todos os elementos utilizados em um subprograma devem ser nele declarados. As declara-
ções de parâmetros, além de nomeá-los para uso interno no subprograma, definem seu tipo. 
Os parâmetros que aparecem na declaração dos subprogramas são chamados de parâme-
tros formais porque, durante a execução, na chamada dos subprogramas, são substituídos 
por variáveis ou valores do mesmo tipo, muitas vezes com nomes totalmente diferentes.
Como exemplo, vamos considerar um subprograma que calcula o fatorial de um número:
Subprograma Fatorial
 Parâmetro: número (inteiro)
O parâmetro formal número não provoca a reserva de espaço na memória. Ele simplesmente 
indica que, ao ser chamado o subprograma Fatorial, deve ser fornecido um número inteiro 
para sua execução.
Os parâmetros utilizados na chamada de um subprograma, chamados de parâmetros reais, 
substituem os formais durante sua execução. Os parâmetros reais devem sempre concordar 
em quantidade e tipo com os respectivos parâmetros formais, na ordem em que esses foram 
definidos. Podem ser fornecidos como parâmetros reais nomes de variáveis, valores literais ou 
resultados de expressões. As variáveis utilizadas como parâmetros reais devem ter sido decla-
radas no programa que chama o subprograma.
No exemplo anterior do subprograma Fatorial, o parâmetro real que vai substituir número 
pode ser fornecido por meio de um valor literal inteiro, do conteúdo de uma variável inteira 
ou de uma expressão que resulte em um valor inteiro. Se, no programa principal, estiverem 
Edelweiss_09.indd 240 12/03/14 09:02
17 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 241
declaradas as variáveis inteiras int1 e int2, os seguintes comandos podem ser utilizados para 
chamar o subprograma Fatorial:
execute Fatorial (5)
execute Fatorial (int1)
execute Fatorial (int1 + int2)
Na primeira chamada, o parâmetro formal número é substituído pelo valor 5; na segunda 
chamada, número é substituído pela variável int1; e, na última chamada, número é substi-
tuído pelo resultado da expressão int1 + int2.
9.3.2 parâmetros de entrada e de saída
A utilização de um subprograma só é efetiva se for claramente definida a tarefa que será 
executada e qual sua interação com o programa que o acionou. Para que isso seja possível, 
é importante que toda a interação seja feita somente através dos parâmetros, identificando 
quais os parâmetros de entrada (que recebem variáveis ou valores para executar a tarefa) 
e quais os parâmetros de saída (que devolvem os valores calculados ao programa que 
acionou o subprograma).
No exemplo anterior, do subprograma que calcula o fatorial, não foi definido como o resulta-
do deveria ser devolvido ao programa. Um segundo parâmetro deve ser definido, por meio do 
qual será informado o valor calculado para o fatorial. No cabeçalho da declaração do subpro-
grama devem ser identificados os parâmetros de entrada (que recebem variáveis ou valores 
para a execução) e os de saída (que devolvem valores):
Subprograma Fatorial
 Parâmetro de entrada: número (inteiro)
 Parâmetro de saída: fat (inteiro)
As chamadas a Fatorial devem fornecer agora dois parâmetros reais, sendo o primeiro 
parâmetro o número para o qual se quer calcular o fatorial, e o segundo, o nome de uma 
variável na qual será devolvido o resultado:
execute Fatorial (4, int1)
execute Fatorial (int1 + 7, int1)
Na primeira chamada, o resultado do cálculo do fatorial de 4 é devolvido através da variável 
int1; na segunda chamada, o conteúdo da variável int1 é alterado após a execução, pas-
sando a conter o valor do fatorial do valor que armazenava anteriormente somado com a 
constante 7.
9.3.3 parâmetros por valor ou por referência
A passagem de valores a subprogramas pode acontecer por valor ou por referência.
A passagem por valor indica que somente o valor interessa ao subprograma. Se esse valor for 
passado por meio do nome de uma variável, somente o valor da variável é transferido para o 
Edelweiss_09.indd 241 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO18
242 Algoritmos e Programação com Exemplos em Pascal e C
parâmetro. Uma cópia do conteúdo da variável é carregadaem uma variável auxiliar, que será 
utilizada durante a execução do subprograma. Dessa forma, qualquer modificação no valor 
da variável auxiliar não se refletirá na variável utilizada como parâmetro real. A passagem de 
valores para parâmetros definidos por valor pode ser feita ainda por meio de um valor literal e 
do resultado de uma expressão. Na execução da chamada a um subprograma, os parâmetros 
passados por valor também são incluídos na pilha de execução, preservando seus valores para 
a continuação posterior da execução.
Na passagem de um parâmetro por referência, o endereço físico da variável utilizada como 
parâmetro real é passado ao subprograma, sendo essa variável utilizada durante a execução. 
Alterações no valor do parâmetro são feitas diretamente nessa variável. Na chamada de um 
subprograma, os parâmetros definidos por referência recebem nomes de variáveis existentes 
no programa principal. É importante observar que, na execução de uma chamada ao subpro-
grama, os parâmetros por referência não sofrem empilhamento, já que não são locais aos 
subprogramas.
No exemplo anterior do subprograma Fatorial, o primeiro parâmetro – de entrada – é pas-
sado por valor. O segundo, que devolve o valor calculado, deve ser definido por referência. 
Na pseudolinguagem, um parâmetro passado por referência é identificado pela palavra ref 
antes de seu nome:
Subprograma Fatorial
 Parâmetro de entrada: número (inteiro)
 Parâmetro de saída: ref fat (inteiro)
9.4 declarações locais e globais
Dentro de um subprograma, podem ser feitas declarações de constantes, tipo e variáveis. As 
declarações feitas internamente aos subprogramas são declarações locais ao subprograma, 
e só são visíveis dentro do subprograma. As áreas de memória associadas às variáveis locais 
são alocadas no momento em que o subprograma é acionado e são liberadas ao final de sua 
execução, quando deixam de existir. Todo esse processo de criação e destruição de variáveis 
locais ocorre novamente a cada nova chamada ao subprograma.
Como exemplo de utilização de uma variável local, será considerado um subprograma que 
permuta o conteúdo de duas variáveis inteiras. Os parâmetros formais A e B representam 
as duas variáveis e, neste exemplo, desempenham o papel tanto de parâmetros de entrada 
quanto de saída. Para fazer a permuta é necessário uma terceira variável para guardar um 
dos valores durante o processamento. Essa será definida como uma variável local, pois sua 
existência não é relevante para o programa principal:
Subprograma Permuta
{TROCA O CONTEÚDO DE DUAS VARIÁVEIS}
 Parâmetros entrada e saída: ref A, ref B (inteiro)
 Variável: aux (inteiro) {VARIÁVEL LOCAL}
Edelweiss_09.indd 242 12/03/14 09:02
19 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 243
início
 aux ← A
 A ← B
 B ← aux
fim {TrocaDois}
No fim da execução do subprograma Permuta, a variável aux é liberada e não está mais dis-
ponível.
Tipos, constantes e variáveis declarados em um programa, visíveis aos subprogramas que 
estiverem nele declarados, são consideradas declarações globais ao programa.
Embora elementos globais possam ser utilizados dentro de subprogramas, essa prática não é 
recomendável, pois dificulta o entendimento e a depuração dos códigos, podendo facilmente 
ocasionar erros. Toda interação de um subprograma com o programa que o chama, no limite 
das possibilidades de cada linguagem, deve ser feita através de parâmetros, devendo os de-
mais elementos necessários à execução de sua tarefa ser declarados localmente.
Segue um quadro resumo das características das declarações locais e globais.
Locais Globais
Declaradas internamente aos subpro-
gramas que as acessam.
Declaradas externamente aos subpro-
gramas que as acessam.
Só são reconhecidas e só podem ser 
referenciadas nos subprogramas em 
que estão declaradas.
São reconhecidas e podem ser refe-
renciadas até mesmo em subprogramas 
em que não foram declaradas.
Existem apenas enquanto os subpro-
gramas em que foram declaradas es-
tiverem em execução.
Sua existência independe dos sub-
programas que as acessam. Existem 
antes, durante e após a ativação 
deles.
Internamente a um subprograma, 
quando têm o mesmo nome que uma glo-
bal, bloqueiam o acesso à global.
9.4.1 escopo de identificadores
A possibilidade de fazer declarações em diferentes pontos de um programa (no programa 
principal e em subprogramas) requer que seja claramente identificado o escopo de cada iden-
tificador. Por escopo entende-se a área de validade de um determinado identificador. O es-
copo de um identificador é definido pela localização de sua declaração. Declarações feitas 
no programa principal valem em todo o programa, inclusive, por vezes, nos subprogramas 
que o compõem. Declarações feitas dentro de um subprograma valem somente dentro desse 
subprograma. Exemplo:
Edelweiss_09.indd 243 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO20
244 Algoritmos e Programação com Exemplos em Pascal e C
Programa Exemplo
 Variáveis:
 um (inteiro)
 dois (real)
{------------------------------------------------}
Subprograma Sub
 Parâmetro de entrada: valor (inteiro)
 Parâmetro de saída: ref result (real)
 Variáveis locais:
 loc1, loc2 (inteiro)
início
 {AQUI PODEM SER UTILIZADOS:
 – os parâmetros valor e result
 – as variáveis globais um e dois
 – as variáveis locais loc1 e loc2 }
...
fim {Sub}
{------------------------------------------------}
início
 { AQUI PODEM SER UTILIZADAS:
 – as variáveis um e dois
 – chamadas ao subprograma Sub}
fim {PROGRAMA PRINCIPAL}
Nas declarações feitas dentro dos subprogramas, podem ser utilizados nomes iguais a outros 
elementos (constantes, tipos ou variáveis) já existentes no programa principal. No exemplo a 
seguir, no programa principal é declarada uma variável item, do tipo inteiro. No subprogra-
ma, é definida uma variável local com o mesmo nome (item), do tipo caractere. Dentro do 
subprograma, qualquer referência ao identificador item se refere à variável local, ficando a 
global de mesmo nome inacessível.
Programa Exemplo
 Variáveis:
 item (inteiro)
 glob (real)
{------------------------------------------------}
Subprograma Sub
 Parâmetro de entrada: valor (inteiro)
 Parâmetro de saída: ref result (real)
 Variável local:
 item (caractere)
início
 {AQUI PODEM SER UTILIZADOS:
Edelweiss_09.indd 244 12/03/14 09:02
21 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 245
 – os parâmetros valor e result
 – a variável global glob
 – a variável local item (caractere) }
...
fim {Sub}
{------------------------------------------------}
início
 { AQUI PODEM SER UTILIZADAS:
 – as variáveis item (inteiro) e glob
 – chamadas ao subprograma Sub}
fim {PROGRAMA PRINCIPAL}
O escopo dos identificadores deve ser atentamente observado quando existirem declarações 
de subprogramas dentro de subprogramas, todos com declarações locais. A Figura 9.4 
mostra graficamente essa situação, considerando um programa principal dentro do qual 
está declarado um subprograma A. Dentro do subprograma A, está declarado outro sub-
programa B. À direita na figura estão representadas as variáveis que podem ser utilizadas 
por comandos dentro de cada um desses blocos – programa principal, subprograma A e 
subprograma B.
Programa
principal 
Subprograma A
Subprograma B
Variáveis
pp1, pp2
Variáveis
a1, a2, a3
Variáveis
b1, b2
< comandos de A >
< comandos de B >
< comandos do
Programa principal > 
pp1,
pp2 
pp1, pp2,
a1, a2, a3 
pp1, pp2, a1, a2,
a3, b1, b2 
figura 9.4 Escopo dos identificadores.
Edelweiss_09.indd 245 12/03/14 09:02
LABORATÓRIODE PROGRAMAÇÃO22
246 Algoritmos e Programação com Exemplos em Pascal e C
Cabe lembrar mais uma vez que não é aconselhável utilizar variáveis globais dentro dos sub-
programas. Sempre que possível, toda a comunicação dos subprogramas com os programas 
que os acionam deverá ser feita através de parâmetros.
9.5 tipos de subprogramas
Dois tipos de subprogramas podem ser utilizados, diferenciados pela forma como são aciona-
dos e o modo como devolvem seus resultados: procedimentos e funções.
9.5.1 procedimentos
Um procedimento é um subprograma que executa uma determinada tarefa com ou sem 
a utilização de parâmetros. Na pseudolinguagem, a declaração de um procedimento é feita 
como segue:
Procedimento <nome do procedimento>
{ <Descrição da tarefa executada pelo procedimento> }
 <Lista de parâmetros formais, cada um com seu tipo,
 identificando os de entrada e os de saída>
 <Lista de constantes, tipos e variáveis locais>
início
 <Comandos do procedimento>
fim {<nome do procedimento>}
Na lista de parâmetros formais, os parâmetros por referência devem ser identificados 
pela sigla ref antes do seu nome. Os parâmetros de saída devem sempre ser definidos por 
referência.
Por exemplo, a declaração de um procedimento que calcula o fatorial de um número é:
Procedimento Fatorial
{CALCULA O FATORIAL DE UM NÚMERO}
 Parâmetro entrada: número (inteiro)
 Parâmetro de saída: ref fat (inteiro)
 Variável local: contador (inteiro)
início
 fat ← 1
 para contador de 1 incr 1 até número faça
 fat ← fat * contador
fim {Fatorial}
Os procedimentos são acionados por meio de um comando especial. Na pseudolinguagem, 
esse comando é:
execute <nome do procedimento> (< lista de parâmetros reais >)
Edelweiss_09.indd 246 12/03/14 09:02
23 Funções e Recursividade UNIDADE 1 Introdução à Modularização. Variáveis locais Vs Variáveis globais PARTE 1
Capítulo 9 Subprogramas 247
Na chamada ao procedimento Fatorial, devem ser fornecidos dois parâmetros: o primeiro 
deve ser o valor para o qual se quer calcular o fatorial, que pode ser um valor literal, o con-
teúdo de uma variável ou o resultado de uma expressão aritmética; o segundo deve ser o 
nome da variável na qual será devolvido o resultado do cálculo efetuado.
Se a1, a2 e a3 forem variáveis inteiras, podem ser feitas as seguintes chamadas ao procedi-
mento Fatorial:
execute Fatorial (a1, a2) {a2 DEVOLVE FATORIAL DE a1}
execute Fatorial (a2, a3) {a3 DEVOLVE FATORIAL DE a2}
execute Fatorial (7, a2) {a2 DEVOLVE FATORIAL DE 7}
execute Fatorial (a1+2,a3){a3 DEVOLVE FATORIAL DE (a1+2)}
9.5.2 funções
Uma função é um subprograma que devolve um valor, resultante de um cálculo ou da exe-
cução de uma determinada tarefa, ao programa que o chamou por meio de seu nome. Uma 
função tem sempre associado a ela um tipo, que é o tipo do valor que ela devolve.
Na pseudolinguagem, a declaração de uma função é feita como segue:
Função <nome da função> : <tipo do resultado>
{ <Descrição do que é calculado pela função> }
 <Lista de parâmetros formais, cada um com seu tipo>
 <Lista de constantes, tipos e variáveis locais>
início
 <Comandos>
fim {<nome da função>}
Em algum lugar do corpo da função, o valor calculado pela função deve ser atribuído ao seu 
nome, para ser devolvido ao programa que a chamou. O nome da função deve, portanto, 
aparecer pelo menos uma vez, no corpo da função, à esquerda de uma atribuição:
<nome da função > ← <valor|variável|expressão|função|constante>
Uma função não é chamada através de um comando especial, como no caso dos procedi-
mentos. A chamada é feita escrevendo seu nome, com os parâmetros reais, no ponto do có-
digo onde se deseja que o seu valor seja utilizado. Como exemplo, segue o cálculo do fatorial 
feito por meio de uma função e não de um procedimento, como mostrado na seção anterior:
Função Fatorial: inteiro
{CALCULA O FATORIAL DE UM VALOR INTEIRO}
 Parâmetro de entrada:
 número (inteiro) {NÚMERO PARA O QUAL SE QUER O FATORIAL}
 Variáveis locais:
 índice (inteiro)
 fat (inteiro)
início
Edelweiss_09.indd 247 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO24
248 Algoritmos e Programação com Exemplos em Pascal e C
 fat ← 1
 para índice de 1 incr 1 até número faça
 fat ← fat * índice
 Fatorial ← fat {DEVOLUÇÃO DE UM VALOR PELA FUNÇÃO}
fim {Fatorial}
Sendo fat1, n, p e comb variáveis inteiras, as chamadas à função Fatorial a seguir são válidas:
fat1 ← Fatorial(7) {fat1 RECEBE O VALOR DO FATORIAL DE 7}
escrever (Fatorial(n)) {INFORMA FATORIAL DO VALOR CONTIDO EM n}
comb ← Fatorial(n) / (Fatorial (n-p) * Fatorial(p))
 {comb RECEBE CÁCULO DAS COMBINAÇÕES DE n ELEMENTOS p A p}
A execução de uma função termina quando seu final lógico é encontrado, ou seja, quando 
a execução atinge o ponto final da função. No caso da função Fatorial, por exemplo, isso 
ocorre quando fim {Fatorial}é atingido.
Embora, pelo conceito fundamental de função, deva ser devolvido somente um valor por 
meio de seu nome, sintaticamente parâmetros de saída também podem ser utilizados, devol-
vendo também valores ao programa que a aciona. Essa prática não é aconselhada porque, 
além de contrariar o conceito de função, torna os códigos mais complexos, favorecendo a 
ocorrência de erros. Assim, aconselha-se: sempre que uma função for utilizada, devolver ape-
nas o valor em seu nome.
As chamadas a funções podem ocorrer em qualquer ponto do código em que o uso de um 
valor seja sintaticamente correto. Isso significa que funções podem ser usadas, por exemplo, 
em atribuições, em expressões, em comandos de saída, na chamada de outras funções e em 
testes.
9.6 refinamentos sucessivos e programação modular
O uso de subprogramação com o objetivo de facilitar a construção de programas deve ser 
feito seguindo técnicas apropriadas, de acordo com a programação estruturada, conforme 
visto na Seção 1.4, no Capítulo 1.
Uma das técnicas aconselhadas pela programação estruturada é o desenvolvimento de al-
goritmos por fases ou refinamentos sucessivos. Isso é feito concentrando-se inicialmente nas 
tarefas maiores a serem executadas e no fluxo de controle entre elas. Uma vez essa fase es-
tando bem definida, cada uma das tarefas identificadas é então refinada gradualmente, até 
que se chegue aos algoritmos finais que podem ser codificados em alguma linguagem de 
programação.
Essa técnica, também denominada top down, traz como consequência uma maior clareza no 
entendimento do problema como um todo, por não considerar inicialmente detalhes de im-
plementação. Gera, também, uma documentação mais clara e compreensível dos algoritmos.
Edelweiss_09.indd 248 12/03/14 09:02
LABORATÓRIO DE PROGRAMAÇÃO26
ENCERRA AQUI O TRECHO DO LIVRO DISPONIBILIZADO 
PELA SAGAH PARA ESTA PARTE DA UNIDADE.
PREZADO ESTUDANTE
unidade 
1
O conteúdo deste livro é 
disponibilizado por SAGAH.
Parte 2
Recursão
LABORATÓRIO DE PROGRAMAÇÃO 28
Recursão
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
 � Definir recursão.
 � Aplicar o conceito de recursão na definição recursiva de funções.
 � Implementar a solução de problemas por meio da recursão.
Introdução
Neste capítulo, aprofundaremos os conhecimentos sobre recursão. 
Verificaremos que há uma relação bem próxima entre indução e recursão. 
Como exemplo, pode-se pensar em quando definimos uma sequência 
recursivamente, especificando como os seus termos são encontrados a 
partir de termos anteriores, e podemos usar a indução para demonstrar 
os resultados dessa sequência. A indução matemática pode ser utilizada 
para demonstrar diversos resultados. Além de recursão ser um conceito 
próximo ao de indução, é de fundamental importância para a ciência 
da computação.
Além disso, quase a totalidade das linguagens de programação 
modernas possui recursão como um construtor básico de programas. 
A maioria dos computadores atuaisconta com facilidades para implemen-
tar recursão, o que faz com que o processamento de recursão alcance 
bons níveis de eficiência.
Neste capítulo, você encontrará conceitos teóricos, teoremas e defi-
nições, e, ao mesmo tempo, serão fornecidos exemplos ilustrativos com 
a finalidade de auxiliar na compreensão do tema em estudo e ampliar 
seus conhecimentos.
29 Funções e Recursividade UNIDADE 1 Recursão PARTE 2
1 Indução e recursão
Para explicar o conceito de indução, Rosen (2009) utiliza o exemplo de uma 
escada infinita. A ideia é verificar se podemos alcançar todos os degraus dessa 
escada. Sabemos duas coisas:
1. podemos alcançar o primeiro degrau da escada;
2. se pudermos alcançar um determinado degrau da escada, então pode-
remos alcançar o próximo degrau. 
Sabemos que, por (1), podemos alcançar o primeiro degrau da escada. Além 
disso, como é possível alcançar o primeiro, por (2), podemos também alcançar 
o segundo degrau, que é o próximo degrau depois do primeiro. Aplicando 
(2) outra vez, como podemos alcançar o segundo degrau, podemos também 
alcançar o terceiro. Continuamos assim e podemos mostrar que será possível 
alcançar o quarto, o quinto degrau, e assim por diante. Depois de usar 100 
vezes (2), sabemos que poderemos alcançar o 101º degrau. Dessa maneira, é 
possível concluir que podemos alcançar todos os degraus dessa escada infi-
nita. Essa verificação também pode ser realizada utilizando uma importante 
técnica de demonstração, chamada de indução matemática. Ou seja, podemos 
mostrar que P(n) é verdadeira para todo número inteiro positivo n, em que 
P(n) é a proposição que afirma que podemos alcançar o n-ésimo degrau da 
escada (ROSEN, 2009).
Rosen (2009) explica que, de modo geral, a indução matemática pode ser 
utilizada para demonstrar proposições que afirmam que P(n) é verdadeira para 
todos os números inteiros positivos n, em que P(n) é uma função proposicional. 
A demonstração é dividida em duas partes, um passo base em que se mostra 
que P(1) é verdadeira, e um passo de indução, em que se mostra que para todos 
os números inteiros k, se P(k) for verdadeira, então P(k + 1) é verdadeira.
Definir um objeto explicitamente nem sempre é fácil, mas é possível 
defini-lo em termos dele próprio, esse processo é chamado de recursão. Para 
ficar mais claro, observe a Figura 1: ela é produzida recursivamente, ou seja, 
primeiro é dada uma ilustração, depois é realizado um processo de sobre-
posições de sucessivas centralizações de fotos menores sobre a ilustração 
anterior (ROSEN, 2009).
Recursão2
LABORATÓRIO DE PROGRAMAÇÃO 30
Figura 1. Uma ilustração definida recursivamente.
Fonte: Rosen (2009, p. 295).
A recursão pode ser usada para definir sequências, funções e conjuntos. 
Podemos pensar em uma sequência que usa uma fórmula explícita, por exemplo, 
a sequência de potências de 2 que é dada por an = 2
n para n = 0,1,2,… Entre-
tanto, essa sequência pode também ser definida a partir do primeiro termo da 
sequência, a0 = 1, e de uma regra para encontrar um termo a partir do anterior, 
an+1 = 2an para n = 0,1,2,… Quando definimos uma sequência recursivamente, 
especificando como os seus termos são encontrados a partir de termos ante-
riores, podemos usar a indução para demonstrar os resultados da sequência. 
Nota-se aqui a relação existente entre indução e recursão (ROSEN, 2009).
Neste contexto, Rosen (2009) destaca que podemos definir um conjunto 
recursivamente, especificando alguns elementos iniciais em um passo e forne-
cendo uma regra para a construção de novos elementos a partir daqueles obtidos 
no passo recursivo, como vimos no caso das sequências. Para demonstrar os 
resultados de recursividade em conjuntos, utiliza-se um método chamado de 
indução estrutural, ou recursão.
3Recursão
31 Funções e Recursividade UNIDADE 1 Recursão PARTE 2
2 Definição recursiva de funções
Nesta seção veremos como as funções são definidas recursivamente. Rosen 
(2009) explica que se utilizam duas etapas para definir uma função com o 
conjunto dos números inteiros não negativos como seu domínio: passo base: 
em que se especifica o valor da função em zero; passo recursivo: em que se 
fornece uma regra para encontrar seu valor em um número inteiro a partir 
dos valores nos números inteiros menores. Essa definição é chamada de re-
cursividade ou definição indutiva. Vejamos alguns exemplos de funções que 
podem ser estudadas usando suas definições recursivas.
Confira a seguir alguns exemplos (ROSEN, 2009, p. 296–297).
Exemplo 1 — Dê uma definição recursiva da função fatorial F(n) = n!.
Solução: podemos definir a função fatorial especificando seu valor inicial, ou seja, F(0) = 1, 
e dando uma regra para encontrar F(n + 1) a partir de F(n). Isso é obtido notando que 
(n + 1)! é computado a partir de n! multiplicado por n + 1. Assim, a regra desejada é:
F(n + 1) = (n + 1)F(n)
Exemplo 2 — Determine um valor de uma função fatorial, tal como F(5) = 5! a partir 
da definição recursiva F(n + 1) = (n + 1)F(n).
Solução: neste caso é necessário usar a regra que mostra como expressar F(n + 1) 
em termos de F(n):
F(5) = 5F(4) = 5 · 4F(3) = 5 · 4 · 3F(2) = 5 . 4 . 3 . 2F(1) = 5 . 4 . 3 . 2 . 1 . F(0) 
= 5 · 4 · 3 · 2 · 1 · 1 = 120
Exemplo 3 — Dê uma definição recursiva de an, em que a é um número real diferente 
de zero e n é um número inteiro não negativo.
Solução: a definição recursiva contém duas partes. Primeiro a0 é determinado, ou 
seja, a0 = 1. Então, é dada a regra para encontrar an+1 a partir de an, ou seja, an+1 = a · 
an, para n = 0,1, 2, 3, … Estas duas equações definem unicamente an para todos os 
números inteiros não negativos n.
Recursão4
LABORATÓRIO DE PROGRAMAÇÃO 32
Exemplo 4 — Dê uma definição recursiva de ∑nk=0 ak.
Solução: a primeira parte da definição recursiva é:
A segunda parte é:
Rosen (2009) afirma que as funções definidas recursivamente são bem 
definidas, isso significa que para todo número inteiro positivo, o valor da 
função neste inteiro é determinado de forma não ambígua. Ou seja, com 
qualquer número inteiro positivo, é possível usar as duas partes da definição 
para encontrar o valor da função naquele inteiro, e significa que obtemos o 
mesmo valor, não importando como aplicamos as duas partes da definição.
Para a ciência da computação, o estudo das funções recursivas e da re-
cursão em geral é de fundamental importância. Ela permite que uma simples 
função represente um algoritmo consideravelmente complexo. Além disso, em 
muitas instituições de ensino, linguagens baseadas em funções recursivas são 
usadas como uma primeira linguagem de programação, sendo que as funções 
recursivas, em particular o cálculo do lambda, possuem importantes aplicações 
em outros contextos da ciência da computação, como por exemplo, lógica e 
linguagens de programação (MENEZES, 2013). Vejamos um exemplo para o 
entendimento da recursão de uma linguagem de programação.
5Recursão
33 Funções e Recursividade UNIDADE 1 Recursão PARTE 2
Definição indutiva: fatorial
Para um dado número natural n, define-se o fatorial n! como segue:
n! = 1, se n = 0
n! = n * (n – 1) ∙ (n – 2) ... * 1, se n > 0
Para o caso n > 0, observe que n! pode ser reescrito como segue:
n * (n – 1)!
Sendo que:
(n – 1)! = (n – 1) * (n – 2) ... * 1
Da mesma forma, (n – 1)! pode ser reescrito como segue:
(n – 1) * (n – 2)!
Sendo que:
(n – 2)! = (n – 2) * (n – 3) * ... *1
E assim sucessivamente. Portanto, o fatorial de um número n pode ser determinado 
multiplicando n pelo fatorial de seu antecessor n – 1. Tal raciocínio pode ser recursiva-
mente aplicado até chegar ao fatorial de zero. Logo, a função fatorial pode ser definida 
em termos dela mesma, até atingir o fatorial de zero, como segue.
a) Base de indução:
0! = 1
b) Passo de indução:
n! = n * (n – 1)!
Exemplificando, o cálculo do fatorial de 4 é como segue:
4! = 4 * (4 – 1)! = 4 * 3! = passo de indução
4 * 3 * (3 – 1)! = 4 * 3 * 2! = passo de indução
4 * 3 * 2 * (2 – 1)! = 4 * 3 *2 * 1! = passo de indução
4 * 3 * 2 * 1 * (1 – 1)! = 4 * 3 * 2 * 1 * 0! = base de indução
4 * 3 * 2 * 1 * 1 = 24
O mesmo princípio pode ser adotado nas linguagens de programação, usando 
o conceito de recursão, ou seja, o de uma função definida em termos dela mesma. 
Essa definição pode ser direta (uma função referencia a si mesma) ou indireta (uma 
função referencia outra função que, por sua vez, direta ou indiretamente, referencia 
a primeira) (MENEZES, 2013, p. 216–217).
Recursão6
LABORATÓRIO DE PROGRAMAÇÃO 34
Outro ponto importante a destacar é que em algumas definições recursivas 
de funções, os valores da função dos primeiros k números inteiros positivos 
são especificados e uma regra é dada para determinar o valor da função para 
números inteiros maiores a partir de seus valores para alguns ou todos os k 
números inteiros precedentes (ROSEN, 2009). Vejamos a definição dos núme-
ros de Fibonacci conforme Rosen (2009, p. 297): “Os números de Fibonacci, 
f0, f1, f2, …, são definidos pelas equações f0 = 0, f1 = 1 e fn = fn–1 + fn–2 para 
n = 2, 3, 4, ...”.
Veja, a seguir, um exemplo utilizando a definição recursiva dos números 
de Fibonacci.
Confira a seguir um exemplo (ROSEN, 2009, p. 297–298).
Mostre que, sempre que n ≥ 3, fn > ∝n–2, em que ∝ = (1 + √5
–)/2.
Solução:
Podemos usar a indução completa para demonstrar esta inequação. Considere P(n) 
como a proposição de que fn > ∝n–2. Queremos mostrar que P(n) é verdadeira sempre 
que n for um número inteiro maior que ou igual a 3.
Passo base: primeiro, note que ∝ < 2 = f3, ∝2 = (3 + √5
–)/2 < 3 = f4, então, P(3) e P(4) 
são verdadeiras.
Passo de indução: assuma que P(j) seja verdadeira, ou seja, que fj > ∝n–2, para 
todos os números inteiros j com 3 ≤ j ≤ k, em que k ≥ 4. Devemos mostrar que P(k + 1) 
é verdadeira, ou seja, que fk+1 > ∝k–1. Como ∝ é uma solução de x2 – x – 1 = 0, temos 
que ∝2 = ∝ + 1. Assim,
∝k–1 = ∝2 ∙ ∝k–3 = (∝ + 1) ∝k–3 = ∝ ∙ ∝k–3 + 1 ∙ ∝k–3 = ∝k–2 + ∝k–3
Pela hipótese indutiva, se k ≥ 4, temos que:
fk–1 > ∝k–3, fk > ∝k–2
Assim, temos:
fk+1 = fk + fk–1 > ∝k–2 + ∝k–3 = ∝k–1
7Recursão
35 Funções e Recursividade UNIDADE 1 Recursão PARTE 2
Temos que P(k + 1) é verdadeira. Isso completa a demonstração.
Lembre-se: O passo de indução mostra que, sempre que k > 4, P(k + 1) é dado 
a partir da hipótese de que P(j) seja verdadeira para 3 ≤ j ≤ k. Assim, esse passo não 
mostra que P(3) → P(4). Além disso, mostramos que P(4) é verdadeira separadamente.
3 Solucionando problemas por recursão
Nesta seção veremos que algumas vezes é possível reduzir a solução de um 
problema com um determinado conjunto de valores iniciais para a solução do 
mesmo problema com valores iniciais menores. A exemplo, podemos mencionar 
o problema para encontrar o máximo divisor comum de dois números inteiros 
positivos a e b, em que b > a, que pode ser reduzido a encontrar o máximo 
divisor comum de um par de números inteiros menores, ou seja, b mod a e a, 
pois mdc (b mod a, a) = mdc (a, b), em que mod significa o resto da divisão 
inteira. Quando essa redução pode ser feita, a solução do problema original 
pode ser encontrada com uma sequência de reduções, até que o problema seja 
reduzido ao caso inicial para qualquer solução conhecida. Para encontrar o 
máximo divisor comum, por exemplo, a redução continua até que o menor dos 
dois números seja zero, porque mdc (a, 0) = a quando a > 0 (ROSEN, 2009).
A seguir, veremos os algoritmos que reduzem sucessivamente um problema 
ao mesmo problema com valores iniciais menores, usados para a resolução de 
vários problemas. Para isso, precisamos conhecer a definição que diz que um 
algoritmo é chamado de recursivo se resolver um problema reduzindo-o a um 
mesmo problema com valores iniciais menores (ROSEN, 2009).
Recursão8
LABORATÓRIO DE PROGRAMAÇÃO 36
Os exemplos a seguir foram propostos por Rosen (2009, p. 312–314).sss
Exemplo 1 — Dê um algoritmo recursivo para computar an, em que a é um número 
real diferente de zero e n é um número inteiro não negativo.
Solução: podemos basear um algoritmo recursivo em uma definição recursiva de 
an. Essa definição afirma que an+1 = a ∙ an para n > 0 e a condição inicial a0 = 1. Para 
encontrar an, usamos sucessivamente o passo recursivo para reduzir o expoente até 
que ele se torne zero, como mostra o procedimento a seguir.
Um algoritmo recursivo para computar an
procedure potencia (a: número diferente de zero, n: número inteiro não negativo)
if n = 0 then potencia (a,n) := 1
else potencia (a,n) := a ∙ potencia (a, n – 1)
Exemplo 2 — Construa um algoritmo recursivo para computar bn mod m, em que b, 
n e m são números inteiros com m ≥ 2, n ≥ 0 e 1 ≤ b < m.
Solução: podemos basear um algoritmo recursivo no fato de que: 
bn mod m = (b ∙ (bn–1 mod m)) mod m
que é mantido com a condição inicial b0 mod m = 1. Entretanto, podemos construir 
algoritmos recursivos muito mais eficientes com base na observação de que: 
bn mod m = (bn/2 mod m)2 mod m
Quando n é par e: 
Quando n é ímpar, como vemos em pseudocódigo no algoritmo a seguir.
Potenciação modular recursiva
procedure mpotencia (b,n,m: números inteiros com m ≥ 2, n ≥ 0)
if n = 0 then 
mpotencia(b,n,m) = 1
9Recursão
37 Funções e Recursividade UNIDADE 1 Recursão PARTE 2
else if n é par then
mpotencia(b,n,m) = mpotencia(b, n/2,m)
2 mod m
else
mpotencia(b,n,m) = (mpotencia (mpotencia(b, |n/2|, m)2 mod m ∙ b mod m) mod m
{mpotencia(b,n,m) = bn mod m}
Podemos rascunhar o algoritmo com a entrada b = 2, n = 5 e m = 3 para ilustrar como 
ele funciona. Primeiro, como n = 5 é ímpar, usamos a cláusula “else” para estabelecer que:
mpotencia(2,5,3) = (mpotencia(2,2,3)2 mod 3 ∙ 2 mod 3) mod 3
Depois, usamos a cláusula “else if” para ver mpotencia(2,2,3) = mpotencia(2,1,3)2 
mod 3. Usando novamente “else”, vemos que:
mpotencia(2,1,3) = (mpotencia(2,0,3)2 mod 3 ∙ 2 mod 3) mod 3
Por fim, usamos a sentença “if”, para ver que mpotencia(2,0,3) = 1. Assim, temos que:
mpotencia(2,1,3) = 12 mod 3 ∙ 2 mod 3) mod 3 = 2
Então mpotencia (2,2,3) = 22 mod 3 = 1 e finalmente, mpotencia(2,5,3) = (12 mod 3 
∙ 2 mod 3) mod 3 = 2.
Exemplo 3 — Dê um algoritmo recursivo para computar o máximo divisor comum 
de dois números inteiros não negativos a e b com a < b.
Solução: podemos basear um algoritmo recursivo na redução mdc(a,b) = mdc(b 
mod a,a) e na condição que mdc(0,b) = b quando b > 0. Ilustramos o funcionamento 
do algoritmo calculando-o quando as entradas são a = 5, b = 8. Com essas entradas, o 
algoritmo usa a sentença “else” para encontrar mdc(5,8) = mdc(8 mod 5,5) = mdc(3,5). 
Ele usa esta sentença novamente para encontrar mdc(3,5) = mdc(5 mod 3,3) = mdc(2,3), 
então para ter mdc(2,3) = mdc(3 mod 2,2) = mdc(1,2), então para ter mdc(1,2) = mdc(2 
mod 1,1) = mdc(0,1). Por fim, para encontrar mdc(0,1) ele usa o primeiro passo com a = 
0 para encontrar mdc(0,1) = 1. Consequentemente, o algoritmo encontra mdc(5,8) = 1.
Um algoritmo recursivo para computar mdc(a,b):
procedure mdc(a,b: números inteiros não negativoscom a < b)
if a = 0 then mdc(a,b) ≔ b
else mdc(a,b) := mdc(b mod a,a)
Recursão10
LABORATÓRIO DE PROGRAMAÇÃO 38
ENCERRA AQUI O TRECHO DO LIVRO DISPONIBILIZADO 
PELA SAGAH PARA ESTA PARTE DA UNIDADE.
PREZADO ESTUDANTE
MENEZES, P. B. Matemática discreta para computação e informática. 4. ed. Porto Alegre: 
Bookman, 2013. (Livros didáticos informática UFRGS, v. 16).
ROSEN, K. H. Matemática discreta e suas aplicações. 6. ed. Porto Alegre: AMGH, 2009.
11Recursão
unidade 
1
O conteúdo deste livro é 
disponibilizado por SAGAH.
Parte 3
Recursividade
LABORATÓRIO DE PROGRAMAÇÃO 40
418 Algoritmos e Programação com Exemplos em Pascal e C
Este capítulo discute a implementação de soluções para problemas utilizando a ativação de 
subprogramas de forma recursiva, ou seja, fazendo os subprogramas chamarem a si mesmos. 
A utilização de recursividade é apropriada para o processamento com determinadas estrutu-
ras de dados.
15.1 conceito de recursividade
Um problema é dito recursivo se é definível em termos de si mesmo. Um exemplo disso é a 
definição dos números naturais:
 ■ o primeiro número natural é zero;
 ■ o sucessor de um número natural é um número natural.
Diversas situações do nosso dia a dia podem ser definidas recursivamente. A seguir, são anali-
sados dois casos muito comuns em que a recursividade é tratada naturalmente.
ler um livro. Um livro normalmente é dividido em capítulos. A leitura de um livro consiste 
em ler o primeiro capítulo e, depois, repetir o processo para ler o restante do livro. O restan-
te do livro tem a mesma estrutura do livro original, sem o capítulo lido, podendo ser tam-
bém encarado como um livro. Se o livro tem 12 capítulos, o processo inicia com a leitura 
do capítulo 1, seguida da leitura do restante do livro, ou seja, dos 11 capítulos restantes. A 
leitura desses 11 capítulos, por sua vez, consiste em ler o primeiro (no caso, o capítulo 2) 
e seguir lendo os 10 capítulos restantes. O processo recursivo se repete até que seja lido o 
último capítulo, ou seja, até não existir o “restante do livro”. Então, a definição recursiva da 
leitura de um livro é:
 ■ ler o primeiro capítulo;
 ■ se houver capítulos depois dele, lê-los.
fila de pessoas no caixa de uma loja. No caixa de uma loja, é atendida em primeiro lugar 
a pessoa que está no início da fila. Uma vez terminado o atendimento, essa pessoa sai da fila 
e a que estava em segundo lugar passa a encabeçar a fila das restantes. As pessoas que estão 
atrás da pessoa atendida também estão formando uma fila. O processo é então repetido para 
a fila restante até que a última pessoa seja atendida. Assim, o atendimento das pessoas de 
uma fila é como segue:
 ■ atender a primeira pessoa da fila;
 ■ se houver alguém atrás da primeira pessoa, repetir o processo para o restante da fila.
Nesses dois exemplos, pode ser observado que as definições recursivas são condicionadas, no 
primeiro caso, a que exista algum capítulo ainda não lido e, no segundo, a que ainda haja 
alguma pessoa na fila. Pode ser observado ainda que as condições fazem que os processos 
recursivos parem em algum momento.
Edelweiss_15.indd 418Edelweiss_15.indd 418 12/03/14 09:0012/03/14 09:00
41 Funções e Recursividade UNIDADE 1 Recursividade PARTE 3Capítulo 15 Recursividade 419
15.2 subprograma recursivo
O cálculo do fatorial de um número inteiro positivo é utilizado aqui para introduzir a utiliza-
ção de recursividade em subprogramas. Como estudado em aritmética, o cálculo do fatorial 
de um número n, inteiro positivo, é realizado por sucessivas multiplicações:
n! = n · (n-1) · (n-2) · ... · 3 · 2 · 1
Esse cálculo pode ser efetuado por meio de uma função, passando o número para o qual se 
quer calcular o fatorial como parâmetro. Na função Fat, a seguir, o fatorial é calculado por 
meio de um comando de repetição que acumula as multiplicações sucessivas necessárias ao 
cálculo.
Função Fat: inteiro
{CALCULA O FATORIAL DE UM INTEIRO N, PASSADO COMO PARÂMETRO}
 Parâmetro de entrada: N (inteiro)
 Variáveis locais:
 número (inteiro) {USADO COMO ÍNDICE PARA AS REPETIÇÕES}
 val_fat (inteiro) {VALOR CALCULADO POR MEIO DE
 MULTIPLICAÇÕES SUCESSIVAS}
início
 val_fat ← 1 {INICIALIZA ACUMULADOR DE PRODUTOS}
 {REPETIÇÕES NAS QUAIS O FATORIAL É CALCULADO}
 para número de N incr -1 até 1 faça
 val_fat ← val_fat * número
 {VALOR CALCULADO É DEVOLVIDO POR MEIO DO NOME DA FUNÇÃO}
 Fat ← val_fat
fim {Fatorial}
Caso o parâmetro passado seja 3, a função efetua o cálculo de 3! da seguinte maneira:
3! = 3 * 2 * 1
Analisando esse exemplo mais detalhadamente, observa-se que, como o fatorial de 2 é dado 
por 2 * 1, o cálculo do fatorial de 3 também pode ser expresso como:
3! = 3 * 2!
De forma análoga, tem-se que:
2! = 2 * 1!
1! = 1 * 0!
Por definição, o fatorial de zero é 1.
Edelweiss_15.indd 419Edelweiss_15.indd 419 12/03/14 09:0012/03/14 09:00
LABORATÓRIO DE PROGRAMAÇÃO 42 420 Algoritmos e Programação com Exemplos em Pascal e C
Assim, o cálculo do fatorial de um número inteiro N pode ser realizado com base na seguinte 
definição recursiva:
se N = 0 então fatorial(N) = 1
se N > 0 então fatorial(N) = N * fatorial(N-1)
A função recursiva Fatorial, a seguir, implementa essa definição. É uma função recursiva 
porque no seu código há uma chamada para ela mesma.
Função Fatorial: inteiro
{CALCULA O FATORIAL DE UM INTEIRO N, PASSADO COMO PARÂMETRO, DE FORMA 
RECURSIVA}
 Parâmetro de entrada: N (inteiro)
início
 se N = 0
 então Fatorial ← 1
 senão Fatorial ← N * Fatorial (N-1)
fim {Fatorial}
15.3 implementação de subprogramas recursivos
Na função mostrada na seção anterior, a chamada à função Fatorial(N-1) é o que se de-
nomina chamada recursiva, ou seja, é uma chamada da função a si mesma. Conforme visto 
no Capítulo 9, o programa ou subprograma que faz uma chamada a outro subprograma fica 
com sua execução suspensa até que termine a execução do subprograma acionado. Quando 
isso acontece, a execução do programa ou subprograma que chamou é retomada a partir do 
ponto em que foi feita a chamada. O mesmo acontece quando a chamada for recursiva: o 
subprograma que faz uma chamada recursiva é suspenso e é iniciada uma nova execução do 
mesmo subprograma de forma totalmente independente. Caso o subprograma possua variá-
veis locais, aí incluídos os parâmetros passados por valor, são alocadas novas variáveis, que 
existirão somente durante essa nova execução. Somente quando o subprograma acionado na 
chamada recursiva terminar sua execução é que o anterior retoma sua execução.
A implementação de chamadas recursivas segue o mesmo mecanismo das chamadas a sub-
programas apresentado na Seção 9.2, mesmo quando o subprograma chamado é o mesmo 
que faz a chamada. A cada chamada recursiva, os recursos locais deverão ser preservados, 
desde o momento em que sua execução é interrompida até o momento em que seja possível 
retomar essa execução para tentar concluí-la, quando então esses recursos locais deverão 
novamente ficar disponíveis. A implementação é feita por meio de uma estrutura de pilha, 
em que vão sendo colocados os elementos locais das chamadas interrompidas, bem como os 
endereços dos pontos a partir de onde as execuções dos subprogramas devem ser retomadas 
para serem concluídas. À medida que as execuções vão sendo concluídas, os elementos locais 
vão sendo restaurados a partir da pilha.
Quando um subprograma é chamado sucessivas vezes por si mesmo, cada nova execução 
gera uma nova entrada na pilha para armazenar seus recursos locais. É muito comum, quan-
Edelweiss_15.indd 420Edelweiss_15.indd 420 12/03/14 09:0012/03/14 09:00
43 Funções e Recursividade UNIDADE 1Recursividade PARTE 3
Capítulo 15 Recursividade 421
do utilizada recursividade, que as chamadas recursivas sejam muito numerosas, ocasionando 
falta de espaço físico para armazenar os valores das chamadas na pilha de execução, o que, 
em algumas linguagens de programação, gera uma mensagem de “stack overflow” (trans-
bordamento da pilha) e a interrupção do processo de execução.
A Figura 15.1 ilustra a execução das chamadas recursivas feitas quando é utilizada uma cha-
mada Fatorial(3). A primeira chamada resulta em três chamadas recursivas. No momen-
to da execução da última, Fatorial(0), todas as anteriores estão suspensas, esperando o 
término daquela que a chamou (Figura 15.1a). Fatorial(0) é a primeira a terminar sua 
execução, devolvendo seu resultado (1) à anterior, Fatorial(1), sendo então liberado seu 
espaço de execução (Figura 15.1b). Ao término da execução de Fatorial(1), seu resultado 
(1) é passado à anterior e seu espaço de execução é liberado (Figura 15.1c). E assim sucessi-
vamente, até que o resultado da primeira chamada seja devolvido.
parada de chamadas recursivas. Nos subprogramas recursivos sempre deve haver uma con-
dição que leve ao término da execução do subprograma. Por exemplo, seja a função a seguir:
Função X: inteiro
 Parâmetro de entrada: N (inteiro)
início
 escrever(N)
==u=← X(N-1) {CHAMADA RECURSIVA}
fim
Fatorial(2)
2*Fatorial(1)
Fatorial(1)
)c()b()a(
1*Fatorial(0)
Fatorial(0)
Fatorial(3)
3*Fatorial(2)
Fatorial(2)
2*Fatorial(1)
Fatorial(1)
1*Fatorial(0)
Fatorial(3)
3*Fatorial(2)
Fatorial(2)
2*Fatorial(1)
Fatorial(3)
3*Fatorial(2)
Fatorial(0)
Fatorial(1)
Fatorial N
Fatorial 
Fatorial 
Fatorial 
Fatorial 
Fatorial 
Fatorial 
Fatorial 
Fatorial 
figura 15.1 Chamadas recursivas no cálculo de Fatorial (3).
Edelweiss_15.indd 421 12/03/14 09:00
LABORATÓRIO DE PROGRAMAÇÃO 44 422 Algoritmos e Programação com Exemplos em Pascal e C
Observa-se que a chamada recursiva será sempre executada, fazendo que a execução nunca 
termine! A chamada recursiva sempre deve ser condicional, garantindo a finalização da exe-
cução do subprograma. No exemplo da função Fatorial, a parada das chamadas recursivas 
se dará quando o parâmetro recebido for zero.
Além de atrelar a chamada recursiva a alguma condição, todo cuidado deve ser tomado para 
que essa condição realmente se torne verdadeira em algum momento, uma vez que ela pode 
envolver valores lidos ou calculados durante o processamento. Por exemplo, as chamadas 
recursivas da função K, a seguir, jamais cessarão se a função receber, na primeira chamada, 
um parâmetro menor do que 1:
Função K: inteiro
 Parâmetro de entrada: N (inteiro)
início
 se N = 1 {CONDIÇÃO DE TÉRMINO DAS CHAMADAS RECURSIVAS}
 então K ← 1 {DEVOLVE O VALOR 1}
 senão K ← K(N-1)
fim
solução recursiva e iterativa. Duas formas foram utilizadas para solucionar o problema 
do fatorial neste livro: inicialmente, foi dada a solução utilizando um comando iterativo e, em 
seguida, a solução recursiva. É importante lembrar que todo problema passível de solução re-
cursiva pode ser resolvido também de forma iterativa, mesmo que os problemas apresentem 
claramente uma estrutura recursiva.
15.4 recursividade indireta
Existem casos em que dois subprogramas fazem chamadas recíprocas, ou seja, cada um faz 
alguma chamada ao outro – por exemplo, supondo dois subprogramas A e B, A faz uma 
chamada a B que, por sua vez, faz uma chamada a A. Essa situação caracteriza uma recursi-
vidade indireta.
Sempre que dois subprogramas apresentarem recursividade indireta, pelo menos em um de-
les a chamada ao outro deve ser condicionada a alguma situação para garantir que, em 
algum momento, as chamadas recíprocas terminem.
A declaração de um subprograma deve sempre ser feita antes de sua utilização em algum 
comando, para que o compilador consiga identificar o significado do nome do subprograma 
e para que possa ser feita a verificação dos parâmetros atuais, que devem corresponder, em 
quantidade e tipos, aos parâmetros formais. No caso citado, em que dois subprogramas se 
chamam mutuamente, não é possível declarar os dois antes de serem utilizados. Algumas 
linguagens de programação permitem informar ao compilador que a declaração de um de-
terminado subprograma será feita mais adiante, permitindo dessa maneira sua utilização 
antes da declaração. Para isso, definem somente o nome do subprograma e seus parâmetros 
Edelweiss_15.indd 422Edelweiss_15.indd 422 12/03/14 09:0012/03/14 09:00
45 Funções e Recursividade UNIDADE 1 Recursividade PARTE 3
Capítulo 15 Recursividade 423
formais (nome e tipo). Na pseudolinguagem utilizada nesse texto, a sintaxe dessa declaração 
é:
Declaração adiante : <cabeçalho da declaração do procedimento_1>
<declaração do procedimento_2>
<declaração do procedimento_1>
O exemplo a seguir ilustra a chamada recíproca de dois procedimentos. No programa princi-
pal, é lido um valor inteiro e, em seguida, chamado o procedimento A. Os dois procedimentos 
passam a se chamar mutuamente, até que o procedimento A receba um valor superior a 100 
como parâmetro, que é a condição de parada das chamadas recursivas. A Figura 15.2 ilustra a 
sequência de chamadas recursivas no caso do valor lido para a primeira chamada de A ser 97.
Subprograma A
{finaliza}
Subprograma B
execute A(101)
Subprograma A
execute B(99,2)
Subprograma B
execute A(99)
Subprograma A
execute B(97,2)
Programa principal
execute A(97)
figura 15.2 Exemplo de recursividade indireta.
Edelweiss_15.indd 423Edelweiss_15.indd 423 12/03/14 09:0012/03/14 09:00
LABORATÓRIO DE PROGRAMAÇÃO 46 424 Algoritmos e Programação com Exemplos em Pascal e C
Algoritmo ExemploMutuo
{-------------------------------------------------------------}
Declaração adiante: Procedimento B (ref v1:inteiro; v2:inteiro)
{-------------------------------------------------------------}
Procedimento A (ref x: inteiro)
início
 se x ≤ 100
 então executar B(x, 2){CHAMADA CONDICIONAL AO PROCEDIMENTO B}
fim {A}
{-------------------------------------------------------------}
Procedimento B (ref v1: inteiro; v2: inteiro)
início
 v1 ← v1 + v2
 executar A(v1) {CHAMADA AO PROCEDIMENTO A}
fim {B}
{-------------------------------------------------------------}
{DECLARAÇÃO DE VARIÁVEL GLOBAL}
 Variável: valor (inteiro)
{-------------------------------------------------------------}
início {PROGRAMA PRINCIPAL}
 ler (valor)
 executar A (valor)
 escrever (valor)
fim {PROGRAMA PRINCIPAL}
15.5 vantagens e desvantagens da recursividade
O uso da recursividade apresenta algumas vantagens:
 ■ um código recursivo é a forma mais simples e direta de solução de problemas que têm 
uma definição recursiva;
 ■ é especialmente conveniente para acessar estruturas de dados implicitamente recursivas, 
como árvores;
 ■ quando bem utilizado, facilita a compreensão da lógica do subprograma;
 ■ o código recursivo tende a ser mais enxuto que o código não recursivo.
Entretanto, sua utilização também traz algumas desvantagens:
 ■ necessidade de memória extra durante a execução das chamadas recursivas para armaze-
namento dos itens locais às chamadas e respectivos endereços de retorno;
 ■ aumento do tempo de processamento, devido ao acionamento das diversas chamadas 
recursivas;
 ■ é inviável em problemas que exijam um número muito elevado de chamadas e, consequen-
temente, um grande espaço de armazenamento para a pilha de execução.
Edelweiss_15.indd 424Edelweiss_15.indd 424 12/03/14 09:0012/03/14 09:00
47 Funções e Recursividade UNIDADE 1 RecursividadePARTE 3
Capítulo 15 Recursividade 425
Observar, portanto, que a utilização de recursividade nem sempre é apropriada, devendo 
sempre ser avaliada sua real utilidade.
15.6 exercícios de fixação
exercício 15.1 A posição em que é feita uma chamada recursiva influi diretamente nas ações 
executadas. Por exemplo, os valores apresentados são substancialmente alterados quando a 
saída de valores for feita antes ou depois de uma chamada recursiva. Neste exercício são 
mostradas duas versões para um procedimento, mudando somente o momento em que é 
mostrada uma informação.
O procedimento MostraVersão1 recebe dois parâmetros inteiros, i e n. O parâmetro i é 
alterado e o parâmetro n nunca sofre alteração.
Procedimento MostraVersão1
{CÓDIGO RECURSIVO COM COMANDO APÓS A CHAMADA}
 Parâmetros de entrada:
 i, n (inteiro)
início
 se i ≥ n
 então início
 escrever('Chamadas recursivas concluídas');
 escrever(i)
 fim
 senão início
 executar MostraVersão1 (i+2, n)
 escrever (i)
 fim
fim {MostraVersão1}
Nessa versão, o valor de i está sendo apresentado na fase do desempilhamento, ou seja, 
após a finalização da execução da chamada recursiva. Caso os parâmetros recebidos valham 
respectivamente 2 e 8, a execução desse código produzirá o seguinte resultado na tela:
Chamadas recursivas concluídas
8
6
4
2
Observar agora o código do procedimento MostraVersão2, que recebe os mesmos dois pa-
râmetros inteiros, i e n, e em que, igualmente, o parâmetro i é alterado e o parâmetro n 
nunca sofre alteração:
Procedimento MostraVersão2
{CÓDIGO RECURSIVO COM COMANDO ANTES DA CHAMADA}
Edelweiss_15.indd 425Edelweiss_15.indd 425 12/03/14 09:0012/03/14 09:00
LABORATÓRIO DE PROGRAMAÇÃO 48
ENCERRA AQUI O TRECHO DO LIVRO DISPONIBILIZADO 
PELA SAGAH PARA ESTA PARTE DA UNIDADE.
PREZADO ESTUDANTE
unidade 
1
O conteúdo deste livro é 
disponibilizado por SAGAH.
Parte 4
Recursividade em C
LABORATÓRIO DE PROGRAMAÇÃO 50
Recursividade em C
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
 � Reconhecer a recursividade e os problemas que podem ser resolvidos 
por meio de soluções recursivas.
 � Definir a construção de funções recursivas e as condições de parada.
 � Desenvolver funções recursivas.
Introdução
De modo genérico, o termo “recursividade” é utilizado para descrever o 
processo de repetição de um objeto ou evento de um modo semelhante 
ao que já tenha ocorrido. Em computação, recursão é um método de 
programação utilizado para solucionar uma classe específica de proble-
mas, dividindo-os em problemas menores de mesma natureza.
Neste capítulo, você aprenderá o conceito de recursividade e como ele 
é empregado na ciência da computação, mais especificamente na progra-
mação. Você também compreenderá melhor quais tipos de problemas 
podem ser resolvidos por meio desta técnica e entenderá a estrutura, a 
sintaxe e o funcionamento das funções recursivas. Por fim, aprenderá a 
implementar computacionalmente esse tipo de função em linguagem C. 
O que é recursividade?
As funções em linguagem C melhoram a organização do código, permitem 
a reutilização de trechos de código e evitam a repetição de comandos. Existe 
uma categoria especial de funções, denominada funções recursivas. Mas 
antes de detalhar essa técnica de programação, você aprenderá o significado 
da palavra recursão. Recursão ou recursividade é um termo usado de maneira 
genérica para descrever o processo de repetição de um objeto de modo similar 
ao que já fora mostrado. 
51 Funções e Recursividade UNIDADE 1 Recursividade em C PARTE 4
Diversas situações do seu dia a dia podem ser definidas recursivamente, 
como por exemplo, quando você lê um livro. Um livro normalmente é dividido 
em capítulos. A leitura de um livro consiste em ler o primeiro capítulo e, 
depois, repetir o processo para ler o restante do livro. Um outro exemplo é a 
fila de pessoas no caixa de uma loja. É atendida em primeiro lugar a pessoa 
que está no início da fila. Uma vez terminado o atendimento, essa pessoa sai 
da fila, e a que estava em segundo lugar passa a encabeçar a fila das restantes. 
O processo é repetido para a fila restante até que a última pessoa seja atendida 
pelo caixa. Observe, nestes dois exemplos, que existem condições que fazem 
com que os processos recursivos parem em algum momento. E isso também 
ocorre quando a recursividade é aplicada à programação.
Na ciência da computação, o conceito de recursividade está relacionado 
com o universo da programação, de onde surge uma nova técnica: as funções 
recursivas. Essa técnica é utilizada para solucionar um grupo específico de 
problemas, também com estrutura recursiva. 
Um problema é dito recursivo se é definível em termos de si mesmo. Um 
exemplo disso é a definição de números naturais (EDELWEISS; LIVI, 2014):
 � o primeiro número natural é zero;
 � o sucessor de um número natural é um número natural.
Nesta classe de problemas, um problema é dividido em subproblemas de 
mesma natureza, onde cada instância contém uma instância menor do mesmo 
problema. Na definição de números naturais, cada antecessor de um número 
natural, por exemplo o 5, é também um número natural (4, 3, 2, 1), até chegar 
ao zero (que é o primeiro número natural). 
Para resolver uma instância de um problema recursivo, você pode aplicar 
o seguinte método (FEOFILOFF, 2018):
se a instância em questão for pequena,
 resolva-a diretamente (use força bruta se necessário);
senão
 reduza-a a uma instância menor do mesmo problema,
 aplique o método à instância menor,
 volte à instância original.
Recursividade em C2
LABORATÓRIO DE PROGRAMAÇÃO 52
Logo, a solução de um problema recursivo consiste em resolver subpro-
blemas mais simples, sucessivamente, até se atingir o caso mais simples de 
todos, cujo resultado é imediato. Muitos problemas podem ser identificados e 
resolvidos assim, desde que possam ser divididos em subproblemas do mesmo 
tipo. Esse paradigma também é conhecido como divisão e conquista, e é 
empregado nos mais variados algoritmos, dentre eles: ordenação de valores, 
busca binária, programação dinâmica, etc.
Agora que você já sabe identificar quais tipos de problemas podem ser 
resolvidos por meio das funções recursivas, vamos entender mais sobre elas.
Uma função é dita recursiva quando ela chama a si mesma durante a 
execução de um programa ou algoritmo (SOFFNER, 2013). A sintaxe para 
implementação de uma função recursiva é semelhante à sintaxe para im-
plementação das funções gerais, ou seja, deverá ter um tipo de retorno, um 
nome, os parênteses e os parâmetros de entrada, quando necessário. A única 
diferença está no corpo da função, pois a função recursiva será invocada 
dentro dela mesma. A Figura 1 mostra a sintaxe de uma função recursiva. 
É possível observar a construção da função, bem como a chamada dela; 
primeiro na função principal (função main) e depois dentro dela mesma.
Figura 1. Sintaxe de uma função recursiva.
<tipo> nomeFuncaoRecursiva(){
// comandos
//comandos
//comandos
nomeFuncaoRecursiva();
}
}
void main(){
nomeFuncaoRecursiva();
Chamando a si mesma
2
1
3Recursividade em C
53 Funções e Recursividade UNIDADE 1 Recursividade em C PARTE 4
Portanto, para você criar uma função recursiva, basta fazer uma chamada 
da função dentro dela própria. Embora a sintaxe seja simples, é necessário 
que você entenda seu funcionamento e saiba quando se pode utilizar essa 
técnica, pois, se mal estruturada, a função recursiva poderá entrar em um 
laço de repetição infinito. 
Estrutura das funções recursivas
Apesar de a sintaxeda função recursiva ser similar à sintaxe das funções não 
recursivas, o funcionamento é bastante distinto, e o mau uso dessa técnica 
pode acarretar utilização indevida de memória, chegando muitas vezes a travar 
a aplicação e o sistema (MANZANO, 2015). Para que você entenda todo o 
processo de construção e funcionamento das funções recursivas, é necessário 
estabelecer alguns pontos de atenção, como os listados a seguir.
 � Ponto de parada: por definição a função recursiva chama a si mesma, 
portanto é preciso estabelecer quando parar esse laço de repetição. 
O ponto de parada poderá ser alcançado por meio de uma estrutura 
condicional ou por meio de um valor informado pelo usuário.
 � Instâncias: uma função possui em seu corpo variáveis e comandos, 
os quais são alocados na memória de trabalho. No uso de uma função 
recursiva, os recursos (variáveis e comandos) são alocados (instanciados) 
em outro local da memória; ou seja, para cada chamada da função, 
novos espaços são destinados à execução do programa. E é justamente 
devido a esse ponto que o critério de parada é crucial. 
 � Variáveis independentes: as variáveis criadas na memória em cada 
instância da função recursiva são independentes, ou seja, mesmo as 
variáveis tendo nomes iguais, cada uma tem seu próprio endereço de 
memória, de modo que a alteração do valor em uma não afetará na outra. 
Recursividade em C4
LABORATÓRIO DE PROGRAMAÇÃO 54
Para auxiliá-lo na compreensão deste esquema, observe a Figura 2.
Figura 2. Esquema de funcionamento de uma função recursiva.
Instância 1 Instância 2 Instância 3
nomeFuncaoRecursiva(){ nomeFuncaoRecursiva(){ nomeFuncaoRecursiva(){
//comandos
nomeFuncaoRecursiva();
//comandos
return valor;
//comandos
nomeFuncaoRecursiva();
//comandos
return valor;
//comandos
//ponto de parada
return valor;
} }
}
A instância 1 representa a primeira chamada da função nomeFuncaoRe-
cursiva(), que, por sua vez, possui em seu corpo um comando que invoca a si 
mesma. Neste momento é criada a segunda instância dessa função na memória 
de trabalho. Veja que um novo espaço é alocado, com variáveis e comandos, e, 
como a função é recursiva, novamente ela chama a si mesma, criando, então, 
a terceira instância. Dentro da terceira instância, uma determinada condição 
de parada é satisfeita. Neste caso a função deixa de ser instanciada e passa 
a retornar valores.
A partir do momento que a função recursiva atinge o ponto de parada, cada 
instância da função passa a retornar seus resultados para a instância anterior (a 
que fez a chamada). No caso da Figura 2, a instância 3 retornará para a 2, e a 
instância 2, para a 1. Note que, se o ponto de parada não fosse especificado na 
última chamada, a função seria instanciada até haver um estouro de memória.
Toda função recursiva precisa ter, obrigatoriamente, uma instância com um caso que 
interromperá a chamada a novas instâncias. Essa instância é chamada de caso base, 
porque representa o caso mais simples, que resultará na interrupção. 
5Recursividade em C
55 Funções e Recursividade UNIDADE 1 Recursividade em C PARTE 4
Desenvolvendo funções recursivas
Agora, você verá a implementação de uma função recursiva que faz a somatória 
dos antecessores de um número inteiro positivo. Neste programa, esse número 
deve ser informado como dado de entrada pelo usuário. 
Supondo que o usuário digite 4, então o programa deverá retornar o resul-
tado da soma 4 + 3 + 2 + 1 + 0, que é 10, como informação de saída.
A partir desse exemplo, você̂ consegue identificar qual é o ponto de parada 
da função recursiva, isto é, quando a função recursiva deverá interromper a 
execução? Pois bem, a função recursiva deverá somar os antecessores de um 
número positivo até́ o valor zero. Então, quando se “alcançar” o valor zero, 
o critério de parada da função será satisfeito. Mas veja bem: ao identificar o 
critério de parada, você também estará determinando o passo básico da solução 
do problema recursivo, cujo resultado é imediatamente conhecido. Na soma, 
há uma propriedade na qual o zero é considerado neutro. Assim, o resultado 
de um número somado com zero é o próprio número. Então este será o retorno 
da função quando a condição de parada for satisfeita. 
As demais somatórias correspondem ao passo recursivo da solução do 
problema, em que se tenta resolver um subproblema do problema inicial. Neste 
exemplo, se o valor for diferente de zero, o passo recursivo é executado; caso 
contrário, o passo básico é realizado. O passo recursivo e o passo básico são 
dados respectivamente por:
A Figura 3 mostra a implementação da solução escrita em linguagem C.
Recursividade em C6
LABORATÓRIO DE PROGRAMAÇÃO 56
Figura 3. Implementação recursiva para soma.
A execução do programa da Figura 3 inicia na linha 9, ou seja, pela fun-
ção principal. Na linha 13 a função recursiva soma() é invocada, passando 
como parâmetro o número inteiro digitado pelo usuário (n). Neste momento, 
a execução “salta” para a linha 2, onde a função recursiva soma() é criada. 
Observe que ela foi criada para retornar e receber um valor inteiro. 
Na linha 3, a estrutura condicional foi usada como critério de parada. 
Observe que, se o valor for diferente de zero (!=0), a execução do programa 
passará para a linha 4, na qual a função recursiva soma() é invocada nova-
mente, com parâmetro de valor menos 1. Caso contrário — isto é, quando o 
valor for zero —, as instâncias passam a retornar o valor para a que chamou. 
A Figura 4 exemplifica o funcionamento na memória de trabalho da função 
recursiva soma(). Neste exemplo, o usuário digitou o número 2, então a função 
main() invocará a função soma(2), criando a primeira instância e passando 
esse valor. Na primeira instância, a estrutura condicional é testada e retorna o 
valor verdadeiro, ou seja, 2 é diferente de zero. Então, o critério de parada não 
é satisfeito e a função soma() chama a si mesma criando a segunda instância. 
Agora, o valor 1 é passado como parâmetro, isto é, soma(1). 
Note que na primeira instância o valor a ser retornado é 2 + ?, pois ainda 
não se conhece o resultado da função. Na segunda instância, o valor (1) também 
é diferente de zero, portanto a função chama a si mesma novamente, agora 
passando como parâmetro 0 (1 – 1). Observe que o retorno fica como 1 + ?, 
pois também não se conhece ainda o resultado da função. 
7Recursividade em C
57 Funções e Recursividade UNIDADE 1 Recursividade em C PARTE 4
Na terceira instância o critério de parada é satisfeito. Neste caso a função 
retorna o valor 0. Esse valor será usado pela instância anterior, que, após somar 
1 + 0, retornará seu resultado para a instância 1, que somará 2 + 1 e retornará 
o valor para a função principal, encerrando o ciclo de recursividade. 
Figura 4. Memória de trabalho da função recursiva soma().
Instância 1 Instância 2 Instância 3
soma(2) soma(1) soma(0)
return 2 + ?; return 1 + ?; return 0;
3 1 0
main
Uma das principais dúvidas dos programadores é quando utilizar a recursi-
vidade em vez de uma estrutura de repetição. Você consegue dizer se a função 
soma(), criada na Figura 3, poderia ser substituída por alguma estrutura de 
repetição, por exemplo a estrutura for? 
A resposta é “sim”. No exemplo dado, você poderia escrever algo parecido 
com o que é mostrado na Figura 5 para resolver este mesmo problema da 
somatória, utilizando a estrutura de repetição for.
Figura 5. Soma utilizando a estrutura de repetição for.
Recursividade em C8
LABORATÓRIO DE PROGRAMAÇÃO 58
A técnica de recursividade pode substituir o uso de estruturas de repetição, 
tornando o código mais simples e elegante do ponto

Continue navegando