Você está na página 1de 11

Revisões – Java

Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Análise da Complexidade de
Algoritmos
(revisões)

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Algoritmos e Estruturas de Dados II


– Licenciatura em Engenharia Informática e Computação –

www.fe.up.pt/∼rcamacho/cadeiras/AED2

Rui Camacho
LIACC/FEUP Universidade do Porto
rcamacho@fe.up.pt

Fevereiro 2005

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Análise de Algoritmos

I Como obter a solução de um problema?


I Especificação do problema: descrição da relação entre os
valores de entrada e os de saı́da
I Algoritmo: procedimento computacional que toma os valores
de entrada e os transforma nos de saı́da
I Análise de algoritmos
I Recursos necessários para executar o procedimento respectivo
I Tempo de processamento
I Espaço de armazenamento
I Avaliação independente da máquina
I Baseada na taxa de crescimento dos recursos com o
tamanho dos dados de entrada

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Análise da Complexidade de Algoritmos

I Tempo e Espaço
I Exemplos
I Notação O()

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Crescimento de funções

I Comparar crescimento
I Comparação de funções em
pontos particulares: muito Função Designação
dependente dos coeficientes c Constante
I Comparação relevante: taxas log N Logaritmo
de crescimento log2 N Quadrado do
I Avaliar taxa de crescimento Logaritmo
N Linear
I em funções com vários termos N log N N log N
o crescimento é determinado N2 Quadrática
pelo termo de crescimento N3 Cúbica
mais rápido 2N Exponencial
I Coeficientes constantes
influenciam o andamento
inicial

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Análise de Algoritmos
Considerações gerais

I Geralmente compromisso entre Espaço ocupado/Tempo de execução


ex: se quero mais rápido uso estruturas de dados auxiliares (uso de redundância
é habitual)
I Estruturas de Dados e Algoritmos essencialmente para problemas
complexos. Para problemas simples qq serve
ex: espaço de soluções pequeno uso “gerar e testar”
I Perspectiva pragmática:
se existe feito então use
senão se quase existe feito então adapte
senão desenvolva
I Adopte sempre a solução mais simples. Não complicar desnecessariamente

Einstein Principle: “A scientific theory should be as simple as


possible, but no simpler.” – AlbertEinstein

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Crescimento de função composta

Regras
1. se T1(n) = O( f(n) ) e T2(n) = O( g(n) )
I T1(n) + T2(n) = max( O( f(n) ), O( g(n) ) )
I T1(n) * T2(n) = O( f(n) * g(n) )
2. se T(x) é um polinómio de grau n, T(x) = Θ (xn )
3. logk n = O(n), para qualquer k (logaritmos crescem devagar)

I não usar constantes ou termos de ordem inferior dentro de um O(*)


f (n)
I crescimento relativo pode ser determinado com limn→∞ g (n)

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Notação O(*)

Notação para o crescimento relativo de funções


I T(n) = O(f(n)) se existem constantes c e n’ tais que T(n) ≤ c f(n)
para n ≥ n’
I T(n) = Ω(f(n)) se existem constantes c e n’ tais que T(n) ≥ c f(n)
para n ≥ n’
I T(n) = Θ(f(n)) se e só se T(n) = O(f(n)) e T(n) = Ω(f(n))
I T(n) = o(f(n)) se T(n) = O(f(n)) e T(n) 6= Θ(f(n))

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima

(valores “grandes” de N do livro do Mark Weiss )

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima

(valores “pequenos” de N do livro do Mark Weiss )

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Número de operações
I Operações no ciclo
interior
I inicialização
Operações de incremento da soma:
k=i (N - tamanho do vector)
I teste k <= j
I incremento Número de ternos (i, j, k) com
1≤i≤j≤k≤N
da soma
é N (N-1) (N-2) /6
thisSum += logo O(N3 ) para o algoritmo
a[k]
I incremento Ciclos exteriores têm efeito multi-
plicativo sobre operações no ciclo
k++ interior
I Operações
dominantes O(N) operações em cada ciclo en-
caixado logo O(N3 ) para o algoritmo
I teste e
incrementos
I inicialização
Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima – cúbico

