Baixe o app para aproveitar ainda mais
Prévia do material em texto
Escola de Exatas Ciência da Computação Pesquisa, Ordenação e Técnicas de Armazenamento Professor Israel Costa Roteiro ❑ Relembrando ❑ Definição de Recursividade ❑ Exemplos de Recursividade ❑ Estrutura da Recursividade ❑ Vantagens e desvantagens da Recursividade 2 Relembrando em Estrutura de Dados • Lista Linear. • Lista Duplamente Encadeada. • Lista Circular. • Pilha. • Fila. • Árvore Binária. • Árvore Binária de Busca. • Percursos em Árvore • Árvore AVL. • Rotação simples à direita. • Rotação simples à esquerda. • Rotação dupla à direita. • Rotação dupla à esquerda Introdução • Fonte: https://encrypted- tbn0.gstatic.com/images?q=tbn:ANd9GcQCGE sUlhPaY2NDRLZNROd5jgklzMjdQUfqsN8hoGXe GHQPZTNxPA https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQCGEsUlhPaY2NDRLZNROd5jgklzMjdQUfqsN8hoGXeGHQPZTNxPA Introdução • Fonte: https://encrypted- tbn0.gstatic.com/images?q=tbn:ANd9Gc QCGEsUlhPaY2NDRLZNROd5jgklzMjdQUf qsN8hoGXeGHQPZTNxPA https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQCGEsUlhPaY2NDRLZNROd5jgklzMjdQUfqsN8hoGXeGHQPZTNxPA Introdução ❑ “O número natural é o 0 (Zero). ❑ O sucessor de um número natural é também o número natural”. ❑ Giuseppe Peano (1858- 1932) Figura 3: Giuseppe Peano Introdução ❑ Em computação, a recursividade é quando definimos uma rotina (procedimento ou função) que chama a si mesma. ❑ Em seu corpo de código há uma chamada (ou invocação) para ela mesma. Recursividade e termos Sinônimos: ❑ Recursão; ❑ Recursividade; ❑ Autoreferência; ❑ Recorrência Recursão em C++ A recursão é uma técnica que define um problema em termos de uma ou mais versões menores deste mesmo problema. Esta ferramenta pode ser utilizada sempre que for possível expressar a solução de um problema em função do próprio problema. 4 Recursão em C Uma função é dita recursiva quando dentro do seu código existe uma chamada para si mesma. Ex: cálculo do fatorial de um número: n! = n * (n -1)! Exemplos de Recursividade ▪ O exemplo a seguir define o ancestral de uma pessoa: ▪ Os pais de uma pessoa são seus ancestrais (caso base); ▪ Os pais de qualquer ancestral são também ancestrais da pessoa inicialmente considerada (passo recursivo). ▪ Componente para uma equipamento eletrônico: ▪ Um componente eletrônico é formado por outros componentes (caso base); ▪ Cada componente integrante do componente eletrônico também é formado por outros componentes (passo recursivo). Vantagens ▪ CÓDIGO MAIS LEGÍVEL ▪ MAIS ENXUTO ▪ MAIS FÁCIL DE MANTER Recursividade – Exercícios 1. Construa um algoritmo que imprima os números pares no intervalo de 0 a 30. 2. Construa um algoritmo que imprima os números ímpares no intervalo de 0 a 50. 3. Construa um algoritmo que imprima os números múltiplos de 5 no intervalo de 0 a 100. 4. Altere o código da questão 1 para mesma solução dos números pares imprimindo-os de forma recursiva. 5. Altere o código da questão 2 para mesma solução dos números ímpares imprimindo-os de forma recursiva. 6. Altere o código da questão 3 para mesma solução dos múltiplos de 5 imprimindo-os de forma recursiva. Exemplos de Recursividade ❑ O fatorial de um número N é o produto de todos os números inteiros entre 1 e N. Por exemplo, . fatorial (ou 3!) é 1 * 2 *3 = 6. ❑ Mas multiplicar n pelo produto de todos os inteiros a partir de n-1 até 1 resulta no produto de todos os inteiros de n a 1. Portanto, é possível dizer que fatorial: 0! = 1 1! = 1 * 0! 2! = 2 * 1! 3! = 3 * 2! 4! = 4 * 3! Exemplos de Recursividade ❑ Logo o fatorial de um número também pode ser definido recursivamente (ou por recorrência) através das seguintes regras: n! = 1, se n = 0 ou n=1 n! = fatorial(n-1)*n! , se n > 0 Exercício 1. Construa um algoritmo que calcule o fatorial de um determinado numero de forma iterativa. 2. Altere o código para a mesma solução do cálculo do fatorial de forma recursiva a partir da relação de recorrência abaixo: N! = 1, se n = 0 ou n=1 (caso base)N! N! = fatorial(n-1)*n! , se n > 1 Exercício última aula (manhã) 3. Escreva uma função recursiva para calcular conforme a estrutura de recorrência abaixo: 4. Calcule o somatório dos N primeiros números a partir da relação de recorrência abaixo: P2 = 1, se N = 1 (solução trivial) P2 = S(N-1) + N, se N > 1 P1=1, se y=0 | P1= x, se y=1 P1 P2 P1=x*pot(x, y-1), se y>1 Exercício 5. Analise o código abaixo, teste-o e monte a relação de recorrência com base na solução do problema em questão: #include <stdio.h> int Rec(int x, int y){ if (y == 0) return 0; else return x + Rec(x, y-1); } main(){ int num1, num2; printf("Resultado: %d", Rec(num1,num2)); } Exercício 6. Faça uma função recursiva que resolva a seguinte equação: r(0) = 2 //caso base r(x) = 2 * r (x –1) –4 //passo recursivo DESAFIO 5. Construa um algoritmo que calcule e imprima a sequência de Fibonacci abaixo: 0 1 1 2 3 5 8 13 21. O Custo de memória e o esforço computacional para tudo isso ❑ Quando uma função chama a si mesma, novos parâmetros e variáveis locais são alocados na pilha, sendo criado um novo contexto de execução para as variáveis e o código da função é executado com essas novas variáveis. ❑ Uma chamada recursiva não faz uma nova cópia da função; apenas os argumentos são novos. ❑ Quando cada função recursiva retorna, as variáveis locais e os parâmetros são removidos da pilha e a execução recomeça do ponto da chamada à função dentro da função. EXEMPLO FATORIAL #include <stdio.h> int fatorial (int n) { if (n == 1 || n == 0) /* condição de parada da recursão*/ return 1; else if (n < 0) { printf ("Erro: fatorial de número negativo!\n"); exit(0); } return n*fatorial(n-1); } 5 EXEMPLO FATORIAL fatorial(5) => (5 ° 0) return 5 • fatorial(4) => (4 ° 0) return 4 • fatorial(3) => (3 ° 0) return 3 • fatorial(2) => (2 ° 0) return 2 • fatorial(1) => (1 ° 0) return 1 • fatorial(0) => (0 == 0) <= return 1 <= return 1 • 1 (1) <= return 2 • 1 (2) <= return 3 • 2 (6) <= return 4 • 6 (24) <= return 5 • 24 (120) 120 6 /* Faça um programa que calcula e mostra o fatorial de um número inteiro positivo n. (Ex: 0! = 1; 3! = 3*2*1 = 6) */ #include <stdio.h> #include <conio.h> int fatorial (int n) { if (n == 0) return 1; else if (n<0){ printf("\nErro: fatorial de numero negativo!\n"); getch(); exit(0); } return n*fatorial(n-1); } 7 int main(void) { int n, fat=1; printf("Digite um numero inteiro:"); scanf("%d", &n); fat=fatorial(n); printf("\n\nO fatorial de %d eh: %d", n, fat); getch(); } 8 EX: SOMA N PRIMEIROS NÚMEROS INTEIROS Supondo N = 5; S(5) = 1+2+3+4+5 = 15 -> S(5) = S(4) + 5 -> 10 + 5 = 15 S(4) = 1+2+3+4 =10 -> S(4) = S(3) + 4 -> 6 + 4 = 10 S(3) = 1+2+3 = 6 -> S(3) = S(2) + 3 -> 3 + 3 = 6 S(2) = 1+2 = 3 -> S(2) = S(1) + 2 -> 1 + 2 = 3 S(1) = 1 =1 -> S(1) = 1 --------------->solução trivial 9 Recursão ❑ Em procedimentos recursivos pode ocorrer um problema de terminação do programa, como um “looping interminável ou infinito”. ❑ Portanto, para determinar a terminação das repetições, deve-se: ❑ Definir uma função que implica em uma condição de terminação (solução trivial), e ❑ Provar que a função decresce a cada passo de repetição, permitindo que, eventualmente, esta solução trivial seja atingida. 10 ESTRUTURA DE UMA RECURSÃO uma recursão obedece a uma estrutura que deve conter os seguintes elementos: função (par) teste de término de recursão utilizando par se teste ok, retorna aqui processamento aqui a função processa as informações em par chamada recursiva em par’ par deve ser modificado de forma que a recursão chegue a um término 11 EX: SOMA N PRIMEIROS NÚMEROS INTEIROS main( ) { int n; scanf(“%d”, &n); printf(“%d”, soma(n)); } int soma(int n) { if (n == 1) return (1); else return (n + soma(n – 1)); } 12 EXEMPLO: PRINTD(INT) printd(int) imprime um inteiro usando recursão void printd(int n) { /* imprime sinal */if (n < 0) { putchar('-'); n = -n; } if (n / 10) /* termino recursao */ printd(n/10); /* recursao se n>10 */ putchar(n % 10 + '0'); /* senao imprime char */ } 13 EXEMPLO PRINTD() printd(-1974) ==> (n < 0) --> putchar(„-‟) - ==>printd(197) - ==> printd(19) ==> printd(1) (1 / 10 = = 0) putchar(1 + „0‟) putchar(19%10 + „0‟) putchar(197%10 + „0‟) putchar(1974 %10 + „0‟) - - - -1 -19 -197 -1974 14 ANALISANDO RECURSIVIDADE Vantagens X Desvantagens Um programa recursivo é mais elegante e menor que a sua versão iterativa, além de exibir com maior clareza o processo utilizado, desde que o problema ou os dados sejam naturalmente definidos através de recorrência. Por outro lado, um programa recursivo exige mais espaço de memória e é, na grande maioria dos casos, mais lento do que a versão interativa. 15 Exemplos de Programas com função recursiva 1. Escreva uma função recursiva para calcular o valor de uma base x elevada a um expoente y. 2. Escrever uma função recursiva que retorna o tamanho de um string, tamstring(char s[]) 3. Fazer uma função recursiva que conta o número de ocorrências de um determinado caracter, caract(char c, char s[]) 4. Escreva uma função recursiva que produza o reverso de um string, reverse(char s[]) Exemplos de Programas com função recursiva 1. Escreva uma função recursiva para calcular o valor de uma base b elevada a um expoente e. Recorrência: be=1, se e=0 | be= b, se e=1 be=b*potencia(b, e-1), se e>1 #include <stdio.h> #include <conio.h> int expo (int x, int y) { if (y == 0) return 1; if (y == 1) return x; return x*expo(x,y-1); } int main(void) { int x, y, e; printf("Exponencial de x elevado a y\n\n"); printf("\nDigite o numero inteiro x:"); scanf("%d", &x); printf("\nDigite o numero inteiro y:"); scanf("%d", &y); if (y < 0) { printf("y tem que ser maior ou igual a zero!!"); getch(); } else{ e=expo(x,y); printf("\n\nX elevado a y eh: %d", e); getch();} } 17 #include <stdio.h> #include <conio.h> int tamstring(char s[]) { if (s[0] == '\0') return 0; return 1+tamstring(&s[1]); } int main(void) { char s[20]; int t; printf("Tamanho de string\n\n"); printf("\nDigite a string: "); scanf("%s", s); t=tamstring(s); printf("\n\nO tamanho eh %d", t); getch(); } 18 /* conta quantas vezes um caractere ocorre em uma string*/ #include <stdio.h> #include <conio.h> int carac(char c,char s[]) { if (s[0] == '\0') return 0; if (s[0]==c) return (1+carac(c,++s)); return carac(c,++s); } int main(void) { char s[30],c; int t; printf("Busca em string\n\n"); printf("\nDigite a string: "); gets(s); printf("\nDigite o caractere desejado: "); c=getchar(); t=carac(c,s); printf("\n\nEncontrei %d vezes", t); getch(); } 19 /* imprime uma string em ordem reversa*/ #include <stdio.h> #include <conio.h> void contrario(char s[]) { if (s[0] != '\0'){ contrario(&s[1]); printf("%c",s[0]);} } int main(void) { char s[30],c; int t; printf("Imprime reverso\n\n"); printf("\nDigite a string: "); gets(s); contrario(s); getch(); } 20 Atividade – Aula01 1. Defina e exemplifique o conceito de recursividade. 2. Descreva sobre as Vantagens e desvantagens da Recursividade. 3. Qual o custo de memória e o esforço computacional para uma função recursiva? BIBLIOGRAFIA BÁSICA DOBRUSHKIN, Vladimir A. Métodos para Análise de Algoritmos. LTC, 03/2012. TANENBAUM, Andrew S., WOODHULL, S. Sistemas Operacionais: Projetos e Implementação - O Livro do Minix. Bookman, 01/2008. MONTEIRO, Mario A. Introdução à Organização de Computadores, 5ª edição. LTC, 05/2007.
Compartilhar