Você está na página 1de 8

1

RESUMÃO – ANÁLISE DE ALGORITIMOS


MODELO DE ANÁLISE

Curso: Ciência da Computação / Engenharia da Computação


Disciplina: Análise de Algoritimos
Professor (a): Profª Larissa Bezerra
1º Bimestre (x) 2º Bimestre () 3º Bimestre () Rec. Paralela() Ano /Semestre: 2020/2

INTRODUÇÃO

No decorrer da aprendizagem de lógica e programação, vimos que os computadores operam seguindo uma lista de instruções estabelecida para
eles e, ainda, que os computadores gastam muito tempo ordenando e pesquisando as coisas, percebemos isso quando praticamos a organização
dos dados (estruturação). Portanto, devemos descobrir métodos rápidos e eficientes para fazer isto. Imagine você tendo que implementar uma
estrutura para manter o cadastro de mais de 5 mil funcionários? Onde manter significasse: assegurar em cada ficha a manutenção e atualização de
30 campos de cada ficha, além de garantir a listagem ordenada de cada ficha.

Ou seja, os algoritmos fazem parte do dia a dia das pessoas, pois, é uma sequência de ações executáveis para chegar à solução de um determina -
do tipo de problema. Segundo Edsger Dijkstra, um algoritmo corresponde a uma descrição de um padrão de comportamento, expresso em ter-
mos de um conjunto finito de ações.

Desta forma, a análise de algoritmos (descrita e difundida por D.E. Knuth) tem como função determinar os recursos necessários para executar um
dado algoritmo. Ela estuda a correção e o desempenho através da análise de correção e da análise de complexidade. Dados dois algoritmos
para um mesmo problema, a análise permite decidir qual dos dois é mais eficiente.

Antes de partir para conhecer as diferenças entre os tipos e análises de algoritimos, saibamos que para determinar se um algoritmo é o mais efici -
ente, podemos utilizar duas abordagens:

1. Análise Empírica: comparações entre programas.


2. Análise Matemática: estudo de propriedades do algoritmo.

Análise Empírica

Envolve avaliar o custo (ou a complexidade) de um algoritmo a partir da avaliação da execução do mesmo quando implementado. Ou seja, um
algoritmo é analisado pela execução de seu programa correspondente.
2

Algumas vantagens podemos adquirir quando realizamos a análise empírica, como por exemplo:

1. Avaliação do desempenho de uma determinada configuração de computador (processamento X hardware);


2. Avaliação do desempenho através do uso de uma linguagem;
3. Avaliação sobre o custo de alocação de memória;

Podemos nos deparar com algumas desvantagens ou dificuldades quando realizamos a análise empírica, como por exemplo:

1. Necessidade de implementar o algoritmo (relacionado ao próximo item);


2. Habilidade do programador;
3. Resultado pode ser mascarado pelo hardware (computador utilizado) ou software (eventos ocorridos no momento da utilização);
4. A natureza dos dados pode influenciar a análise (pode ocorrer o trabalho com dados reais, aleatórios (só envolve desempenho médio),
“perversos” (pior caso)).

Análise Matemática (pressuposição teórica)


Envolve realizar um estudo mais formal de um algoritmo ao nível de ideias e suposições por trás do algoritmo, fazendo uso de um computador
idealizado e simplificações que buscam considerar custos dominantes (que realmente “importam”) de um algoritmo. Neste caso, a medição do
tempo gasto é feita de maneira independente do hardware ou da linguagem usada na implementação.

Algumas vantagens quando realizamos a análise matemática:

1. Ignora-se o detalhamento sobre: linguagem de programação utilizada, o hardware no qual o algoritmo é executado, conjunto de instruções da
cpu.
2. Permite a compreensão de como o algoritmo se comporta à medida que o conjunto de dados de entrada cresce (podemos então expressar a
relação entre o conjunto de dados de entrada e a quantidade de tempo necessária para processar esses dados).

Podemos começar a Análise Matemática de um algoritmo apenas “contando” as suas instruções simples até se chegar um axioma (proposições
aceitas como verdadeiras sem demonstração e que servem de base para o desenvolvimento de uma teoria), para podermos então encontrar o
melhor, caso médio e pior caso de determinado algoritimo.

Vamos considerar que as instruções simples de um algoritmo serão as que provavelmente são as executadas pelo cpu ou algo muito perto disso.
Vejamos alguns exemplos:

Tipos de instruções:

 Atribuição de um valor à uma variável;


 Acesso ao valor de um determinado elemento de um vetor (array);
