Estruturas de Dados Aula 14: Recursão 04/06/2014.

Slides:



Advertisements
Apresentações semelhantes
IFTO ESTRUTURA DE DADOS AULA 05 Prof. Manoel Campos da Silva Filho
Advertisements

Estrutura de Dados Pilha by Aquiles Burlamaqui. Definição Uma pilha é uma das várias estruturas de dados que admitem remoção de elementos e inserção de.
Aquiles Burlamaqui AULA 09
Python: Recursão Claudio Esperança.
Aula T10 – BCC202 Listas – Parte 2 Túlio Toffolo www. decom. ufop
Aula T-09 – BCC202 Listas (Parte 1) Túlio Toffolo www. decom. ufop
Programação em Java Prof. Maurício Braga
Marco Antonio Montebello Júnior
Recursividade Prof. Rosana Palazon.
Listas duplamente encadeadas
Programação II Estruturas de Dados
Alocação Dinâmida de Memória
Árvores.
1 MergeSort Seja uma lista A de n elementos. O algoritmo consiste das seguintes fases Dividir A em 2 sub-listas de tamanho n/2 Conquistar: ordenar cada.
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Estruturas de Dados I DECOM – UFOP
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Estruturas de Dados I DECOM – UFOP
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
BCC101 – Matemática Discreta
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
Recursividade Conceitos e Aplicações.
Árvores Introdução e Aplicações Árvores de Busca Binária Fundamentos
Estruturas de Dados I Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Prof.: Sergio Pacheco Estruturas de Dados I Prof.: Sergio Pacheco 1.
Estruturas de Dados II Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Listas com Ponteiros Listas encadeadas Listas circulares.
Slides: Prof. João Fabro UTFPR - Curitiba
Lista Encadeada Circular Lista Duplamente Encadeada
Listas Encadeadas.
ALGORITMOS E ESTRUTURAS DE DADOS
Introdução à Programação
Pesquisa em Memória Primária
Denise Guliato Faculdade de Computação – UFU
Denise Guliato Faculdade de Computação – UFU
Denise Guliato Faculdade de Computação – UFU
Estruturas de Dados com Jogos
INTELIGÊNCIA ARTIFICIAL
Lista Encadeada Circular Lista Duplamente Encadeada
Estrutura de dados II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação
UNIDADE 6 - complemento Funções recursivas
Denise Guliato Faculdade de Computação – UFU
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Recursão.
Mergesort Katia Guimarães.
Estruturas de Dados Aula 9: Listas (parte 1)
Orientação a Objetos e Java Graduação em Ciência da Computação
Algoritmos e Estruturas de Dados I – Recursão
Algoritmos e Estruturas de Dados I – Recursão
Recursão Uma função é dita recursiva quando dentro do seu código existe uma chamada para si mesma Exemplo Cálculo do fatorial de um número:
Estruturas de Dados Aula 11: TAD Pilha
Árvore Binária de Busca
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática Disciplina: Estrutura de Dados Professor: Cheli dos S. Mendes da Costa Listas.
Universidade do Vale do Rio dos Sinos - São Leopoldo -
BCC 101 – Matemática Discreta I
Estruturas de Dados Aula 8: Tipos Abstratos de Dados 30/04/2014.
Estruturas de Dados Aula 17: Estruturas Genéricas
Estruturas de Dados Aula 15: Árvores
Estruturas de Dados Aulas 3 e 4: Uso da memória e Vetores
Recursividade Profs. De Prog2 e Lab2.
Copyright 1998, Departamento de Informática da UFPE. Todos os direitos reservados sob a legislação em vigor. Variáveis e métodos estáticos, Passagem de.
Estruturas de Dados Aula 9 -2: Listas simplesmente encadeadas sem sentinela e sem cabeçalho 19/06/2013.
Estruturas de Dados Aula 10: Listas (parte 2) 07/05/2014.
Algoritmo e Estrutura de Dados I
Professor Luiz José Hoffmann Filho
Estrutura de Dados Prof. André Cypriano M. Costa
Estrutura de Dados Prof. André Cypriano M. Costa
Recursividade e análise Cristiano Arbex Valle Vinicius Fernandes dos Santos
Transcrição da apresentação:

Estruturas de Dados Aula 14: Recursão 04/06/2014

