MAC 323 Estruturas de Dados - 2004
Referˆencia Principal: Este livro est´a dispon´ıvel na FNAC (por R$ 48,70).
J. L. Szwarcfiter e L. Markenzon. Estruturas de Dados e seus Algoritmos. 2.a Edi¸c˜ao, LTC Editora, 1997.
Preliminares
Objetivo de estudar estruturas de dados
Estudo de estruturas de dados visa principalmente o problema de armazenamento e recu- pera¸c˜ao (busca) r´apida de dados.
Nota¸c˜ao para algoritmos
Procuramos apresentar algoritmos numa nota¸c˜ao sucinta, desprovida de pesada sintaxe t´ıpica de linguagens de programa¸c˜ao, para real¸car o que realmente ´e o essencial.
Usaremos uma nota¸c˜ao parecida com Pascal.
• Estrutura de bloco, indicada por indenta¸c˜ao.
• Atribui¸c˜ao indicada por :=
• Comandos usados:
if ... then ...
endif
if ... then ...
else ...
endif
while ... do ...
endwhile
for ... do ...
endfor
• Vari´aveis simples e elementos de arrays como A[i,3].
• Registros com v´arios campos: T.chave indica o campo chave do registro T.
• Vari´aveis apontadoras (pointers): vari´avel apontadorapt, pt↑.inf oindica o campo info de um registro apontado por pt.
• Procedimentos e fun¸c˜oes.
• % indica in´ıcio de um coment´ario.
1
Recursividade
Procedimento que possui dentro da sua descri¸c˜ao uma ou mais chamadas a si pr´oprio.
Exemplo cl´assico:
Algorithm 1 Fatorial recursivo
1: fun¸c˜aof at(i)
2: f at := se i≤1 ent˜ao 1 sen˜ao i×f at(i−1) Exemplo Torre de Hanoi:
• Pinos A, B e C (origem, destino, trabalho)
• ndiscos no pino A, em ordem decrescente de tamanho, de baixo para cima.
• Mover todos os discos para o pino destino sujeito a:
– mover um disco de cada vez.
– um disco nunca pode ser colocado sobre outro de tamanho menor.
Algorithm 2 Torre de Hanoi
1: procedimento hanoi(n, A, B, C)
2: if (n >0) then
3: hanoi(n−1, A, C, B)
4: mover o disco do topo deC paraB
5: hanoi(n−1, C, B, A)
6: end if
Eficiˆencia ou complexidade de algoritmos
(Daremos aqui um tratamento informal sobre o assunto. Maiores detalhes devem ser obtidos em cursos de An´alise de Algoritmos.)
Costuma-se analisar um algoritmo em termos de tempo e espa¸co (ou mem´oria). Para o tempo, diversas medidas s˜ao em princ´ıpio poss´ıveis:
1. Tempo absoluto (em minutos, segundos, etc.) – n˜ao ´e interessante por depender da m´aquina.
2. N´umero de opera¸c˜oes consideradas relevantes (por exemplo compara¸c˜oes, opera¸c˜oes aritm´eticas, movimento de dados, etc.)
Trˆes casos podem ser considerados: o melhor caso, o caso m´edio e o pior caso. O estudo do caso m´edio depende do conhecimento ou suposi¸c˜ao da distribui¸c˜ao das entradas ao problema. Em geral o pior caso ´e o mais f´acil de se analisar.
Por exemplo, se temos 2 m´etodos para resolver um mesmo problema, cuja entrada tem tamanhon, podemos ter:
2
M´etodo 1: T1(n) = 2n2+ 5nopera¸c˜oes M´etodo 2: T2(n) = 500n+ 4000 opera¸c˜oes
Dependendo do valor de n, m´etodo 1 pode requerer mais ou menos opera¸c˜oes que m´etodo 2.
Nota¸c˜ao O
Para estudarmos o comportamento assint´otico – parangrande – interessa-nos o termo de ordem superior:
M´etodo 1: T1(n) =O(n2) M´etodo 1: T2(n) =O(n)
A nota¸c˜ao O pode ser formalizada como se segue:
Dizemos queT(n) =O(f(n)) se existirem inteiro m e constantec tais que T(n)≤cf(n) para n > m.
Isto ´e, para valores den suficientemente grandes,T(n) n˜ao cresece mais rapidamente que f(n).
A importˆancia da complexidade pode ser observada pelo seguinte exemplo, que mostra 5 algoritmos A1 a A5 para resolver um mesmo problema, de complexidades diferentes.
Supomos que uma opera¸c˜ao leva 1 ms para ser efetuada. A tabela seguinte d´a o tempo necess´ario por cada um dos algoritmos. (Sempre suporemos logaritmos na base 2.)
A1 A2 A3 A4 A5
n T1(n) =n T2(n) =nlogn T3(n) =n2 T4(n) =n3 T5(n) = 2n
16 0.016s 0.064s 0.256s 4s 1m 4s
32 0.032s 0.16s 1s 33s 46 dias
512 0.512s 9s 4m 22s 1 dia 13h 10137 s´eculos
Podemos muitas vezes melhorar o tempo de execu¸c˜ao de um programa (que implementa um algoritmo dado) fazendo otimiza¸c˜oes locais (e.g. usarx+xao inv´es de 2x, em m´aquinas em que a multiplica¸c˜ao ´e mais demorada que a adi¸c˜ao).
Entretanto, melhorias substanciais s˜ao muitas vezes obtidas se usarmos um algoritmo diferente, com outra complexidade de tempo, e.g. obter um algoritmo de O(nlogn) ao inv´es de O(n2).
Cota superior ou limite superior (“upper bound”)
Seja dado um problema, por exemplo, multiplica¸c˜ao de duas matrizes quadradas de ordem n. Conhecemos um algoritmo para resolver este problema (pelo m´etodo trivial) de com- plexidade O(n3). Sabemos assim que a complexidade deste problema n˜ao deve superar O(n3), uma vez que existe um algoritmo desta complexidade que o resolve. Uma cota superior (ou “upper bound”) deste problema ´e O(n3). A cota superior de um problema pode mudar se algu´em descobrir um outro algoritmo melhor. Isso de fato aconteceu com o algoritmo de Strassen que ´e de O(nlog 7). Assim a cota superior do problema de multi- plica¸c˜ao de matrizes passou a ser O(nlog 7). Outros pesquisadores melhoraram ainda este
3
resultado. Atualmente o melhor resultado ´e o de Coppersmith e Winograd – deO(n2.376).
Notem que a cota superior de um problema depende do algoritmo.
A cota superior de um problema ´e parecida com orecord mundialde uma modalidade de atletismo. Ela ´e estabelecida pelo melhor atleta (algoritmo) do momento. Assim como orecord mundial, a cota superior pode ser melhorada por um algoritmo (atleta) mais veloz.
Cota inferior ou limite inferior (“lower bound”)
As vezes ´e poss´ıvel demonstrar que para um dado problema, qualquer que seja o algoritmo a ser usado, o problema requer pelo menos um certo n´umero de opera¸c˜oes. Essa comple- xidade ´e chamada cota inferior ou “lower bound” do problema. Veja que a cota inferior depende do problema mas n˜ao do particular algoritmo. Usamos a letra Ω em lugar de O para denotar uma cota inferior.
Dizemos queT(n) = Ω(f(n)) se existirem inteiro me constante c tais que T(n)≥cf(n) para n > m.
Para o problema de multiplica¸c˜ao de matrizes de ordemn, apenas para ler os elementos das duas matrizes de entrada leva tempoO(n2). Assim uma cota inferior trivial ´e Ω(n2).
Na analogia anterior, uma cota inferior de uma modalidade de atletismo n˜ao dependeria mais do atleta. Seria algum tempo m´ınimo que a modalidade exige, qualquer que seja o atleta. Uma cota inferior trivial para os 100 metros rasos seria o tempo que a velocidade da luz leva para percorrer 100 metros no v´acuo.
Se um algoritmo tem uma complexidade que ´e igual a cota inferior do problema, ent˜ao ele ´e ´otimo. O algoritmo de Coppersmith e Winograd ´e deO(n2.376) mas a cota inferior ´e de Ω(n2). Portanto n˜ao podemos dizer que ele ´e ´otimo. Pode ser que esta cota superior possa ainda ser melhorada. Pode tamb´em ser que a cota inferior de Ω(n2) possa ser melhorada (isto ´e “aumentada”). Muitos pesquisadores desta ´area dedicam seu tempo tentando encurtar este intervalo (“gap”) at´e encostar uma da outra.
4