3

 Comparação de dois valores;


 Incremento de um valor – Movimento de Dados (nos Arrays ou listas por exemplo);
 Operações aritméticas básicas, como adição e multiplicação;

Iniciando os estudos construindo escritos por indução matemática :

EXEMPLO EXERCÍCIO

Enunciado: O seguinte trecho de código abaixo, demonstra partes de um algorítimo que foi construído pensando-se na realização de uma
pesquisa realizada em uma estrutura de dados composta homogênea.

int x=vet[0];
for (i=0;i<n;i++){
if (vet[i]>=x){
x=vet[i];
}
}

Utilizando o estudo da Complexidade Computacional (Análise por Indução Matemática), pede-se:

A. Identifique de forma coesa e sucinta o problema a qual muito provavelmente o trecho irá resolver (2 linhas).
B. Comente cada linha de instrução (relacione comandos de instrução, comparações, identifique operações aritméticas, trocas e ):

C. Identifique de forma coesa e sucinta as propriedades do problema a qual o trecho de código provavelmente irá resolver:

i. Parâmetros de Entrada:
ii. Parâmetros de Saída
iii. Propriedades:
iv. Instâncias (se houver):

D. Realize :
I. A contagem das instruções em cada linha:
II. Gere gráfico para demonstração referenciando função de tempo (considere Comparações x Instâncias)
III. Identifique : Pior, Melhor e Médio Caso do trecho de código.

Solução :
4

A. Identifique de forma coesa e sucinta o problema a qual muito provavelmente o trecho irá resolver: Irá resolver um problema de busca de uma
chave dentro de um Array cujo tamanho é definido pela constante n. (particularmente, algoritmo que busca o maior valor presente em um vetor “vet”, contendo “n”
elementos e o armazena na variável “x”)

B. Comente cada linha de instrução (relacione comandos de instrução, comparações, identifique operações aritméticas, trocas e ):

int x=vet[0]; // atribuição do valor do vetor à variável auxiliar


for (i=0;i<n;i++){ //estrutura de repetição, identificando variável auxiliar instanciada, para percorrer todo o vetor e realizar comparação e em seguida
realiza o incremento para troca de posição no vetor.
if (vet[i]>=x){ //procura menor elemento através de comparação entre o valor que consta no vetor em determinada posição com o valor assumido
pela variável auxiliar.
x=vet[i]; // utiliza uma variável para receber menor elemento
}}

C. Identifique de forma coesa e sucinta as propriedades do problema a qual o trecho de código provavelmente irá resolver:

i. Parâmetros de Entrada: Variáveis : x e vet[0], vet[1], vet[2]……..vet[n]


ii. Parâmetros de Saída: Variável x após comparação realizada em estrutura de decisão, quando assumirá novo valor.
iii. Propriedades: Somente pelo trecho é apenas um Array com elementos agrupados (não se tratando no código de qualquer ordenação)
iv. Instâncias (se houver): Não há prescrição no código – não se aplica

D. Faça :
I. A contagem das instruções em cada linha:
II. Gere a função / axioma matemático que você pode encontrar da contagem das funções
III. Teste com instâncias inseridas (à seu critério)
IV. Gere gráfico para demonstração referenciando função de tempo (considere Comparações x Instâncias)
V. Identifique : Pior, Melhor e Médio Caso do trecho de código.

Assumindo que as instruções possuem um mesmo “custo” e os “comandos de seleção” possuem um custo zero (ou seja, a linha contendo o
comando que vai inicializar a estrutura da repetição não custa nada, o que custa é a comparação dentro da estrutura de decisão), vamos contar as
instruções no seguinte trecho de código (algoritmo que busca o maior valor presente em um vetor “vet”, contendo “n” elementos e o armazena na variável “x” ):

Você pode considerar os seguintes Tipos de instruções:

 Atribuição de um valor à uma variável;


 Acesso ao valor de um determinado elemento de um vetor (array);
 Comparação de dois valores;
 Incremento de um valor – Movimento de Dados (nos Arrays ou listas por exemplo);
5

 Operações aritméticas básicas, como adição e multiplicação;

Resposta :

int x=vet[0]; → 1
for (i=0;i<n;i++){ → 1+1n e de novo → 1+1n
if (vet[i]>=x){
x=vet[i];
}
}

Considerando que:

