Vous êtes sur la page 1sur 10

Complexidade de Algoritmos

Complexidade de tempo Interpretao da complexidade de tempo Clculo da complexidade de tempo

Introduo

O estudo de Estruturas de Dados basicamente o estudo de mtodos de organizao de grandes quantidades de dados. dados. Estes mtodos incluem: formas de organiz-los (estruturas); tcnicas para manipul-los (algoritmos bsicos). Pilhas, Listas e Filas so estruturas de dados tpicas; Para manipular estas estruturas - inserir elementos, retirar elementos e ordenar elementos - necessitamos de algoritmos; Estes algoritmos podem ser implementados de muitas maneiras. Algumas simples e diretas, outras no to simples - porm engenhosas - e outras ainda complicadas e envolvendo muitas operaes; Quando trabalhamos com quantidades muito grandes de dados, um projeto ruim de algoritmo para manipular uma estrutura de dados pode resultar em um programa que apresenta um tempo de execuo invivel. Quando estudamos algoritmos, um aspecto a ser considerado, alm de sua correo, a anlise da sua eficincia. eficincia. A anlise de algoritmos pode ser definida como o estudo da estimativa do tempo de execuo dos algoritmos (M. A. Weiss).

Idias bsicas

Um algoritmo um conjunto finito de passos que devem ser seguidos com um conjunto de dados de entrada para se chegar soluo de um problema; Um problema, geralmente, pode ser resolvido por muitos algoritmos diferentes.

Exemplo: clculo da potncia xn de um nmero inteiro x. //Verso iterativa. inteiro potncia(x, n) inteiro y, i; incio i <- n; y <- 1; enquanto (i > 0) faa y <- y * x; i <- i - 1; fim enquanto retorne y; fim //Verso recursiva. inteiro potncia_recursiva(x, n) inteiro y; incio se (n = 1) ento retorne x; y <- potncia_recursiva (x, (n / 2)); se (mpar(n)) ento retorne x*y*y; seno retorne y*y; fim se fim O fato de existir um algoritmo para resolver um problema no implica necessariamente que este problema possa realmente ser resolvido na prtica. H restries de tempo e de espao de memria. Exemplo: calcular todas as possveis partidas de xadrez. Um algoritmo uma idia abstrata de como resolver um determinado problema. Ele , a princpio, independente da mquina que o executar e de suas caractersticas. Um programa uma implementao de um algoritmo em uma linguagem particular que ser executado em um computador particular. Um programa est sujeito s limitaes fsicas da mquina na qual ser executado, como capacidade de memria, velocidade do processador e dos perifricos, entre outras.

O tempo que a execuo de um programa toma uma grandeza fsica que depende: do tempo que a mquina leva para executar uma instruo ou um passo de programa; da natureza do algoritmo, isto , de quantos passos so necessrios para se resolver o problema para um dado; do tamanho do conjunto de dados que constitui o problema.

Problema bsico na Anlise de Algoritmos

Necessitamos definir uma forma de criar uma medida de comparao entre diferentes algoritmos que resolvem um mesmo problema, para: Determinar se so viveis; Determinar qual o melhor algoritmo para a soluo do problema. Para isso, necessria a abstrao de um computador em particular e assumir que a execuo de todo e qualquer passo de um algoritmo leva um tempo fixo e igual a uma unidade de tempo: o tempo de execuo em um computador particular no interessante; muito mais interessante uma comparao relativa entre algoritmos.

Modelo de computao

as operaes so todas executadas sequencialmente; a execuo de toda e qualquer operao consome uma unidade de tempo; a memria do computador infinita. Assim , restam duas grandezas: tempo = nmero de operaes executadas; quantidade de dados de entrada.

Complexidade de Tempo

Podemos expressar de forma abstrata a eficincia de um algoritmo descrevendo o seu tempo de execuo como uma funo do tamanho do problema (quantidade de dados). Isto chamado de complexidade de tempo. Exemplo: ordenao de um Vetor. Exemplo: Primeiro caso: Bubblesort caso: Bubblesort o mais primitivo dos mtodos de ordenao de um vetor. A idia percorrer um vetor de n posies n vezes, a cada vez comparando dois elementos e trocando-os caso o primeiro seja maior que o segundo.