Fontes Bibliográficas Livros: –Projeto de Algoritmos (Nivio Ziviani): Capítulo 2; –Estruturas de Dados e seus Algoritmos (Szwarefiter, et. al): Capítulo 1; –Algorithms in C (Sedgewick): Capítulo 5; Slides baseados nas aulas de Sedgewick (

Máximo Divisor Comum mdc (p, q): encontre o maior divisor comum entre p e q; Ex.: mdc (4032, 1272) = 24 = 2 2 x 3 1 –4032 = 2 6 x 3 2 x 7 1 –1272 = 2 3 x 3 1 x 53 1 Uso de mdc: –Simplificação de frações: 1272/4032 = 53/168 –Importante em mecanismos de criptografia

Introdução O que é recursão? – É um método de programação no qual uma função pode chamar a si mesma –Relação estreita com árvore e pilha Por que precisamos aprender recursão? –Paradigma de programação poderoso –Nova maneira de pensar Muitas estruturas têm natureza recursiva: –Estruturas encadeadas –Fatorial, máximo divisor comum –Uma pasta que contém outras pastas e arquivos

Introdução (cont.) Uma forma visual de recursão conhecida como efeito Droste

Introdução (cont.)

Máximo Divisor Comum (2) Algoritmo de Euclides mdc (p, q) = mdc (4032, 1272) = mdc (1272, 216) mdc (216, 192) mdc (192, 24) mdc (24, 0) 24 pse q =0 mdc (q, p%q) caso contrario - caso base - passo de redução, converge para o caso base / 1272 = 3 x

Máximo Divisor Comum (3) mdc (p, q) = pse q =0 mdc (q, p%q) caso contrario - caso base - passo de redução, converge para o caso base p = 8x q = 3x mdc mdc (8x, 3x) mdc (3x, 2x) mdc (2x, x) mdc (x,0) mdc (p, q) = x

Máximo Divisor Comum (4) mdc (p, q) = Implementação em C int mdc (int p, int q) { if (q == 0) return p; //caso base else return mdc(q, p % q); //passo de redução } pse q =0 mdc (q, p%q) caso contrario - caso base - passo de redução, converge para o caso base

Memória abab “constante”“constante” Sist.OperacionalSist.Operacional HeapPointer Início da Área Alocável StackPointer Inicio da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes

Sist.OperacionalSist.Operacional StackPointer Inicio da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes Programa: int mdc (int p, int q) { if (q == 0) return p; //caso base else return mdc(q, p % q); //passo de redução } main () { int n = mdc(6, 4); }

Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); }

Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) &mdc- #2 (?) p (4) q (2) Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); }

Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) &mdc- #2 (?) p (4) q (2) Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } &mdc- #3 (?) p (2) q (0)

Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) &mdc- #2 (?) p (4) q (2) &mdc- #3 (2) p (2) q (0)

Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) &mdc- #2 (2) p (4) q (2)

Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (?) &main- #1 (?) p (6) q (4) &mdc- #2 (2) p (4) q (2) vale 2!

Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n &main- #1 (2) p (6) q (4)

Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n &main- #1 (2) p (6) q (4) Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } vale 2!

Programa: Programa: int mdc (int p, int q) { if (q == 0) return p; else return mdc(q, p % q); } main () { int n = mdc(6, 4); } Sist.Operacional StackPointer Topo da Pilha Topo da Memória Base da Memória Variáveis estáticas Código objeto Constantes n (2) vale 2!

Gráficos Recursivos

Árvore H

Árvore-H de ordem n –Desenha uma letra H –Recursivamente desenha 4 árvores-H da ordem de n-1 (e metade do tamanho), cada árvore conectada em um “topo” (tip). ordem 1 ordem 2 ordem 3

