Revisão: Tipo Abstrato de Dados Recursividade

Propaganda
Algoritmos e Estrutura de Dados II
Revisão:
Tipo Abstrato de Dados
Recursividade
Profa Karina Oliveira
[email protected]
Introdução
• Estudo das estruturas de dados envolve
dois objetivos complementares:
– Identificar e desenvolver estruturas de
dados, determinando os tipos de problemas
que podem ser resolvidos com estas
estruturas;
– Estudar formas de implementação das
estruturas de dados nos computadores.
Algoritmos e Estrutura de Dados II - Karina Oliveira
2
Tipo Abstrato de Dados (TAD)
• TAD constitui um modelo matemático
que pode ser empregado para modelar e
solucionar problemas do mundo real
– Conjunto de valores e operações que podem
ser aplicadas sobre estes valores
• TAD não considera:
– Representação dos valores na memória do
computador (organização dos bits);
– Tempo necessário para aplicar as operações.
Algoritmos e Estrutura de Dados II - Karina Oliveira
3
Tipo Abstrato de Dados (TAD)
• Aspecto mais relevante na programação é
a implementação do TAD em um tipo de
dado concreto
• Exemplo: O tipo abstrato dos inteiros
– Dados: {...,-3,-2,-1,0,1,2,3,...}
– Operações: {+,-,*,/}
• Obs.: Apenas um subconjunto dos
números inteiros pode ser implementado.
Algoritmos e Estrutura de Dados II - Karina Oliveira
4
Recursividade - Fundamentos
• Algoritmo que para resolver um
problema divide-o em subproblemas mais
simples estas soluções requerem a
aplicação dele mesmo
• Recursividade Direta ou Indireta
R ≡ [C, R]
R1 ≡ [C, R2]
R2 ≡ [C, R3]
R3 ≡ [C, R4]
...
Rn ≡ [C, R1]
Algoritmos e Estrutura de Dados II - Karina Oliveira
5
Recursividade - Fundamentos
• Todo algoritmo recursivo deve terminar
após ter executado uma quantidade
finita de passos
– Deve existir uma expressão lógica que
deverá ser falsa em algum instante
permitindo que a recursão termine
– R ≡ [C, T→R], rotina R só vai ser chamada
se o teste T for verdadeiro
Algoritmos e Estrutura de Dados II - Karina Oliveira
6
Recursividade - Fundamentos
• Rotina recursiva deve ter:
– Solução trivial: não usa recursão. Resolvida
por um conjunto de comandos C.
– Solução geral: parte do problema que é em
essência igual ao original, porém menor. A
solução, neste caso, pode ser obtida por
uma chamada recursiva R(x-1)
Algoritmos e Estrutura de Dados II - Karina Oliveira
7
Recursividade - Fundamentos
• Rotina recursiva deve ter:
– Exemplo: Fatorial de número natural
• Solução trivial: 0! = 1 {dada por definição}
• Solução geral: n! = n*(n-1)! {requer aplicação da
rotina para (n-1)!}
– Código Exemplo:
int fatorial (int n){
if (n == 0) return 1;
else return (n * fatorial(n - 1));
}
Algoritmos e Estrutura de Dados II - Karina Oliveira
8
Quando aplicar Recursão?
• Deve-se analisar o problema para
verificar se é válido usar recursão
• Quando bem utilizada a recursão torna o
algoritmo elegante, simples e conciso
• Porém solução iterativa é mais eficiente,
pois cada vez que a rotina é chamada,
todas as variáveis locais são recriadas
• Portanto, deve-se decidir entre
recursão e iteração
Algoritmos e Estrutura de Dados II - Karina Oliveira
9
Quando aplicar Recursão?
1) Eliminar recursão de cauda
•
•
Definição: recursividade se encontra no
final do código criando um “looping”
Exemplo:
int fatorial (int n){
if (n == 0) return 1;
else return (n * fatorial(n - 1));
}
•
Nesse caso, a recursão é menos eficiente que a
iteração.
Algoritmos e Estrutura de Dados II - Karina Oliveira
10
Quando aplicar Recursão?
1) Eliminar recursão de cauda
•
•
Deve-se usar uma estrutura de repetição
que esteja condicionada à expressão de
teste usada na versão recursiva
Exemplo do fatorial:
int fatorial (int n){
int result = 1;
while(n > 0){
result = result * n;
n = n – 1;
}
return result;
}
Algoritmos e Estrutura de Dados II - Karina Oliveira
11
Quando aplicar Recursão?
• Pilhas e Rotinas Recursivas
– Controle de chamadas e retornos de rotinas
é feito através de uma pilha criada e
mantida, automaticamente, pelo sistema
– Sempre que uma rotina é evocada, não
apenas o endereço de retorno é empilhado,
mas todas as suas variáveis locais são
recriadas na pilha
Algoritmos e Estrutura de Dados II - Karina Oliveira
12
Quando aplicar Recursão?
• Pilhas e Rotinas Recursivas
– fatorial(4)
0
3
n
4
n
4
n
1
1
2
2
2
3
3
3
4
n
4
n
4
– Obs.: Em cada momento, apenas a última
variável n criada pode ser acessada!
Algoritmos e Estrutura de Dados II - Karina Oliveira
13
Pilhas e Rotinas Recursivas
• Relação entre pilhas e recursão
struct LstOrd{
int num;
struct LstOrd *prox;
}
//Versão com recursividade
void show (LstOrd *lista){
if (lista != null){
show(lista->prox);
cout << (lista->num);
}
}
Algoritmos e Estrutura de Dados II - Karina Oliveira
14
Pilhas e Rotinas Recursivas
• Relação entre pilhas e recursão
// Versão com pilha
void show_pilha (LstOrd *lista){
int num;
Pilha p;
push: insere um novo
init(P);
elemento no topo da pilha
while (lista != null){
pop: remove um elemento do
push(P, lista->num);
topo da pilha
lista = lista->prox;
init: inicializa a pilha no
}
estado vazia
while(!isEmpty(P)){
isEmpty: verifica se a pilha
num = pop(P);
está vazia
cout << num;
}
}
Algoritmos e Estrutura de Dados II - Karina Oliveira
15
Quando aplicar Recursão?
• Eliminar recursão utilizando em seu
lugar comandos de repetição e,
eventualmente pilhas
– Nova versão se torna mais rápida que a
recursiva
• O uso de muitas pilhas e muitos
comandos de repetição, tornará o código
muito complexo
– Versão recursiva nesse caso, é mais clara,
simples e concisa
Algoritmos e Estrutura de Dados II - Karina Oliveira
16
Exercício
• Escreva uma função não recursiva, ou seja,
iterativa para a seguinte função:
int func (int i){
int result;
if (i > 1){
result = i + func(i-1);
}else{
result = 1;
}
return result;
}
Algoritmos e Estrutura de Dados II - Karina Oliveira
17
Download