//Mtodo da bolha.

Bubblesort(a[], n) inteiro i, j, x; incio para i de 1 at n faa para j de 2 at n faa se (a[j-1] > a[j]) ento x <- a[j-1]; a[j-1] <- a[j]; a[j] <- x; fim se fim para fim para fim A comparao (a[j-1] > a[j]) vai ser executada n*(n-1) vezes. No caso de um vetor na ordem inversa, as operaes da atribuio triangular podero ser executadas at 3*n*(n-1) vezes, j que uma troca de elementos no significa que um dos elementos trocados tenha encontrado o seu lugar definitivo. Segundo caso: StraightSelection caso: O mtodo da seleo direta uma forma intuitiva de ordenarmos um vetor: escolhemos o menor elemento do vetor e o trocamos de posio com o primeiro elemento. Depois comeamos do segundo e escolhemos novamente o menor dentre os restantes e o trocamos de posio com o segundo e assim por diante. StraightSelection(a[], n) inteiro i, j, k, x; incio para i de 1 at n-1 faa k <- i; x <- a[i]; para j de i+1 at n faa se (a[j] < x) ento k <- j; x <- a[k]; fim se fim para a[k] <- a[i]; a[i] <- x; fim para fim Neste algoritmo o nmero de vezes que a comparao (a[j] < x) executada expresso por (n-1)+(n-2)+...+2+1 = (n/2)*(n-1). O nmero de trocas a[k] <- a[i]; a[i] <- x realizado no pior caso, onde o vetor est ordenado em ordem inversa, somente n-1 vezes, num total de 2*(n-1).

Interpretao