/**
* Cubic maximum contiguous subsequence sum algorithm.
* seqStart and seqEnd represent the actual best sequence.
*/
public static int maxSubSum1(int [] a){
int maxSum = 0;

for( int i = 0; i < a.length; i++ )


for( int j = i; j < a.length; j++){
int thisSum = 0;
for( int k = i; k <= j; k++ )
thisSum += a[k];

if(thisSum > maxSum){


maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
return maxSum;
}
Rui Camacho Algoritmos e Estruturas de Dados II – LEIC
Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Novos Algoritmos
I Linear
I Requer melhor uso das
caracterı́sticas do problema
I Observações
I Quadrático
I Observação: soma
I Se Ai,j é uma
dassubsequências no ciclo interior subsequência com
é repetida custo negativo, Ai,q
I Cada soma pode ser obtida com q>j não é a
apartir da anterior subsequência máxima
I as subsequências
I o ciclo interior reduz-se
a 1 operação -tempo contı́guas da máxima
constante têm custo negativo
I quando se encontra
I passa-se de O(N3 ) para
O(N2 ) umasubsequência de
custo negativo pode
recomeçar-se a
pesquisa noelemento
Rui Camacho Algoritmos e Estruturas de Dados II – LEIC
seguinte
Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima
– quadrático

/**
* Quadratic maximum contiguous subsequence sum algorithm.
* seqStart and seqEnd represent the actual best sequence.
*/
public static int maxSubSum2(int [] a){
int maxSum = 0;

for( int i = 0; i < a.length; i++){


int thisSum = 0;
for( int j = i; j < a.length; j++){
thisSum += a[ j ];

if(thisSum > maxSum){


maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
}
Rui Camacho Algoritmos e Estruturas de Dados II – LEIC
Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima – recursivo

/**
* Recursive maximum contiguous subsequence sum algorithm.
* Finds maximum sum in subarray spanning a[left..right].
* Does not attempt to maintain actual best sequence.
*/
private static int maxSumRec(int [] a, int left, int right){
int maxLeftBorderSum = 0, maxRightBorderSum = 0;
int leftBorderSum = 0, rightBorderSum = 0;
int center = ( left + right ) / 2;

if(left == right) // Base case


return a[left] > 0 ? a[left] : 0;

int maxLeftSum = maxSumRec(a, left, center);


int maxRightSum = maxSumRec(a, center + 1, right);

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima – linear

/**
* Linear-time maximum contiguous subsequence sum algorithm.
* seqStart and seqEnd represent the actual best sequence.
*/
public static int maxSubSum3(int [] a){
int maxSum = 0;
int thisSum = 0;

for( int i = 0, j = 0; j < a.length; j++){


thisSum += a[j];

if(thisSum > maxSum){


maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
else if(thisSum < 0){
i = j + 1;
thisSum = 0;
}
}
Rui Camacho Algoritmos e Estruturas de Dados II – LEIC
Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima
– recursivo (métodos auxiliares)–

/* Return maximum of three integers. */


private static int max3(int a, int b, int c){
return a > b ? a > c ? a : c : b > c ? b : c;
}
/* Driver for divide-and-conquer maximum contiguous
* subsequence sum algorithm. */
public static int maxSubSum4(int [] a){
return maxSumRec(a, 0, a.length - 1);
}

“Data Structures & Algorithm Analysis in Java”, Weiss

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima – recursivo (cont.)

for(int i = center; i >= left; i–) {


leftBorderSum += a[ i ];
if(leftBorderSum > maxLeftBorderSum)
maxLeftBorderSum = leftBorderSum;
}

for(int i = center + 1; i <= right; i++){


rightBorderSum += a[i];
if(rightBorderSum > maxRightBorderSum)
maxRightBorderSum = rightBorderSum;
}

return max3(maxLeftSum, maxRightSum,


maxLeftBorderSum + maxRightBorderSum);
}

“Data Structures & Algorithm Analysis in Java”, Weiss

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Eficiência de Estruturas de Dados

Acesso Comentário
Pilha Apenas ao elemento mais recente Muito rápido
O(1)
Fila Apenas ao elemento menos recente Muito rápido
O(1)
Lista Ligada Qualquer item O(N)
Árvore de Qualquer item por nome ou ordem Caso médio; em árvores
Pesquisa O(log N) especiais é pior caso
Tabela de Qualquer item por nome Quase garantido
Dispersão O(1)
Fila de Acesso ao mı́nimo: O(1) Inserção: O(1) caso médio,
Prioridade Apagar mı́nimo: O(log N) O(log N) pior caso

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Subsequência Máxima
– recursivo (teste)–

public final class MaxSumTest{


static private int seqStart = 0;
static private int seqEnd = 0;

public static void main(String [] args){


int a[] = {4, -3, 5, -2, -1, 2, 6, -2};
int maxSum;

maxSum = maxSubSum1(a);
System.out.println(”Max sum is ” +maxSum+ ”; it goes”
+ ” from ” + seqStart + ” to ” +seqEnd);
maxSum = maxSubSum2(a);
System.out.println(”Max sum is ” +maxSum+ ”; it goes”
+” from ” + seqStart + ” to ” + seqEnd );
maxSum = maxSubSum3(a);
System.out.println(”Max sum is ” + maxSum + ”; it goes”
+” from ” + seqStart + ” to ” + seqEnd );
maxSum = maxSubSum4(a);
System.out.println(”Max sum is ” + maxSum);
}
}

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC


Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Pesquisa Binária- teste

public static void main(String [] args){


int SIZE = 8;
Comparable [] a = new MyInteger [ SIZE ];

for(int i = 0; i < SIZE; i++)


a[i] = new MyInteger(i * 2);
for(int i = 0; i < SIZE * 2; i++){
try {
System.out.println( ”Found ” + i + ” at ” +
binarySearch(a, new MyInteger(i)));
}
catch(ItemNotFound e){
System.out.println(i + ” not found” );
}
}
}
}

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Revisões – Java
Revisões – Complexidade
Revisões – Árvores Binárias de Pesquisa

Pesquisa Binária

import Supporting.*;
import Exceptions.*;
import Supporting.Comparable;

public class BinarySearch {


public static int binarySearch( Comparable [ ] a, Comparable x)
throws ItemNotFound
int low = 0;
int high = a.length - 1;
int mid;

while(low <= high){


mid = (low + high) / 2;

if(a[mid].compares(x) < 0)
low = mid + 1;
else if(a[mid].compares(x) ¿ 0)
high = mid - 1;
else return mid;
}

throw new ItemNotFound(”BinarySearch fails”);


}

Rui Camacho Algoritmos e Estruturas de Dados II – LEIC

Você também pode gostar