Implementação Recursiva da Árvore H (em C) void draw(int n, double tam, double x, double y) { if (n == 0) return; //condição de parada double x0 = x - tam/2; double x1 = x + tam/2; double y0 = y - tam/2; double y1 = y + tam/2; DesenhaLinha(x0, y, x1, y); DesenhaLinha(x0, y0, x0, y1); DesenhaLinha(x1, y0, x1, y1); draw(n-1, tam/2, x0, y0); draw(n-1, tam/2, x0, y1); draw(n-1, tam/2, x1, y0); draw(n-1, tam/2, x1, y1); } desenha o H centralizado em (x, y) recursivamente desenha 4 Hs com a metade do tamanho

Animação Árvore H

Torres de Hanói

Objetivo Mover os discos do pino mais a esquerda para o pino da direita –Somente um disco por vez pode ser movido; –Um disco pode ser colocado num pino vazio ou sobre um disco de tamanho maior; InícioFinal Torres de Hanói: animação

Torres de Hanói: Solução Recursiva

Lenda das Torres de Hanói Mundo vai acabar quando um grupo de monges conseguirem mover 64 discos de ouro em 3 pinos de diamante. Algoritmos de computação irão ajudar a resolver o problema?

Torres de Hanói: Implementação Recursiva void moves (int N, boolean left) // N=número do disco, left no pino 1 = pino 3 (cíclico) { if (N == 0) return; // se não houver discos, retorna moves(N-1, !left); if (left) printf(“Disco %d left”, N); else printf(“Disco %d right”, N); moves (N-1, !left); }

Torres de Hanói: Implementação Recursiva (para 3 discos) moves (3, left) moves (2, right) moves (1, left) moves(0,right) “Disco 1 left” “Disco 2 right” moves (1, left) moves(0,right) “Disco 1 left” “Disco 3 left” moves (2, right) moves (1, left) moves(0,right) “Disco 1 left” “Disco 2 right” moves (1, left) moves(0,right) “Disco 1 left”

Torres de Hanói: árvore de recursão

Torres de Hanói: Propriedades da solução Leva h n = 2 n – 1 “moves” para resolver o problema com n discos: h n = h n h n-1 ; O algoritmo revela um fato: –São necessários 585 bilhões de anos para n=64 (considerando que cada movimento de disco leve 1 segundo, os monges não cometam erros e que os monges saibam exatamente para onde movimentar o disco, sem pestanejar) (crescimento exponencial) Outro fato: qualquer solução possível para as torres de Hanói levará no mínimo esse tempo!

Dividir para Conquistar Consiste em dividir o problema em problemas menores Problemas menores são resolvidos recursivamente usando o mesmo método Resultados são combinados para resolver problema original Vários algoritmos são resolvidos com essa técnica (e.x., quicksort, mergesort)

Pontos Negativos da Recursão Considere a sequência de Fibonacci: 0,1,1,2,3,5,8,13,21,34...

Sequência de Fibonacci

Sequência de Fibonacci e a Natureza

Solução Recursiva? long F(int n) { if (n == 0) return 0; if (n == 1) return 1; return F(n-1) + F(n-2); } -> Código muito ineficiente! -> Leva muito tempo para computar F(50)!

Problema com Recursão Pode facilmente levar a soluções incrivelmente ineficientes! F(50) é chamado uma vez F(49) é chamado uma vez F(48) é chamado 2 vezes F(47) é chamado 3 vezes F(46) é chamado 5 vezes F(45) é chamado 8 vezes... F(1) é chamado 12,586,269,025 vezes

Resumindo Como escrever programas recursivos simples? –Condição de parada, passo da recursão –Use desenhos Dividir para conquistar –Técnica elegante de resolver problemas (não somente recursivos)

Implementação Recursiva de Listas Considere a lista sem sentinela e sem cabeçalho Definição recursiva: –Uma lista é: Uma lista vazia; ou Um elemento seguido de uma (sub)-lista

Implementação Recursiva de Listas Exemplo – função imprime –Se a lista for vazia, não imprime nada –Caso contrário: Imprime o conteúdo da primeira célula (l->Item ou l- >Item.campo) Imprime a sub-lista dada por l->Prox, chamando a função recursivamente

Implementação Recursiva de Listas /* Função imprime recursiva */ void lst_imprime_rec (TipoLista* l) { if ( !lst_vazia(l)) { /* imprime primeiro elemento: lista de inteiros */ printf(“Item: %d\n”,l->Item); /* imprime sub-lista */ lst_imprime_rec(l->Prox); }

Implementação Recursiva de Listas Exemplo – função retira –retire o elemento, se ele for o primeiro da lista (ou da sub-lista) –caso contrário, chame a função recursivamente para retirar o elemento da sub-lista

Implementação Recursiva de Listas /* Função retira recursiva */ TipoLista* lst_retira_rec (TipoLista* l, int v){ if (!lst_vazia(l)) { /* verifica se elemento a ser retirado é o primeiro */ if (l->Item == v) { TipoLista* t = l; /* temporário para liberar */ l = l->Prox; free(t); } else { /* retira de sub-lista */ l->Prox = lst_retira_rec (l->Prox,v); } return l; }

Implementação Recursiva de Listas Exemplo – função que testa igualdade entre duas listas int lst_igual (TipoLista* l1, TipoLista* l2) –se as duas listas dadas são vazias, são iguais –se não forem ambas vazias, mas uma delas é vazia, são diferentes –se ambas não forem vazias, teste: se informações associadas aos primeiros nós são iguais se as sub-listas são iguais

Implementação Recursiva de Listas boolean lst_igual (TipoLista* l1, TipoLista* l2){ if (l1 == NULL && l2 == NULL) return TRUE; if (l1 == NULL || l2 == NULL) return FALSE; boolean itemIgual= l1->Item == l2->Item; if( !itemIgual ) return FALSE; return lst_igual(l1->Prox, l2->Prox); }