Академический Документы
Профессиональный Документы
Культура Документы
2
Algoritmos Iterativos vs. Recursivos
Algoritmos Iterativos
Um algoritmo iterativo usa estruturas de repetio (ciclos) para resolver problemas
Exemplo: A funo factorial static int factorial (int n) { static factorial int fact = 1; int for (int i=2; i<=n, i++) for int int fact = fact * i; return fact; return }
Algoritmos Recursivos
Um algoritmo recursivo possui a caracterstica de invocar-se a sim prprio repetidamente at que certa condio seja satisfeita
Exemplo: A funo factorial
static int factorial (int n) { static factorial if (n == 0) if return 1; return else else factorial(n-1); return n * factorial return factorial }
Algoritmos e Estruturas de Dados,
Uma funo recorrente inclui uma instruo de deciso que decide se parar o continuar a recorrncia.
rvore de Recorrncia
Clculo de 4!
4! = 4 x 3! = 4 x 6 = 24
3!=6
4!
4! = 4 x 3!
3!
2!=2
3! = 3 x 2!
2!
1!=1
2! = 2 x 1!
1!
Desenhos extrados de http://www.lcc.uma.es/~lopez/modular/recursion/ transp_recursion.pdf Autor: Pablo Lpes 0!=1
1! = 1 x 0!
0!
2007-2008 , Gladys Castillo
4
Caixa de Execuo
Clculo de 4!
4! = 24
O valor de 4! calculado no regresso das sucessivas invocaes da funo recursiva, pelo que 4! = 1 x 1 x 2 x 3 x 4 = 24 factorial(4) = 4 x factorial(3) =4x6 factorial(3) = 3 x factorial(2) =3x2 factorial(2) = 2 x factorial(1) =2x1 factorial(1) = 1 x factorial(0) =1x1 factorial(0) = 1
Cada caixa representa o espao de execuo de uma nova chamada da funo. Em total so efectuadas 5 chamadas e 4 multiplicaes
Memria utilizada: 4 bytes x 5 Cada chamada gera uma cpia do valor do parmetro n pelo que no eficiente em termos da utilizao da memria
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
Sucesso de Fibonacci
Esta sucesso foi estudada pelo matemtico Leonardo Fibonacci (1170-1250), quando conjecturava acerca do crescimento de uma populao de coelhos.
F(n) =
static int fibonacci (int n) { static fibonacci int f, f1, f2; int if (n<=2) return 1; return if f1 = 1; f2 = 1; for (int i=3; i<=n, i++){ for int int f = f1 + f2; f1 = f2; f2 = f; } return f; return }
static int fibonacci (int n) { static fibonacci if (n <= 2) if return 1; return else else return fibonacci (n-1) + fibonacci (n-2) ; return }
O algoritmo recursivo mais elegante e parecido com a definio da sucesso, mas muito menos eficiente do que a sua verso iterativa
rvore de Recorrncia
Clculo do Fibonacci de 6
A soluo recursiva ineficiente pois para calcular o Fibonacci de 6, calcula repetidamente valores intermdios:
2 vezes F(4), 3 vezes F(3), 5 vezes F(2) e 3 vezes o F(1) F(6) = 8
hhhhh
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
9
Tringulo de Pascal
C ( n, k ) =
n! ( n k )!k!
Cada elemento, com excepo dos elementos terminais da cada linha calculado atravs da soma dos valores da linha anterior, ou seja: C(n,0) = C(n, n) = 1 C(n, k) = C(n-1, k-1) + C (n-1, k) ,
Algoritmos e Estruturas de Dados,
se 0<k<n
10
Trabalho para casa: 1. Imprimir o tringulo de Pascal usando o algoritmo recursivo 2. Implementar a verso iterativa para o clculo do coeficiente binomial
11
static void inverterNumero static void inverterNumero(int n){ inverterNumero while (n >0){ while System.out.print(n%10); n /=10; } }
static void inverterNumero static void inverterNumero(int n){ inverterNumero System.out.print(n%10); if (n / 10 > 0) if inverterNumero(n inverterNumero /10); inverterNumero } }
O algoritmo recursivo mais elegante e mais fcil
12
Tipos de Recursividade
Existem trs tipos de algoritmos recursivos:
1. Recursividade directa:
o valor de retorno o valor de retorno da chamada recursiva (no existem operaes pendentes)
13
Torres de Hanoi
Edouard Lucas, 1883
Deslocar todos os discos da Torre A para a Torre C, um de cada vez Utilizar a Torre B como auxiliar Nunca colocar nenhum disco, sobre outro menor
Incio
Torre A
Torre B
Torre C
Fim
Torre A
Torre B
Torre C
14
Torres de Hanoi
Algoritmo Recursivo
Mover n discos de A para C usando B como auxiliar
mover n-1 discos de A para B usando C como auxiliar mover 1 disco de A para C mover n-1 discos de B para C usando A como auxiliar
recurso
mover n -1 discos de A para B usando C como auxiliar
A B C
recurso
mover n-1 discos de B para C usando A como auxililar
A B C
15
Torres de Hanoi
Algoritmo Recursivo em Java
static void torresHanoi (int n, int origem, int auxiliar, int destino) { if (n == 1){ moverDisco (origem, destino); } else { torresHanoi (n-1, origem, destino, auxiliar); moverDisco (origem, destino); torresHanoi (n-1, auxiliar, origem, destino); } } static void moverDisco (int origem, int destino){ System.out.println (desde : + origem + -}
para: + destino);
ini
fim
aplicar Quicksort
Escolha do piv:
O 1 elemento da sequncia O elemento do mdio e depois colocar o piv por forma a que ini, medio e fim fiquem por ordem crescente
2007-2008 , Gladys Castillo
17
O Algoritmo Quicksort
static void quickSort (int [ ] seq, int ini, int fim) { int if (seq.length == 1 || ini > fim) return; if (seq.length == 2) { /* sequncia com 2 elementos */ trocar(seq, ini, fim); if (seq[ini] > seq[fim]) trocar return; return; } /* calcular o ndice do piv no meio */ int medio = (ini + fim) /2; /* colocar o piv por forma a que ini, medio e fim fiquem por ordem crescente */ colocarPivo (seq, ini, medio, fim); return; if (seq.length == 3) return // se sequncia com 3 elementos ento j est ordenada /* dividir a sequencia: na parte esquerda colocam-se os valores menores do que o piv na parte direita, os valores maiores do que o piv */ medio = dividirSeq (seq, ini, medio, fim); quickSort (seq, ini, medio-1); // invocao recursiva para a parte esquerda da sequncia quickSort (seq, medio+1, fim); // invocao recursiva para a parte direita da sequncia
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
18
O Algoritmo Quicksort
Mtodos: trocar e colocarPivot
private static void trocar (int[ ] seq, int ind1, int ind2){ int temp = seq[ind1]; seq[ind1] = seq[ind2]; seq[ind2] = seq[temp]; } private static void colocarPivo (int[ ] seq, int ini, int medio, int fim){ /* colocar o piv por forma a que ini, medio e fim fiquem por ordem crescente */ trocar(seq, ini, medio); if (seq[ini] > seq[medio]) trocar trocar(seq, ini, fim); if (seq[ini] > seq[fim]) trocar trocar(seq, medio, fim); if (seq[medio] > seq[fim]) trocar }
19
O Algoritmo Quicksort
Mtodo: dividirSeq (I)
private static int dividirSeq ( int[ ] seq, int ini, int medio, int fim ){ int indEsq = ini + 1; int indDir = fim - 1; while (indEsq < indDir) { // 1. procurar elementos na parte esquerda maiores do que piv while (indEsq < medio){ break; if (seq[indEsq] > seq[medio]) break indEsq++; } // 2. procurar elementos na parte direita menores do que piv while (indDir > medio){ break; if (seq[indDir] < seq[medio]) break indDir--; }
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
20
10
O Algoritmo Quicksort
Mtodo: dividirSeq (II)
// 3. trocar elementos segundo 3 casos Caso I: existe um elemento na if (indEsq != medio && indDir != medio){ parte esquerda maior do que piv e um elemento na parte direita trocar (seq, indEsq, indDir); menor do que piv ento trocar os indEsq++; indDir--; elementos } else if (indEsq == medio && indDir != medio){ trocar (seq, medio,indDir); Caso II: existe um elemento na parte direita menor do que piv, medio++; ento trocar o elemento de ndice trocar(seq, medio,indDir); if (medio != indDir) trocar indDir com o piv e deslocar o indEsq = medio; // a parte esquerda j est OK piv uma posio direita } else if (indEsq != medio && indDir == medio){ trocar(seq, medio,indEsq); trocar Caso III: existe um elemento na medio --; parte esquerda maior do que piv, if (medio != indEsq) trocar (seq, medio, indEsq); ento trocar o elemento de ndice indEsq com o piv e deslocar o indDir= medio; }// a parte direita j est Ok piv uma posio esquerda } // fecho while return medio;
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
21
medio = 4 2 32 8
Trocar 145 com 8 Como 209, 42 e 145 no esto ordenados Trocar 209 com 42 e 209 com 145
42 55 25 fim = 9 8 55 209
15
ini = 0 42 330 25 15
medio = 4 145 2 32
42 55 25
15
piv 145: na parte esquerda colocam-se os valores menores do que o piv e na parte direita, os valores maiores do que o piv
indEsq = 5 42 55 25 indEsq = 6 15 8
145 32
indDir = 8 8 55 209
medio = 6 15 8 2
42 55 25
15
11
Ordenao Quicksort
Complexidade
Este algoritmo considerado uns dos melhores algoritmos de ordenao, pois apesar de, no pior caso, ser um algoritmo quadrtico, no caso mdio tem uma complexidade linear logartmica de comparaes, ou seja de ordem O(n log2 n)
n de comparaes
Outro algoritmo recursivo de ordenao de complexidade linear logartmica tambm muito popular o algoritmo MergeSort (ordenao por fuso). Pode ler sobre este algoritmo no livro Programao avanada usando C de Antonio Rocha, pag 184
23
12
25
Bibliografia
C. Thomas Wu: An introduction to Object-Oriented Programming with Java, third edition. Chapter 15: Recursive Algorithms
slides online:
http://highered.mcgraw-hill.com/sites/0072518847/student_view0/chapter15/powerpoint.html
Antnio Adrego da Rocha: Programao Avanada usando C. Tecnologias da Informao. FCA Editora de Informtica, 2006 Captulo 1. Recursividade, Captulo 6.6. Algoritmos de ordenao recursivos
Nota: Algumas das figuras usadas nos acetatos foram extradas destas fontes
Algoritmos e Estruturas de Dados, 2007-2008 , Gladys Castillo
26
13
Caixa de Execuo
Clculo de 4!
true
O valor de palindromo(somos) calculado no regresso das sucessivas invocaes da funo recursiva, pelo que palindromo(somos) = (s == s) && (o == o) && true = true palindromo(somos) = (s == s) && palindromo(omo) = true && palindromo(omo) = (o == o) && palindromo(m) = true && true true
palindromo(m) = true
27
14