Como j foi visto, a nica forma de se comparar dois algoritmos descrevendo o seu comportamento temporal em funo do tamanho do conjunto de dados de entrada. Assim: Talgoritmo = f(n), f(n), onde n o tamanho do conjunto de dados. Se tomarmos as operaes de troca de valores como critrio-base, podemos dizer que: TBubblesort = 3*n*(n-1) sempre TStraightSelection = 2*(n-1) para o pior caso O que nos interessa o comportamento assinttico de f(n), ou seja, como f(n) se comporta com a variao de n. Razo: interessante saber como o algoritmo se comporta com uma quantidade de dados realstica para o problema e o que acontece quando ocorre variao da quantidade desses dados. Exemplo Existem dois algoritmos (a e b) para a soluo de um problema. Se a complexidade de um (a 2 expressa por fa(n) = n e a do outro por fb(n) = 100*n, significa que o algoritmo a cresce quadraticamente (uma parbola) e que o algoritmo b cresce linearmente (embora seja uma reta bem inclinada). Se esses algoritmos forem aplicados para um conjunto de 30 dados, o segundo com Tb=3.000, pior do que o primeiro, com Ta=900. Se usados para um conjunto de 30.000 dados, porm, tem-se Ta=900.000.000 e Tb=3.000.000. Isto ocorre porque o comportamento assinttico dos dois bem diferente, como pode ser visto no grfico abaixo.

Interpretao da Complexidade de Tempo

Aspecto essencial que deve ser expresso pelo clculo de complexidade:

Qual o comportamento assinttico predominante de um algoritmo em funo do tamanho do conjunto de dados a ser processado. Exemplo: se linear, polinomial (quadrtico, cbico, etc.), logartmico ou exponencial.

Anlise Assinttica

Para a anlise do comportamento de algoritmos existe toda uma terminologia prpria. Para o clculo do comportamento de algoritmos foram desenvolvidas diferentes medidas de complexidade. A mais importante delas e que usada na prtica chamada de Ordem de Complexidade ou Notao-O ou Big-Oh. Big-Oh. Definio (Big-Oh): T(n) = O(f(n)) se existem constantes c e n0 tais que T(n)c.f(n) quando (Big-Oh): T(n)c n=n0. n=n A definio indica que existe uma constante c que faz com que c.f(n) seja sempre pelo menos to grande quanto T(n), desde que n seja maior que um n0. Em outras palavras: a Notao-O fornece a Ordem de Complexidade ou a Taxa de Crescimento de uma funo. Para isso, no consideramos os termos de ordem inferior da complexidade de um algoritmo, apenas o termo predominante. Exemplo: algoritmo com complexidade T(n) = 3n2 + 100n. 100n. Nesta funo, o segundo termo tem um peso relativamente grande, mas a partir de n0 = 11, o termo n2 que "d o tom" do crescimento da funo: uma parbola. A constante parbola. 3 tambm tem uma influncia irrelevante sobre a taxa de crescimento da funo aps um certo tempo. Por isso dizemos que este algoritmo da ordem de n2 ou que tem complexidade O(n2). Problema da Subseqncia de Soma Mxima: Mxima: dada uma seqncia de nmeros a1, a2, ... , an, positivos ou negativos, encontre uma subseqncia aj, ..., ak dentro desta seqncia cuja soma seja mxima. A soma de uma seqncia contendo s nmeros negativos por definio 0. Exemplo: Exemplo: para a seqncia -2, 11, -4, 13, -5, -2, a resposta 20 (a2,a3,a4). Este problema oferece um bom exemplo para o estudo de como diferentes algoritmos que resolvem o mesmo problema possuem diferentes comportamentos, pois para ele existem muitas solues diferentes.

Clculo da Complexidade de Tempo


Um exemplo intuitivo inteiro somaCubos(inteiro n)

1 2 3 4 5

inteiro i, somaParcial; incio somaParcial <- 0; para i de 1 at n faa somaParcial <- somaParcial + i * i * i; fim para retorne somaParcial; fim

Anlise: Anlise: as declaraes no tomam tempo nenhum; a linha 4 tambm no toma tempo nenhum; as linhas 1 e 5 contam uma unidade de tempo cada; a linha 3 conta 4 unidades de tempo (2 multiplicaes, uma adio e uma atribuio) e executada n vezes, contando com um total de 4n unidades de tempo; 4n a linha 2 possui custos implcitos de inicializar i, testar se menor que n e increment-lo. Contamos 1 unidade para sua inicializao, n + 1 para todos os testes e n para todos os incrementos, o que perfaz 2n + 2 unidades de tempo; 2n o total perfaz 6n + 4 unidades de tempo, o que indica que o algoritmo O(n), da 6n O(n Ordem de Complexidade n, ou seja, linear.

Regras para o clculo

Laos: Laos: o tempo de execuo de um lao , no mximo, a soma dos tempos de execuo de todas as instrues dentro do lao (incluindo todos os testes) multiplicado pelo nmero de iteraes. Laos aninhados: aninhados: analise-os de dentro para fora. O tempo total de execuo de uma instruo dentro de um grupo de laos aninhados o tempo de execuo da instruo multiplicado pelo produto dos tamanhos de todos os laos. Exemplo: O(n2) O(n para i de 1 at n faa para j de 1 at n faa k <- k + 1; fim para fim para Instrues Consecutivas: estes simplesmente somam, sendo os termos de ordem menor da soma ignorados. Exemplo: O(n) + O(n2) = O(n2) O(n O(n O(n para i de 1 at n faa a[i] <- 0; fim para

para i de 1 at n faa para j de 1 at n faa a[i] <- a[j] + k + 1; fim para fim para Se / Ento / Seno: considere o fragmento de cdigo abaixo. se cond ento expressso1 seno expresso2 fim se O tempo de execuo de um comando Se / Ento / Seno nunca maior do que o tempo de execuo do teste cond em si mais o tempo de execuo da maior dentre as expresses expresso1 e expresso2. Ou seja: se expresso1 O(n3) e expresso2 O(n), ento o teste expresso1 expresso2. expresso1 O(n expresso2 O(n 3 3 O(n ) + 1 = O(n ). O(n O(n Chamada a Funes: segue a mesma regra dos laos aninhados - analise tudo de dentro para fora. Ou seja: para calcular a complexidade de um programa com vrias funes, calcula-se primeiro a complexidade de cada uma das funes e depois considera-se cada uma das funes como uma instruo com a complexidade de funo. Recurso: a parte mais difcil da anlise de complexidade. Na verdade existem dois casos: muitos algoritmos recursivos mais simples podem ser "linearizados", substituindo-se a chamada recursiva por alguns laos aninhados ou por uma outra subrotina extra e eventualmente uma pilha para control-la. Nestes casos, o clculo simples e pode ser feito depois da "linearizao". Em muitos algoritmos recursivos, porm, isto no possvel. Nestes casos obtemos uma relao de recorrncia que tem de ser resolvida e uma tarefa matemtica menos trivial.

Exemplo de clculo de complexidade em recurso: Fatorial inteiro Fatorial(inteiro n)

incio se n <= 1 ento retorne 1 seno retorne (n * Fatorial (n - 1)); fim se fim Este exemplo realmente um exemplo pobre de recurso e pode ser "iterativisado" de forma extremamente simples com apenas um lao para-faa: para-faa: inteiro FatorialIterativo(inteiro n) inteiro i, fatorial; incio fatorial <- 1; para i de 2 at n faa fatorial <- fatorial * i; fim para retorne fatorial; fim A complexidade de FatorialIterativo pode ento ser facilmente calculada e evidente que O(n). O(n O caso dos nmeros de Fibonacci abaixo no to simples e requer a resoluo de uma relao de recorrncia: inteiro Fibonacci(inteiro n) incio se n <= 1 ento retorne 1 seno retorne (Fibonacci(n-1) + Fibonacci(n-2)); fim se fim Observando o algoritmo, vemos que para n >= 2 temos um tempo de execuo T(n) = T(n1)+T(n-2)+2. A resoluo desta relao nos mostra que Fibonacci O(()n).

Logaritmos e outros Tempos de Execuo

O aspecto mais complexo na anlise de complexidade centra-se em torno do logaritmo. Para analisar-se um algoritmo de complexidade logartmica e chegar-se a um resultado correto sobre a sua ordem exata de complexidade necessria uma certa experincia e algum "jeito" matemtico. Algumas regras de aproximao podem ser dadas: algoritmos seguindo a tcnica Dividir-Para-Conquistar so muitas vezes n log n. n. Quando um algoritmo, em uma passada de uma iterao toma o conjunto de dados e o divide em duas ou mais partes, sendo cada uma dessas partes processada separada e recursivamente, este algoritmo utiliza a tcnica dividir-para-conquistar e ser possivelmente n log n. Um n.

algoritmo log n se ele toma um tempo constante O(1) para dividir o tamanho do problema, O(1 usualmente pela metade. A pesquisa binria um exemplo de log n. n. Se o algoritmo toma tempo constante para reduzir o tamanho do problema em um tamanho constante, ele ser O(n). O(n Algoritmos combinatrios so exponenciais. Qualquer algoritmo que teste todas as combinaes de alguma coisa, ele ser exponencial. Exemplo: Problema do Caixeiro Viajante

Checando a sua anlise

Uma vez que a anlise de complexidade tenha sido executada, interessante verificar-se se a resposta est correta e to boa quanto possvel. Uma forma de se fazer isto o procedimento pouco matemtico de se codificar o trecho de algoritmo cuja complexidade se tentou descrever e verificar se o tempo de execuo coincide com o tempo previsto pela anlise. Quando n dobra, o tempo de execuo se eleva de um fator 2 para algoritmos lineares, fator 4 para quadrticos e fator 8 para cbicos. Programas logartmicos s aumentam o seu tempo de execuo de uma constante a cada vez que n dobra. Algoritmos de O(n log n) tomam um pouco mais do que o dobro do tempo sob O(n n) as mesmas circunstncias. Estes aumentos podem ser difceis de se detectar se os termos de ordem inferior tm coeficientes relativamente grandes e n no grande o suficiente. Um exemplo o pulo no tempo de execuo de n=10 para n=100 em algumas implementaes do problema da subseqncia de soma mxima. Distinguir programas n log n de programas lineares s em evidncia de tempo de execuo pode tambm ser muito difcil. Uma boa prtica , caso o programa no seja exponencial (o que voc vai descobrir muito rpido), fazer alguns experimentos com conjuntos maiores de dados de entrada.

Vous aimerez peut-être aussi