Funções recursivas. O exemplo mais comum: int fat(int n){ if(n == 0) return 1; return n*fat(n-1); }



Documentos relacionados
Estruturas de Dados. Módulo 11 Pilhas. 9/8/2005 (c) Dept. Informática - PUC-Rio 1

FACULDADE DE TECNOLOGIA SENAC GOIÁS ADELTON HENRIQUE ABISHAI LEMES BORGES NETO HENRIQUE FERREIRA DA SILVA

Introdução à Programação. Recursão

INF 1620 P1-10/04/02 Questão 1 Nome:

SCC 202 Algoritmos e Estruturas de Dados I. Pilhas (Stacks) (implementação dinâmica)

Estruturas de Dados. Parte dos slides a seguir são adaptações, extensões e traduções para C dos originais:

Aula 3 Alocação Dinâmica

2ª Lista de Exercícios

Programas operam sobre dados. Dados são relacionados e possuem estrutura. Como representar e manipular dados em um computador

DAS5102 Fundamentos da Estrutura da Informação

ALGORITMOS E ESTRUTURAS DE DADOS Terceiro Trabalho Prático Recursividade e Pilhas

struct LISTA item quant

Estruturas (Registros)

Estruturas de Dados Aula 11: TAD Pilha 09/05/2011

Pilhas. Profa Morganna Diniz

Linguagem C: agregados heterogêneos, arquivos binários, recursividade. Prof. Críston Algoritmos e Programação

Analise o código abaixo:

Busca. Pesquisa sequencial

Estruturas de Dados. Prof. Gustavo Willam Pereira Créditos: Profa. Juliana Pinheiro Campos

ESTRUTURAS DE DADOS I. Notas de Aula. Prof. Dr. Gilberto Nakamiti

INF 1007 Programação II

Listas (Parte 2) Túlio Toffolo BCC202 Aula 10 Algoritmos e Estruturas de Dados I

Algoritmos e Estruturas de Dados

A Pilha. Aula 02. DPEE 1038 Estrutura de Dados para Automação Curso de Engenharia de Controle e Automação Universidade Federal de Santa Maria

Listas ligadas/listas encadeadas

Princípios de Desenvolvimento de Algoritmos MAC122

Revisão: Tipo Abstrato de Dados Recursividade

Introdução a Programação. Ponteiros e Strings, Alocação Dinâmica

BUSCA EM LISTAS LISTAS SEQÜENCIAIS, LISTAS SIMPLESMENTE E DUPLAMENTE ENCADEADAS E LISTAS CIRCULARES

Alocação dinâmica de memória

Estruturas de Dados Aula 15: Árvores 17/05/2011

Introdução a Programação. Tipos Abstratos de Dados Implementando Pilha e Fila

PIP/CA - Programa Interdisciplinar de Pós-Graduação em Computação Aplicada da UNISINOS ALGORITMOS & ESTRUTURAS DE DADOS

CIÊNCIA DA COMPUTAÇÃO PROVA PARA TRANSFERÊNCIA

Operaçõe õ s c om o Strings Intr oduç ão a o Ponte iros o e Funçõe õ s

Algoritmos e Programação Estruturada

SCC0214 Projeto de Algoritmos

Computação I - C Prova /10/ Profs. Adriano Cruz e Valeria Bastos

Questão 1: O histograma deve ser: [0, 1, 4, 2, 0, 3, 0,, 0, 2] Exemplo: Para a matriz

Métodos Computacionais. Listas Encadeadas

Introdução a POO. Introdução a Linguagem C++ e POO

10. Listas Encadeadas

Métodos Computacionais. Árvores

INF1007 Programação 2 9 Pilhas. (c) Dept. Informática - PUC-Rio 1

SCC Algoritmos e Estruturas de Dados I

INF 1007 Programação II

Programação Estruturada I

Métodos Computacionais. Fila

Princípios de Desenvolvimento de Algoritmos MAC122

Recursividade. Aula 9

1 se n = 0 n (n 1)! se n 1

INF1007: Programação 2 10 Árvores Binárias. (c) Dept. Informática - PUC-Rio 1

Algoritmo e Técnica de Programação - Linguagem C

