Você está na página 1de 7

Análise de Algoritmos

com Listas

Isabel Harb Manssour

Porto Alegre, abril de 2019

Análise de Algoritmos (revisão)

◼ No desenvolvimento de uma aplicação tem-se


como objetivo projetar “boas” estruturas de dados
e algoritmos
◼ Otimizados
◼ Simples

1
Análise de Algoritmos (revisão)

◼ Análise de Algoritmos: estudo das características


de desempenho de um determinado algoritmo.
◼ Exemplo: espaço ocupado e tempo gasto na execução.

◼ Complexidade de um algoritmo: medida do


consumo de recursos durante a sua execução.
◼ Recursos: tempo de execução, memória ocupada,
quantidade de atribuições, quantidade de comparações,
etc.

Análise de Algoritmos (revisão)

◼ Contar o tempo não oferece precisão!


◼ Depende de Hardware (CPU, memória, ...) e Software
(Sistema operacional, programas em execução, ...

◼ Solução: contar operações


◼ Atribuição
◼ Comparações
◼ Cálculos
◼ ...

2
Análise de Algoritmos com Listas

◼ Objetivo:
◼ Comparar a performance das duas listas: baseada em
arranjo e encadeada)
◼ Para isto, será usado o algoritmo de simplificação de
polígonos (http://www.inf.pucrs.br/~flash/alpro2/aulas/07-
listaenc/)
◼ Características do algoritmo: muitas operações de
remoção
◼ Qual é a implementação aparentemente mais indicada?

Análise de Algoritmos com Listas


private ListTAD<Ponto> simplifyGet(ListTAD<Ponto> nova, int totalPontos) {
while (nova.size() > totalPontos) {
double menorD = 10000;
int menorPos = 0, pos = 1;
Ponto prev = nova.get(pos-1);
Ponto atual = nova.get(pos);
Ponto next = nova.get(pos+1);
while (pos < nova.size() - 2) {
double l1 = atual.distancia(prev);
double l2 = atual.distancia(next);
double l3 = prev.distancia(next);
double d = l1 + l2 - l3;
if (d < menorD) { menorD = d;
menorPos = pos; }
pos++; prev = atual; atual = next;
next = nova.get(pos + 1);
}
nova.remove(menorPos);
}
return nova;
}
6

3
Análise de Algoritmos com Listas
◼ Tabela da contagem dos tempos
Análise do algoritmo de simplificação de polígonos
Lista encadeada/Get Arranjo/Get
Todos $ 2.183,00 $ 4.733,00
"1/2" $ 1.518.137.548,00 $ 2.857.564,00
"1/4" $ 1.707.838.967,00 $ 3.503.393,00
"1/8" $ 1.731.525.973,00 $ 3.665.758,00
◼ Tempo para “Todos” é menor na lista encadeada.
◼ Não há remoção de pontos, e o método add da
implementação baseada em arranjo precisa
redimensionar o arranjo de tempos em tempos
◼ Tempo para (1/2, 1/4 e 1/8) é menor na lista
baseada em arranjo
◼ Método get x Método remove

Análise de Algoritmos com Listas

◼ Solução para melhorar a eficiência:


◼ Ter uma referência para a “posição corrente” da lista
(atributo current)
◼ Ter um método para posicionar a referência para a
posição corrente no início da lista (método reset)
◼ Ter um método para retornar o elemento da posição
corrente da lista e passar para a próxima posição
(método next)

4
Análise de Algoritmos com Listas
public class ListSimpleLinked<E> implements ListTAD<E> {
private class Node<T> {...}
private Node<E> head;
private Node<E> tail;
private Node<E> current;
private int count;
public ListSimpleLinked() {
head = null; tail = null;
current = null; count = 0;
}
public void reset() {
current = head;
}
public E next() {
E obj = null;
if (current != null) { obj = current.element;
current = current.next;
return obj; }
return null;
} ...

Análise de Algoritmos com Listas


public class ListArray<E> implements ListTAD<E> {
private E[] data;
private int count, capacity;
private int current;
public ListArray() {
data = (E[]) new Object[10];
count = 0; capacity = 10;
current = -1;
}
public void reset() {
current = 0;
}
public E next() {
if(current==-1 || current == count)
return null;
E item = data[current];
current++;
return item;
}
...

10

5
Análise de Algoritmos com Listas
private ListTAD<Ponto> simplifyResetNext(ListTAD<Ponto> nova, int totalPontos){
while (nova.size() > totalPontos) {
double menorD = 10000; int pos = 1;
Ponto menorImp = null;
nova.reset();
Ponto prev = nova.next();
Ponto atual = nova.next();
Ponto next = nova.next();
while (next != null) {
double l1 = atual.distancia(prev);
double l2 = atual.distancia(next);
double l3 = prev.distancia(next);
double d = l1 + l2 - l3;
if (d < menorD) { menorD = d;
menorImp = atual; }
prev = atual; atual = next; next = nova.next();
}
nova.remove(menorImp);
}
return nova; ◼ Solução com reset e next
}
11

Análise de Algoritmos com Listas


◼ Tabela da contagem dos tempos
Lista encadeada/Get Arranjo/Get Lista encadeada/Reset-Next Arranjo/Reset-Next
Todos $ 2,183.00 $ 4,733.00 $ 2,183.00 $ 4,733.00
"1/2" $ 1,518,137,548.00 $ 2,857,564.00 $ 2,516,156.00 $ 3,583,217.00
"1/4" $ 1,707,838,967.00 $ 3,503,393.00 $ 3,211,101.00 $ 4,478,111.00
"1/8" $ 1,731,525,973.00 $ 3,665,758.00 $ 3,384,039.00 $ 4,701,971.00

◼ A lista encadeada tem o melhor desempenho.


◼ A implementação com arranjo perde no remove e
no add
◼ Se fosse usado o construtor que recebe a capacidade
inicial, o add não teria custo
◼ Mesmo sem isso, o custo não é significativo

12

6
Análise de Algoritmos com Listas

◼ Conclusões
◼ Importante:
◼ Considerar todas as operações que serão feitas com a lista na
solução do problema
◼ De acordo com as operações, definir a estrutura de dados e o
algoritmo mais adequado
◼ Para pensar:
◼ Existe alguma forma de melhorar mais a performance do
algoritmo?
◼ Se a aplicação exigir alto desempenho, pode-se considerar a
opção de trabalhar diretamente com a implementação da lista
encadeada

13

Você também pode gostar