1. Linha 1:
O Custo da linha 1 é de 1 (uma) instrução referente à ocorrência de uma atribuição (o que ocorre é que o valor da primeira posição do
vetor está sendo copiado para a variável “x”) referente à: acessar o valor de vet[0] e atribuí-lo à x;
2. Linha 2:
Para calcular o custo da linha 2, devemos considerar as regras para prova de corretude do algorítimo (ANTES, DURANTE e APÓS
EXECUÇÃO), desmembremos o laço/estrutura de repetição em:

a. Antes da execução do laço (teremos a contagem do custo de inicialização do laço):

 Atribuição feita (i=0);


 Em seguida (durante a execução do laço) é feita uma comparação em relação à n (i<n), independente se o valor de n for igual à o (zero);

Logo, teremos até aqui: 2 (duas) instruções (1+1n), sendo que uma delas é em relação à n.

b. Após a execução do laço (teremos a contagem em relação à execução do laço):

 Incremento após a comparação;


 E novamente a comparação;

Logo, até aqui, teremos: 2 (duas) instruções (1+1n), sendo que uma delas é em relação à n.

No total, já temos que:

5175
6

ou

5133

1+1+1n+1+1n

Supondo até aqui, sem levar em conta a estrutura de repetição dentro do laço, se considerarmos a execução do laço vazio, já conseguimos chegar
a definir uma função matemática para expressar o custo do algoritmo em relação ao tamanho de entrada no vetor:

F(n)= 2n+3 – Axioma Matemático gerado até a linha de instrução que trata a estrutura de repetição

Prova de Corretude até aqui:

Logo, exemplificando, para um vetor de entrada 10, temos: F(10)=2x10+3=23 instruções. Para um vetor de entrada 20, F(20)=2x20+3=43
instruções.

Percebemos até aqui que de acordo com o axioma gerado, em relação ao custo do tempo de execução do algorítimo, ainda que ocorram instâncias
diferenciadas, não ocorrendo o aumento de tamanho da estrutura, o nº de comparações será sempre o mesmo, pois não há aumento da tamanho
da estrutura criada, porém, quando aumento do tamanho da estrutura, e consequentemente aumento do nº de entradas, percebemos que ocorrerá
aumento em relação ao consumo de tempo.

Continuando agora, contando as demais instruções que faltam:

a. Antes da execução (na linha de comando do if):


 Comparação (vet[i]>=x)
b. Para execução (dentro do if):
 Atribuição (x=vet[i])

Até agora, sem e tratando da estrutura de decisão, teríamos então : 2 (duas) instruções.

Apenas, observemos o seguinte:

- Antes de analisarmos a decisão, havíamos visto que as instruções eram sempre executadas na análise do laço/estrutura de repetição;
7

- Agora, percebemos que dentro do for, as instruções poderão ou não serem executadas, devido à decisão (vai depender dos valores que temos
dentro do vetor).

Ou seja, antes, bastava saber o tamanho do vetor, n, para definirmos a função de custo do algoritmo (Fn)).

Mas agora, precisaremos considerar também o conteúdo do vetor. Vejamos melhor no exemplo abaixo:

VetA={1,2,3,4}
VetB={4,3,2,1}

 No caso de VetA, nos deparamos com a decisão (o if) sendo sempre verdadeira, nesse caso teremos supostamente mais instruções, sempre
terá a atribuição.
 No caso de VetB, nos deparamos com a decisão (o if) sendo sempre falsa (a linha de atribuição nunca será executada, nunca será feito a
atribuição).

Em análise de algoritmos é comum procurarmos considerar qual seria o pior caso (em relação aos custos) de um algoritmo. No caso, o “pior
caso” seria o maior número de instruções executadas.

Neste caso do algoritmo que busca o maior valor de um vetor, o pior caso acontece quando o vetor possui valores em ordem crescente. Por quê?

- Porque o valor de x será sempre substituído (maior número de instruções);


-O laço/for sempre executaria as 2 (duas) instruções de comando dentro dele (advindas da decisão (if)).

Enfim, após observações, neste caso, do “pior caso”, a função de complexidade de custo em relação ao tamanho de entradas no vetor vet
sofreria alteração, passando para:

F(n)= 3+2n+2n , ou seja, F(n)=4n+3

Esta também pode ser a função de complexidade de custo de tempo pois, nos dá também uma ideia de custo de execução do algoritmo para um
problema de tamanho “n”.

Encaixando-se na terminologia BIG – O, as constantes podem ser excluídas, e teremos então que:

F(n) = n

Logo, a terminologia encaixa-se na de Ordem Linear.


8

Você também pode gostar