Carregar apresentação
A apresentação está carregando. Por favor, espere
PublicouKléber Campos Jardim Alterado mais de 6 anos atrás
2
2. Conceitos básicos A complexidade de algoritmos trata do esforço computacional de algoritmos. Além disso, ela fornece subsídios para escolher o melhor entre os algoritmos disponíveis para o problema. A complexidade em ordem assintótica avalia a complexidade do algoritmo quando o seu desempenho é mais crítico. Existem vários critérios de avaliação de um algoritmo como: quantidade de trabalho requerido, quantidade de espaço requerido, simplicidade, exatidão de resposta e otimalidade. Complexidade de Algoritmos
3
Visão geral do capítulo
2.1 Medidas de complexidade Introduz as idéias de complexidade pessimista (pior caso) e complexidade média, bem como as medidas de complexidade de tempo e de espaço. 2.2 Critérios de complexidade Introduz as idéias de operações fundamentais e de tamanho da entrada. Introduz também a idéia de comparação entre complexidades. 2.3 Ordens assintóticas Introduz as idéias de comportamento assintótico (notações O, e ), e examina algumas de suas propriedades. 2.4 Exemplos ilustrativos Ilustram as idéias anteriores com alguns exemplos de algoritmos. Complexidade de Algoritmos
4
2.1 Ideias básicas 2.1.1 Complexidade e desempenho de algoritmos
medidas de tempo e espaço. 2.1.1 Complexidade e desempenho de algoritmos A complexidade de um algoritmo é o reflexo do esforço computacional requerido para executá-lo. Esforço computacional mede a quantidade de trabalho, em termos de tempo de execução ou da quantidade de memória requerida. Complexidade de Algoritmos
5
Aspectos a considerar na determinação da complexidade de um algoritmo: um critério pode ser medir o tempo de execução, mas: uma pequena mudança no programa pode não representar uma mudança significativa no algoritmo, e velocidade de execução ser bastante afetada; dois programas comparados, primeiro numa máquina, depois em outra podem dar resultados diferentes; este critério é fortemente dependente tanto da implementação quanto da máquina. Uma alternativa útil é uma análise matemática das dificuldades intrínsecas da resolução computacional do problema. Complexidade de Algoritmos
6
2.1.2 Medidas de desempenho e complexidade
Uma das medidas de desempenho mais importante é o tempo de execução: complexidade de tempo. Outra é a complexidade de espaço, que usa como medida de desempenho a quantidade de memória necessária para execução do algoritmo. Espaços: a área para guardar as instruções, as constantes, as variáveis e os dados. Se os dados têm uma representação óbvia como uma matriz, são considerados para a análise de espaço somente os espaços extras. A memória usada por um programa, bem como o tempo requerido na sua execução é dependente da implementação. Complexidade de Algoritmos
7
2.2 Critérios de complexidade
Para medir a quantidade de trabalho realizado por um algoritmo, é escolhida uma operação significativa do algoritmo, chamada operação fundamental. Às vezes, é necessária mais de uma operação fundamental, talvez com pesos diferentes. Por exemplo, para um algoritmo de ordenação, uma operação fundamental natural é a comparação entre elementos quanto à ordem. Custo: esforço computacional do algoritmo sobre essa entrada. É dado pelo número de operações fundamentais executadas pelo algoritmo. 2.2.1 Desempenho de algoritmo O desempenho (em tempo) de um algoritmo pode ser medido pelo custo de suas seqüências de execução. Complexidade de Algoritmos
8
Exemplo 2.2.1. Máximo de tabela Algoritmo 2.2.1: Máximo de tabela
Procedimento Max(tab : tabela) {para máximo de tabela} { Entrada: tabela tab : vetor [ 1..n ] de Elmord . Saída: Mx = valor máximo em tab.} 1. Mx tab[1] ; {candidato a máximo} 2. para i de 2 até n faça {varre tabela: 2} 3. se Mx < tab[i] então Mx tab[i] fim-se ; {atualiza Mx} 4. fim-para ; {2: tabela varrida} 5. retorne-saída ( Mx ) {retorna valor máximo} 6. fim-Procedimento {fim do algoritmo: máximo de tabela} Análise: operação fundamental é a comparação < (no se da linha 3) Quantas vezes essa linha é executada ? Complexidade de Algoritmos
9
Dado um algoritmo a, considere os conjuntos:
D, de seus possíveis dados de entrada, e E, de todas as sequências de execuções de operações fundamentais. E as seguintes funções: Execução exec[ a ] : D E; exec[ a ]( d ) dá a seqüência de execuções de operações fundamentais para os dados d. Custo custo : E +; custo( s ) dá o comprimento da sequência s E, levando em conta os pesos das operações fundamentais. Desempenho desemp[a] : D +; desemp[ a ]( d ) := custo( exec[ a ]( d ) ) dá o custo (em operações fundamentais). O desempenho de um algoritmo com uma entrada mede o custo da execução do algoritmo sobre essa entrada. Complexidade de Algoritmos
10
2.2.2 Complexidade de algoritmo
Note que a função desemp : D + dá informação sobre cada entrada específica. O objetivo é associar um custo a cada tamanho de entrada, em vez de a cada entrada. Tamanho tam : D ; onde tam ( d ) mede o tamanho da entrada d D. Por exemplo: dfgdfgdfg para matrizes quadradas, tam(d) dá a ordem de d. para listas, tam(d) pode ser o comprimento de d. para um grafo, pode ser dado pelos número de vértices ou o número de arestas. para números a quantidade de caracteres (como bits) usada para codificá-los. Usando a função tam, pode-se condensar a informação dada pela função desemp[ a ] : D + em uma função aval[ a ] : +, de modo que para tam( d ) = n: aval[ a ]( n ) dá informação sobre desemp[ a ]( d ). Complexidade de Algoritmos
11
Qual avaliação devemos escolher?
Note que a função tam : D em geral não é inversível: costuma haver várias entradas com mesmo tamanho. Além disso, um algoritmo pode apresentar desempenhos distintos sobre várias entradas, apesar de elas terem o mesmo tamanho. Qual avaliação devemos escolher? Aqui entrarão os critérios de complexidade, como o do pior caso e o do caso médio. Complexidade de Algoritmos
12
A determinação de aval[a](n)
Dn := { d D / tam( d ) = n } é o conjunto das entradas com tamanho n. Em geral, a função desemp não é constante sobre o conjunto Dn. Dois critérios razoáveis são tomar o valor máximo ou o valor médio dentre esses. Complexidade Média A complexidade média (ou esperada) de um algoritmo a (notada cM[ a ] ou avalM[ a ]) é o valor médio de seus desempenhos sobre todas as entradas com tamanho n, usando-se como peso a probabilidade de ocorrência de cada entrada avalM[ a ] = onde prob( d ) dá a probabilidade de ocorrer a entrada d no conjunto Dn Complexidade de Algoritmos
13
Complexidade pessimista
A complexidade pessimista de um algoritmo fornece seu desempenho no pior caso: o pior desempenho que se pode esperar sobre todas as entradas com tamanho n. A complexidade pessimista (pior caso de um algoritmo a (notada cP[ a ] ou avalP[ a ]) é o valor máximo de seus desempenhos sobre todas as entradas com tamanho n: avalP[ a ]( n ) := Máx { desemp[ a ]( d ) / d Dn } Exemplo 2.2.2: Busca Sequencial O problema é procurar um valor (chave) em uma tabela tab para determinar se ch encontra-se ou não em tab. Aqui tab será um vetor de n elementos. Complexidade de Algoritmos
14
Algoritmo 2.2.2: Busca sequencial em tabela
Procedimento Busca_Seq(ch : Valor, tab : tabela) {busca sequencial em tabela} { Entrada: ch: Valor, tabela tab : vetor [ 1..n ] de Valor. Saída: achou, pos (achou = V se ch está em tab e tab[pos] = ch).} 1. i 0 ; achou F ; { inicialização } 2. repita {varre tabela: 5} 3 i i + 1 ; {incrementa índice} 4. se tab[i] = ch então achou V fim-se {compara com chave} 5. até achou ou i = n ; {2: tabela varrida} 6. se achou então pos i fim-se ; {verifica se achou chave} 7. retorne-saída( achou, pos ) {retorna saída} 8. fim-Procedimento {fim do algoritmo: busca seqüencial em tabela} Complexidade de Algoritmos
15
Operação fundamental: a comparação = (no se da linha 4) e como tamanho da entrada o tamanho n de tab. Se ch encontra-se: na 1a posição, Busca_Seq faz 1 comparação na 2a posição, Busca_Seq faz 2 comparações na ka posição, Busca_Seq faz k comparações na na posição (ou não está em tab), Busca_Seq faz n comparações. Assim, a complexidade no pior caso é n (linear no tamanho n da entrada). Se todos os elementos da tabela forem igualmente prováveis como chave, então o número médio de comparações será: Complexidade de Algoritmos
16
No pior caso, o critério anterior dá
cP = [ a ]( n ) := Máx { desemp[a]( d ) + / tam( d ) = n }; enquanto o critério relaxado dá cP [ a ]( n ) := Máx { desemp[a]( d ) + /tam( d ) ≤ n }. O critério relaxado dá uma cota superior para o anterior: cP = [ a]( n ) ≤ cP [ a ]( n ) n . Uma vantagem do critério relaxado é que é uma função monotônica: cP [ a ]( m ) ≤ cP [ a ]( n ) para m ≤ n. Os critérios de complexidade, entradas de tamanho exatamente n ou até n, costumam dar a mesma ordem em boa parte dos algoritmos, principalmente os eficientes. Esses critérios de complexidade dependem do custo e tamanho da entrada. Complexidade de Algoritmos
17
2.2.3 Comparação entre complexidades
Um problema pode ter mais de um algoritmo para resolvê-lo. Qual deles escolher? Fixada as operações fundamentais e função tamanho, a cada algoritmo a Î A temos: desempenho (sobre A) desempA : A D + A é o conjunto de algoritmos para um dado problema . A pode consistir de algoritmos de uma certa família ou ser o conjunto de todos os algoritmos possíveis (conhecidos ou não) para o problema . avaliação (sobre A) aval : A IN + Um algoritmo ótimo é um algoritmo o A, tal que aval(o) é melhor do que aval(a) para todo a A. No caso em que A consiste de todos os algoritmos para o problema , a complexidade aval(o) é a complexidade (intrínseca) do problema . Complexidade de Algoritmos
18
2.3 Ordens assintóticas A complexidade assintótica é definida pelo crescimento da complexidade para entradas suficientemente grandes. Algoritmo assintoticamente mais eficiente é melhor para todas as entradas, exceto para entradas relativamente pequenas. A complexidade exata costuma conter muita informação, resultando em uma função de difícil análise e manipulação, vamos simplificar. Exemplo: Considerando as funções f(n) = n + 4 e g(n) = n2; Para: n = 0, 1, 2, temos f(n) g(n); mas para n 4, temos f(n) = n + 4 n + n = 2 . n n2 = g(n). Complexidade de Algoritmos
19
2.3.1 Notação O A notação O define uma cota assintótica superior.
Define-se que f(n) é O(g(n)) se: para alguma constante c + : c . g(n) é f(n) c . g(n).), i. e. ( Ǝ c + ) ( Ǝ n0 ) ( n n0 ): f(n) c . g(n). Para n suficientemente grande, g(n) é cota superior para f(n) com um fator constante Complexidade de Algoritmos
20
f(n) = 5 . n + 7 e g(n) = n2; para n 7, temos
Exemplo: f(n) = 5 . n + 7 e g(n) = n2; para n 7, temos f(n) = 5 . n + 7 5 . n + n 6 . n 6 . n2 = 6 . g(n). Assim, tomando n0 := 7 e c := 6, vemos que para todo n n0, temos f(n) c . g(n); logo f(n) é ( g(n) ). Pode-se determinar a ordem de um polinômio a partir de seu grau. Por exemplo, considerando o polinômio cúbico k(n) = n3 + 3 . n2 + 7 . n + 5, para n 1, temos Logo, k(n) = n3 + 3 . n2 + 7 . n + 5 ≤ c n3 , para n 1 Complexidade de Algoritmos
21
2.3.2 Notação A notação define uma cota assintótica inferior a menos de constantes. De maneira geral, define-se f(n) é ( g(n) ) sse para alguma constante d + : d . f(n) g(n) d . f(n), i. e. ( Ǝ d + ) ( Ǝ n0 ) ( n n0 ): g(n) d . f(n). Para valores de n sufucientemente grande g(n) é sempre menor ou igual a d . f(n). Complexidade de Algoritmos
22
Exemplo: f(n) = n3 e quadrática g(n) = 6 . n2 + 10. para n 4, temos
g(n) = 6 . n2 + 10 6 . n2 + 16 6 . n2 + n2 7 . n2 7 . n3 = 7 . f(n). Assim, com n0 := 4 e d := 7, vemos que para todo n n0, temos g(n) d . f(n); logo f(n) é ( g(n) ). Os algoritmos de ordem ( 1 ), ( n ), ( n2 ), etc. são polinomiais, isto é, têm complexidade limitada por um polinômio (complexidade polinomial). Já 2n é uma função não limitada por polinômio, polinômio i. e. não existe m tal que 2n seja ( nm ), m uma constante. Um algoritmo de ordem ( 2n ), ( 3n ), etc., é dito exponencial. Quando o algoritmo é polinomial no valor da entrada (quando a entrada é um número) ao invés do tamanho da entrada o algoritmo é dito pseudopolinomial. Complexidade de Algoritmos
23
2.3.3 Notação A notação define um limite assintótico exato, a menos de constantes. Em geral, diz-se f(n) é ( g(n) ) sse ( Ǝ c, d + ) ( Ǝ n0 ) ( n n0 ): c . g(n) f(n) & f(n) d . g(n). Para n sufucientemente grande o valor de f (n) está entre os produtos c . g(n) e d . g(n). Complexidade de Algoritmos
24
Exemplo: f(n) = 7n + 3, g(n) = 2n + 5
Para n3, f(n) = 7n + 3 ≤ 7n + n = 8n ≤ 8(2n + 5) = 8 g(n) Para n5, g(n) = 2n + 5 ≤ 2n + n = 3n ≤ 3(7n +3) = 3 f(n) n0 = 5 = max{3,5}, c = 3, d = 8. temos c . g(n) f(n) e f(n) d . g(n); logo f(n) é ( g(n) ). Se f(n) é ( g(n) ), então f(n) também é ( g(n) ) e ( g(n) ). Utiliza-se notações assintótico: para simplificar a notação. Por exemplo usado simplesmente log n, independente da base, pois a troca de base é simplesmente a multiplicação por uma constante para expressar estimativas de erro em aproximações. Por exemplo, no truncamento aproximação de Stirling Se f(n) está à esquerda de g(n), então f(n) = ( g(n) ), e g(n) não é ( f(n) ). Complexidade de Algoritmos
25
2.4 Exemplos Exemplo 2.4.1: Máximo de tabela.
Algoritmo 2.1: Máximo de tabela. Procedimento Max(tab: tabela) {máximo de tabela} {Entrada: tabela tab: vetor [ 1..n ] de Elmord.Saída: Mx = valor máximo em tab.} 1. Mx tab[1]; {candidato a máximo} 2. para i de 2 até n faça {varre tabela: de 2 a 4} 3. se Mx ≤ tab[i] então Mx tab[i]; {atualiza Mx} 4. fim-para; {2: i de 2 até n} 5. retorne-saída (Mx); {fim do algoritmo: máximo de tabela} 6. fim-Procedimento. O desempenho do algoritmo Max em qualquer caso é n - 1 comparações. Tomando como tamanho da entrada o tamanho n da tabela e como operação fundamental a comparação <, a complexidade (média, no pior ou no melhor caso) de Max é n - 1, isto é de ordem linear ( n ). Complexidade de Algoritmos
26
Exemplo 2.4.2: Busca Sequencial
Algoritmo 2.2: Busca sequencial em tabela. Procedimento BuscaSeq(ch: Valor, tab: tabela) {busca sequencial em tabela} {Entrada: ch: Valor, tabela tab: vetor [ 1..n ] de Valor.Saída: achou, pos.} 1. i 0; achou F; {inicialização} 2. repita {varre tabela} 3. i i+1; {incrementa índice} 4. se tab[i] = ch então achou V; {compara com chave} 5. até achou v i = n; {fim do repita de 2} 6. se achou então pos i; {verifica se achou chave} 7. retorne-saída (achou, pos); {fim do algoritmo: busca seqüencial em tabela} 8. fim-Procedimento. Tomando como operação fundamental a comparação = e como tamanho da entrada o tamanho n de tab. O algoritmo tem complexidade no pior caso n: de ordem ( n ), complexidade média de ordem ( n ). Complexidade de Algoritmos
27
Exemplo 2.4.3: Particionamento
O algoritmo de particionamento é de a C. A. Hoare, utilizado no algoritmo Quicksort Dado um pivô, particionar os elementos de um vetor, de tal forma que no final: todos os elementos à direita do pivô serão maiores ou iguais a ele, os elementos à sua esquerda serão menores que ele. O pivô é o primeiro elemento do vetor. O algoritmo usa dois apontadores que caminham em direções opostas: Assim, aplicado à entrada O algoritmo deve fornecer como saída. Complexidade de Algoritmos
28
Algoritmo 2.3: Particionamento.
Procedimento Particionamento(A: vetor, m,k: Elmord) {particionar vetor} {Entrada: vetor A: vetor [ 1..n ] de Elmord, m, k. Saída: (j, A), o vetor A com os elementos rearranjados de tal forma que todos os elementos inferiores a A[m] estarão à esquerda da posição j.} 1. v A[m]; i m+1; j k; {v é pivô; i apontador da esq.; j apontador da dir.} 2. repita {2 a 6: percorre a nas duas direções} 3. enqto A[i] < v faça i i+1; {elem. da esq. é < pivô, move apontador} 4. enqto A[j] v faça j j -1; {elem. da dir. é pivô, move apontador} 5. se i < j então troca(A[i] e A[j]) {A[i] maior e A[j] menor que pivô} 6. i i + 1; 7. j j - 1; 8. fim-se; 9. até i > j; {2: todo a foi percorrido} 10. A[m] A[j]; A[j] v; {na posição j está o elem. < pivô mais à esquerda} 11. retorne-saída (j, A); {fim do algoritmo: particionar vetor} 12. fim-Procedimento. Complexidade de Algoritmos
29
Exemplo 2.4.4. Intercalação de listas
A intercalação de duas listas d1 e d2, com comprimentos m1 e m2, pode ser feita com m1 + m2 - 1 comparações: desemp[ Intercl ]( d1 , d2 ) = compr( d1 ) + compr( d2 ) - 1. a) Tomarndo como tamanho da entrada a soma dos dois comprimentos tam( d1 , d2 ) := compr( d1 ) + compr( d2 ) temos cP=[ Intercl ]( n ) = n - 1 e cP[ Intercl ]( n ) = n - 1. b) Tomando como tamanho da entrada o máximo entre os dois comprimentos tam( d1 , d2 ) := Máx [ compr( d1 ), compr( d2 ) ], temos cP=[ Intercl ]( n ) ≤ 2 . n - 1 e cP[ Intercl ]( n ) = 2 . n - 1. Alteração da noção de tamanho afeta a complexidade de intercalação, porém, as complexidades associadas a cada noção estão relacionadas. Complexidade de Algoritmos
30
Exemplo 2.4.5: Multiplicação de matrizes
O produto C de uma matriz A, p x q, por outra B, q x r é O algoritmo imediato, vindo diretamente dessa definição, obtém cada elemento Cij por uma soma de q parcelas, cada uma delas obtida por uma multiplicação de 2 elementos. Considerando matrizes quadradas n x n, tomando n como tamanho da entrada. Operação fundamental: a multiplicação de elementos, o algoritmo obtém cada um dos n2 elementos da matriz produto n multiplicações de elementos, o que leva a uma complexidade de n2 . n = n3. Operações fundamentais soma e multiplicação de elementos, o algoritmo obtém cada um dos n2 elementos do produto C por n multiplicações e n - 1 somas.o que leva a uma complexidade de n2 . ( 2 . n - 1 ) = 2 . n3 - n2 operações. Alteração da noção de custo das operações fundamentais afetou a complexidade. Complexidade de Algoritmos
31
2.5 Resumo do capítulo O objetivo deste capítulo foi introduzir e ilustrar os conceitos básicos de complexidade (medidas e critérios) e de análise assintótica. As principais medidas de complexidade são tempo e espaço, relacionadas à velocidade e quantidade de memória. O desempenho de um algoritmo sobre uma entrada é o esforço (quantidade de trabalho) para executar o algoritmo com essa entrada. A complexidade é determinada com base em operações fundamentais e no tamanho da entrada. A complexidade pessimista (ou no pior caso) dá o valor máximo. Complexidade de Algoritmos
32
A complexidade média (ou esperada) dá o valor esperado: a média dos esforços, levando em conta a probabilidade de ocorrência de cada entrada. Análise matemática fornece a complexidade intrínseca do algoritmo. A complexidade assintótica dá o desempenho para entradas de tamanho grande. As principais notações de comportamento assintótico dão limites superior (O), inferior () e exato (), a menos de constantes multiplicativas. Algoritmos polinomiais têm complexidade ( nk ); os algoritmos com complexidade ( 2n ), ( 3n ), etc.,algoritmos exponenciais Complexidade de Algoritmos
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.