Pearson Education Slide 1
Pearson Education Slide 2 Cap í tulo 13 Criado por Frederick H. Colclough, Colorado Technical University Recursão
Pearson Education Slide 3 Objetivos de Estudo Funções void Recursivas Acompanhando uma Chamada Recursiva Recursão infinita e transbordamento Funções Recursivas que Retornam um Valor Função power Pensando Recursivamente Técnicas para projetar recursões Busca Binária
Pearson Education Slide 4 Introdução à Recursão Um função que chama a si própria Chama-se recursiva Na definição de função, chama a mesma função C++ permite recursão Como a maioria da linguagens modernas Pode ser uma técnica muito útil Há limitações
Pearson Education Slide 5 Funções Recursivas void Dividir e Conquistar Técnica básica de projeto Quebrar grandes tarefas em subtarefas Subtarefas podem ser versões menores da tarefa original! Quando elas são recursão
Pearson Education Slide 6 Exemplo de Funções Recursivas void Considere a tarefa: Pesquisa um valor em uma lista Subtarefa 1: Pesquisa 1 a metade da lista Subtarefa 2: Pesquisa 2 a metade da lista As subtarefas são versões menores da tarefa original! Quando isso ocorre, pode ser usada uma uma função recursiva Geralmente o resultado é uma solução elegante
Pearson Education Slide 7 Funções Recursivas void : Números Verticais Tarefa: Mostrar números verticalmente, um por linha Exemplo de chamada: escrevaVertical(1234); Produzirá a saída:
Pearson Education Slide 8 Números Verticais: Definição de Recursão Quebra o problema em dois casos Caso simples: se n<10 Simplesmente escreva o numero n na tela Caso recursivo: Se n>=10, duas subtarefas: 1- Obtenha todos os dígitos exceto o último 2- Obtenha o último dígito Exemplo: argumento 1234: 1 a subtarefa mostra 1, 2 e 3 verticalmente 2 a subtarefa mostra 4
Pearson Education Slide 9 Definição da Função escrevaVertical Dado o caso anterior: void escrevaVertical(int n) { if (n < 10) //Caso simples cout << n << endl; else {//Subtarefa recursiva escrevaVertica (n/10); cout << (n%10) << endl; } }
Pearson Education Slide 10 Acompanhando escrevaVertical Exemplo de chamada: escrevaVertical(123); escrevaVertical (12); (123/10) escrevaVertical (1); (12/10) cout << 1 << endl; cout << 2 << endl; cout << 3 << endl; A seta indica a tarefa que a função executa Observe que duas chamadas chamam de novo (recursão) Última chamada (1) exibe e finaliza
Pearson Education Slide 11 Recursão – Olhando mais de perto O computador controla as chamadas recursivas da seguinte forma: Pára a função atual Precisa saber os resultados da chamada recur- siva antes de prosseguir Salva toda a informação que precisa Para ser usada mais tarde Continua a executar a chamada recursiva Quando AQUELA chamada termina, retorna para terminar o cáculo externo
Pearson Education Slide 12 Recursão Esquema geral de uma boa definição de função recursiva: Um ou mais casos onde a função completa suas tarefas: Fazendo uma ou mais chamadas recursivas para resolver versões menores da tarefa original Chamadas Caso(s) recursivo(s) Um ou mais casos onde a função completa suas tarefas sem chamadas recursivas chamados caso(s) simples ou caso(s) de parada
Pearson Education Slide 13 Recursão Infinita Precisamos chegar a um caso de parada Se isto não acontece recursão infinita Chamadas recursivas que nunca terminam! Lembre-se do exemplo escrevaVertical: O caso de parada ocorreu quando chegamos a um número de 1 dígito Quando a recursão parou
Pearson Education Slide 14 Exemplo de Recursão Infinita Considere a definição de função alternativa: void novaEscrevaVertical(int n) { novaEscrevaVertical(n/10); cout << (n%10) << endl; } Parece bastante razoável Faltando o caso de parada! A recursão nunca pára
Pearson Education Slide 15 Pilhas para Recursão Uma pilha Estrutura de memória especializada Como uma pilha de pápel Coloque novos no topo Quando necessário, remova do topo Estrutura de memória chamada último a entrar/primeiro a sair Recursão utiliza pilhas Cada chamada recursiva é colocada em uma pilha Quando uma estiver completa, a última chamada é removida da pilha
Pearson Education Slide 16 Transbordamento da pilha O tamanho da pilha é limitado Memória é finita Cadeias longas de chamadas recursivas continuamente adicionadas à pilha Se a pilha tenta crescer além dos limites: Erro de Transbordamento de pilha (Stack overflow) Recursão Infinita sempre causa esse erro
Pearson Education Slide 17 Recursão Versus Iteração Recursão nem sempre é necessária Nem mesmo permitida em algumas linguagens Qualquer tarefa executada com recursão pode também ser feita sem ela Não-recursiva: chamada iterativa, usando loops Recursiva: Roda mais lentamente e usa mais memória Solução elegante; menos código
Pearson Education Slide 18 Funções Recursivas que Retornam um Valor Recursão não se limita a funções void Pode retornar valores de quaisquer tipos Mesma técnica, esquema: 1- Um ou mais casos em que o valor retornado é calculado por chamadas recursivas Devem ser sub-problemas menores 2- Um ou mais casos em que o valor retornado é calculado sem chamadas recursivas Casos de parada
Pearson Education Slide 19 Exemplo de Recursão que Retorna um Valor: Power Lembre-se da função predefinida pow(): result = pow(2.0,3.0); Retorna 2 elevado à potência de 3 (8.0) Requer dois argumentos tipo double Retorna um valor tipo double Vamos escrevê-la recursivamente Um exemplo simples
Pearson Education Slide 20 Definição de função para power() int power(int x, int n) { if (n 0) return (power(x, n-1)*x); else return (1); }
Pearson Education Slide 21 Chamando a Função power() Exemplo de chamada: power(2, 0); retorna 1 power(2, 1); retorna (power(2, 0) * 2); retorna 1 Valor 1 multiplicado por 2 e retornado a chamada original
Pearson Education Slide 22 Chamando a Função power() Exemplo maior: power(2,3); power(2,2)*2 power(2,1)*2 power(2,0)*2 1 Alcança o caso de parada A recursão pára Valores retornados para o topo da pilha
Pearson Education Slide 23 Acompanhando a Função power() Painel 13.4 página 389
Pearson Education Slide 24 Pensando Recursivamente Ignore os detalhes Esqueça como a pilha trabalha Esqueça a suspensão dos cálculos Sim, isto é um princípio de abstração! E um princípio de encapsulamento! Deixe o computador fazer a contabilidade
Pearson Education Slide 25 Pensando Recursivamente: power Considere a função power() novamente Definição recursiva de power(): power(x, n) retorna: power(x, n – 1) * x Apenas assegure-se que a fórmula esteja correta E assegure-se que o caso de parada irá ocorrer
Pearson Education Slide 26 Técnicas para Projetar Recursões Não acompanhe a seqüência recursiva inteira! Apenas verifique 3 propriedades: 1- Não há recursão infinita 2- Casos de parada retornam valores corretos 3- Casos recursivos retornam valores corretos
Pearson Education Slide 27 Verificação do Projeto de Recursão: power() Confronte power() contra as 3 propriedades: 1- Não há recursão infinita: 2 o argumento diminui em 1 em cada chamada Conseqüentemente deve chegar ao caso de parada em 1 2- Casos de parada retornam valores corretos: power(x,0) é o caso de parada Retorna 1, o qual é correto para x 0 3- Casos recursivos retornam valores corretos: Para n>1, power(x,n) retorna power(x,n-1)*x Valores conectados correto
Pearson Education Slide 28 Busca Binária Função Recursiva para busca em um vetor Determina SE o item está na lista, e se estiver: Onde ele está na lista Assume que o vetor está ordenado Divide a lista ao meio Determina se o item está na 1 a ou 2 a metade Então busca novamente só naquela metade Recursividade (é claro)!
Pearson Education Slide 29 Pseudocódigo para Busca Binária Painel 13.5 página 392
Pearson Education Slide 30 Verificando a Recursão Confronte a busca binária com os critérios: 1- Não há recursão infinita: Cada chamada incrementa first decrementa last Finalmente first será maior que last 2- Casos de parada retornam valores corretos: Se first > last não há elemento entre eles, assim, key não pode estar lá! Se key == a[mid] Encontrada corretamente! 3- Casos recursivos retornam valores corretos: Se key < a[mid] key na 1 a metade – chamada correta Se key > a[mid] key na 2 a metade – chamada correta
Pearson Education Slide 31 Execução da Busca Binária Painel 13.7 página 395
Pearson Education Slide 32 Eficiência da Busca Binária Extremamente Rápida Comparada com a busca seqüencial Metade do vetor é eliminada logo no início! Então um quarto, 1/8, etc. Finalmente elimina a metade com cada chamada Exemplo: Vetor de 100 elementos: Busca binária nunca precisará mais do que 7 comparações! Eficiência logarítimica (log n)
Pearson Education Slide 33 Soluções Recursivas Observe que o algorítmo de busca binária resolve atualmente o problema mais geral Tarefa original: projetar uma função de busca em um vetor inteiro Nossa função : permite pesquisar qualquer intervalo do vetor Especificando os limites first [primeiro] e last [ultimo] Isso é normal quando projetamos funções recursivas
Pearson Education Slide 34 Sumário Reduzir o problema em instâncias menores do mesmo problema -> solução recursiva O Algorítmo recursivo tem dois casos: Casos-base ou casos de parada Caso recursivo Assegure-se: Não há recursão infinita Use os critérios para determinar se a recursão está correta Três propriedades essenciais Tipicamente resolve o problema mais geral