void push(int i){ if (num<max) vet[num++]=i; else { printf(">>> Erro: overflow na pilha!!!\n"); printf("%d nao foi empilhado!!!

INF 1620 P3-02/07/02 Questão 1 Nome:

Algoritmos e Estruturas de dados

Tipos abstratos de dados

INTRODUÇÃO AO C++ SISTEMAS DE INFORMAÇÃO DR. EDNALDO B. PIZZOLATO

INF PROGRAMAÇÃO II LISTA DE EXERCÍCIOS 15

Introdução a Programação. Listas Encadeadas

INF 1620 P1-13/09/02 Questão 1 Nome:

Exercício 1. Tabela 1: Cadastro de usuários, senhas e privilégios (exemplo). Login Senha Privilégio Armamento

UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO CENTRO UNIVERSITÁRIO NORTE DO ESPÍRITO SANTO

INF 1007 Programação II

Programação de Computadores II. Cap. 4 Funções

Programação II. Pilhas (stacks) Bruno Feijó Dept. de Informática, PUC-Rio

Métodos Computacionais. Variações de Listas Encadeadas

ESTRUTURA DE DADOS PILHA

Princípios de Desenvolvimento de Algoritmos MAC122 Prof. Dr. Paulo Miranda IME-USP

Programação II. Listas Encadeadas (Linked Lists) Bruno Feijó Dept. de Informática, PUC-Rio

13. ALOCAÇÃO DINÂMICA DE MEMÓRIA

Programação de Computadores I Introdução ao C PROFESSORA CINTIA CAETANO

INF 1007 Programação II

1ª versão. #include <stdio.h> #include <string.h> #include <stdlib.h> #define maxdiscos 1000

Algoritmos e Estruturas de Dados

Atividade de laboratório listas encadeadas simples

Trabalho 3: Agenda de Tarefas

5 - COMANDOS DE CONTROLE DE PROGRAMA Em C existem os comandos de decisões, os comandos de iteração (ou de laços) e os comandos de desvios.

Universidade da Beira Interior Cursos: Matemática /Informática e Ensino da Informática

Listas Encadeadas. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

SCC 202 Prova 1. 28/9/2010 Resolução e Comentários

Tipos de Dados, Tipos Abstratos de Dados Estruturas de Dados

PROVA P2 INF /10/2014 Programação II

REVISÃO DE PILHAS E FILAS. Vanessa Braganholo Estruturas de Dados e Seus Algoritmos

MC102 Algoritmos e programação de computadores Aula 3: Variáveis

Introdução a Programação. Ponteiros e Strings, Alocação Dinâmica

Estruturas de Dados Aula 11: TAD Pilha

Resumo da Introdução de Prática de Programação com C. A Linguagem C

Curso C: Funções e Macros

Linguagem C: Listas Encadeadas

Linguagem C: Elementos fundamentais

Pilhas e Filas Encadeadas. Algoritmos e Estruturas de Dados I

Programação de Computadores I. Ponteiros

Estruturas de Dados. Introdução Definição de Ponteiros Declaração de Ponteiros em C Manipulação de Ponteiros em C

Alocação de Memória. Lucas Ferrari de Oliveira Professor Adjunto Universidade Federal do Paraná (UFPR)

Métodos Computacionais. Tipos Estruturados

Transcrição:

Funções Recursivas

Funções recursivas O exemplo mais comum: int fat(int n){ if(n == 0) return 1; return n*fat(n-1); Versão sem recursão: int fat(int n){ int i = 0; int f = 1; for(i=1; i <=n; i++) f *= i; return f;

Outro exemplo Série de Fibonacci (0,1,1,2,3,5,8,13,...) : int fib(int n){ if(n <= 1) return m; return fib(n-1)*fib(n-2); Versão sem recursão: int fibb(int n){ int f1 = 0, f2 = 1, f3, i; for(i=1; i <= n; i++) { f3 = f2 + f1; f1 = f2; f2 = f3; return f1;

Mais um exemplo Torres de Hanoi void movetorre(int n, char a, char b, char c){ if(n > 0) { movetorre(n-1,a,c,b); printf("mover de %c para %c\n",a,b); movetorre(n-1,c,b,a);

Eliminação da recursão Dada uma função recursiva, sempre é possível escrever uma função equivalente, sem recursão. Para se eliminar a recursão, na maioria das vezes é necessário recorrer ao uso de uma pilha. Caso simples: a função faz uma única chamada recursiva durante sua execução (ex. fatorial).

Um exemplo #include <stdio.h> void g(...){ char m,n;... g(...);... g(...);... int main(){ char x,y,z;... g();...... x y z... m n... m n... endereços crescentes registro de ativação de main() registro de ativação de g(...) registro de ativação de g(...) Cada ativação de g() usa o seu próprio registro de ativação que contém suas variáveis locais e parâmetros.

Eliminação da recursão Idéia Geral (usando uma pilha) Cada chamada recursiva é substituida por comandos para empilhar o valor das variáveis locais e parâmetros alterar os valores das variáveis locais e parâmetros voltar ao início da função O encerramento de uma chamada (retorno) é substituído por comandos para desempilhar os valores dos parâmetros e variáveis locais. continuar a execução a partir do ponto onde seria o retorno da chamada recursiva correspondente (esse ponto pode ser representado por um valor adicional na pilha).

Eliminação da recursão Idéia Geral (usando uma pilha) Na prática, ao se usar uma linguagem de programação de alto nível, voltar ao início da função e continuar a execução a partir determinado ponto nem sempre são óbvios. Em geral é necessário recorrer a combinações de comandos while e switch.

Um exemplo (1) typedef enum { iniciar, imprimir, encerrar operacao; void movetorre2(int n, char a, char b, char c){ empilha(encerrar,-1,'?','?','?'); operacao op = iniciar; do{ switch(op){ case iniciar: if(n > 0) { empilha(iniciar, n-1,c,b,a); empilha(imprimir,n-1,a,b,c); empilha(iniciar, n-1,a,c,b); break; case imprimir: printf("mover de %c para %c\n",a,b); break; desempilha(&op,&n,&a,&b,&c); while(op!= encerrar);

Um exemplo (2) Pilha em alocação sequencial (vetor) #define PMAX 100 #define EMPTY -1 int pilha[pmax]; int t; void erro(char* s){ printf("erro: %s\n",s); exit(-1); void iniciapilha(){ t = EMPTY;

Um exemplo (3) void empilha(operacao op, int n, char a, char b, char c){ if(t+5 >= PMAX) erro("pilha cheia!"); pilha[++t] = (int) op; pilha[++t] = n; pilha[++t] = (int)a; pilha[++t] = (int)b; pilha[++t] = (int)c; void desempilha(operacao* op, int* n, char* a, char* b, char* c){ if(t-5 < EMPTY) erro("pilha vazia!"); *c = (char)pilha[t--]; *b = (char)pilha[t--]; *a = (char)pilha[t--]; *n = pilha[t--]; *op = (operacao)pilha[t--];

Um exemplo (4) Implementação de pilha usando alocação ligada typedef struct config* pconfig; typedef struct config { operacao opp; int nn; char aa,bb,cc; pconfig prox; config; pconfig topo; void iniciapilha(){ topo = NULL;

Um exemplo (5) void empilha(operacao op, int n, char a, char b, char c){ pconfig p = (pconfig)malloc(sizeof(config)); if(p == NULL) erro("falha ao alocar memória"); p->opp = op; p->nn = n; p->aa = a; p->bb = b; p->cc = c; p->prox = topo; topo = p; void desempilha(operacao* op, int* n, char* a, char* b, char* c){ pconfig p = topo; if(p == NULL) erro("pilha vazia"); *op = p->opp; *n = p->nn; *a = p->aa; *b = p->bb; *c = p->cc; topo = p->prox; free(p);

Recursão e retrocesso Várias alternativas devem ser tentadas Se uma alternativa não é bem sucedida, voltar ao estado anterior e tentar a próxima alternativa. Exemplo: Procurar um caminho num labirinto

Recursão e retrocesso Idéia geral: void tenta(alternativa){ if(<alternativa viável> { <marca alternativa selecionada> if(<atingiu objetivo>) <encontrou solução>; else <para todas alternativas alt atuais> tenta(alt); < desmarca alternativa selecionada>

Um exemplo (labirinto) /* matriz que define o labirinto */ int m[8][8]; void tenta(int i, int j){ X int dx[8] = {-1,-1,-1,0,0,1,1,1; int dy[8] = {-1,0,1,-1,1,-1,0,1; int k; if(m[i][j] == ' '){ /* alternativa viável */ m[i][j] = 'x'; /* marcar o caminho */ if((i==di)&&(j==dj)) /* atingiu o objetivo */ imprime(); else { /* tentar todas alternativas */ for(k=0; k < 8; k++) tenta(i+dx[k],j+dy[k]); m[i][j] = ' '; /* desfazer a marca */

Um exemplo (labirinto) /* inicia a matriz m */ void inicia(){ int i,j; for(i=0; i < 8; i++) for(j=0; j < 8; j++) m[i][j] = ' '; for(i=0; i < 8; i++){ /* bordas do labirinto */ m[i][0] = '#'; m[i][7] = '#'; m[7][i] = '#'; m[0][i] = '#'; for(i=0; i < 6; i++){ /* paredes internas */ m[2][i] = '#'; m[4][i+2] = '#'; m[5][2] = '#'; m[5][4] = '#';