You are on page 1of 27

Captulo 5 Eci ncia de Algoritmos e

O estudo da eci ncia de algoritmos refere-se ao comportamento assimpt tico de algoritmos e o que informa da depend ncia do tempo de execucao de um algoritmo em funcao de um par metro e a de entrada. Este par metro e, em geral, um natural que traduz a dimens o do argumento. Por a a exemplo, no caso das listas, este par metro e o seu comprimento. No que se segue os algoritmos a s o codicados em Mathematica a

5.1 Denicoes preliminares


No contexto do estudo da eci ncia de algoritmos interessam funcoes que traduzem o tempo da e execucao de um algoritmo. Em geral este tempo poder depender de mais de uma quantidade a (por exemplo, para funcoes com diversos argumentos). No entanto, o caso mais importante e o de funcoes f : IN0 IR com um s argumento natural. o Na sequ ncia assumir-se- tamb m que estas funcoes tomam valores positivos e que s o e a e a crescentes em sentido lato. Ser utilizada a notacao f = Q(g) com o signicado que o comportamento assimpt tico da a o funcao f : IN0 IR e o mesmo de g. Isto signica que, para valores sucientemente grandes do argumento, a funcao f se comporta essencialmente como g. Mais formalmente, dene-se Q(g) como se segue: Q(g) = { f : $c1 ,c2 IR+ $n0 IN "nn0 c1 g(n) f (n) c2 g(n)} A notacao f = Q(g) signica f Q(g). E tamb m conveniente denir O(g) e W(g) que representam as classes de funcoes limitadas e superiormente, ou inferiormente, por g (a menos de uma constante multiplicativa): O(g) = { f : $c2 IR+ $n0 IN "nn0 0 f (n) c2 g(n)} 63

W(g) = { f : $c1 IR+ $n0 IN "nn0 0 c1 g(n) f (n)} Naturalmente f = O(g) e f = W(g) sse f=Q(g).

5.2 Um exemplo
Para ilustrar o tipo de consideracoes que s o efectuadas consideramos um primeiro exemplo a (simples) que e o algoritmo da determinacao da soma n k. Para facilidade de raciocnio k=1 consideram-se duas colunas, uma com o tempo associado a execucao de cada comando (TE) ` e outra com o n mero de vezes que esse comando e efectuado durante o processamento do u algoritmo (#):

somaNat TE r=0; c1 k=0; c2 While[k!=n, c3 r=r+(k+1); c4 k=k+1] c5

# 1 1 n+1 n n

Os comandos r=0 e k=0 demoram tempos c1 e c2 e s o executados uma unica vez. Sendo n a o conte do da vari vel n (que permanece inalterada) tem-se que o teste da guarda do While e u a executado n + 1 vezes e os comandos do corpo do While s o executados n vezes. A constante a c3 , referente a avaliacao da guarda k!=n, signica que se assume que o tempo da avaliacao ` 1 desta express o e independente dos valores de k e n envolvidos . A constante c4 signica que a se assume tamb m que o tempo da atribuicao r=r+(k+1) n o depende dos valores de r e k. e a Para a constante c5 as consideracoes s o semelhantes. a

O tempo de avaliacao de uma express o o(e1 , ..., en ) , e uma soma denida in a dutivamente na estrutura da express o e que corresponde a soma dos tempos a ` necess rios a determinacao dos valores a1 , ..., an das express es e1 , ..., en argua ` o mento, mais o tempo necess rio a determinacao do resultado de o(a 1 , ..., an ). a ` Assume-se, neste texto, que o tempo da avaliacao de express es aritm ticas o e ou booleanas b sicas e independente dos argumentos em questao. a

O tempo associado a uma atribuicao x=e e a soma do tempo da determinacao do resultado da express o e com uma constante c= correspondente a a ` associacao desse valor a vari vel x. ` a

Esta simplicac frequente, mas n inteiramente correcta em Mathematica, como se discutir em ao e ao e a ap endice.

64

No exemplo anterior, tem-se, em particular, que o tempo de avaliacao de r*(k+1) e o tempo c r , associado a localizacao do valor de r, mais o tempo ck+1 da determinacao do valor de k+1 (que ` corresponde ao tempo associado a localizacao do valor de k, mais o tempo associado a soma) ` ` mais o tempo c* da determinacao do produto daqueles valores. Como referimos, considera-se que estes tempos s o independentes dos valores de k de r. Mais ainda, considera-se tamb m que a e a atribuicao r=r*(k+1) demora um tempo c= , tamb m independente do valor da express o e a r*(k+1). A constante c4 da tabela e, portanto, c4 = cr + ck+1 + c* + c= . Sendo n o valor da vari vel n conclui-se nalmente que o algorimo anterior demora um tempo a TsomaNat (n) = c1 + c2 + c3 (n + 1) + c4 n + c5 n = k1 + k2 n, a que corresponde um comportamento assimpt tico linear. Ou seja: TsomaNat = Q(ln.n). o

5.3 Funcoes
A invocacao de uma funcao levanta algumas quest es que se referem de seguida. Considere-se o a funcao somaNaturais correspondente ao algoritmo j apresentado: a

somaNaturais=Function[n,Module[ r,k , r=0; k=0; While[k!=n, r=r+(k+1);k=k+1]; r]]

O tempo associado a determinacao da express o somaNaturais[arg] e determinado co` a mo se segue: Em primeiro lugar h que determinar o valor da express o argumento arg, a a o que demora Targ . Seja a este valor. Depois h que localizar a funcao somaNaturais, a associar o par metro n ao valor a da express o argumento e criar as vari veis locais r e a a a k. Seja cinv a constante correspondente a soma dos tempos associados a estas actividades ` (e independente do valor a da express o argumento). Posto isto, h que executar o corpo a a da funcao, que e o algoritmo j referido (com n associado a a), seguido da avaliacao de a r. Seja TsomaNat (a) o tempo associado ao algoritmo da determinacao da soma e c res a cons tante associada a avaliacao da vari vel do resultado. Tem-se que avaliacao de somaNatu` a rais[arg] demora TsomaNaturais (a) = Targ + cinv + TsomaNat (a) + cres . O tempo Targ depende da express o argumento em quest o. No caso da invocacao somaNaturais[m], com m a a uma vari vel com valor m teremos que Targ e constante e independente do valor de m pelo que a TsomaNaturais (m) = c + cinv + TsomaNat (m) + cres = a1 + a2 m e linear em m. No caso da invocacao somaNaturais[somaNaturais[m]] vir agora Targ (m) = k1 +k2 m e, notando que o valor a do argumento da invocacao exterior e o valor de somaNaturais[m]= m i = m(m+1) , vir a i=1 2 m m TsomaNaturais (m) = Targ (m) + cinv + TsomaNat (i=1 i) + cres = k1 + k2 m + cinv + k1 + k2 (i=1 i) + cres = a + bm + cm2 , ou seja, um comportamento quadr tico em m. a

65

A determinacao do tempo associado a invocacao f[exp1,...,expn] e ` T = Targ + cinv + Tcor po onde Targ e o tempo associado a determinacao dos valores das express os ` a argumento, Tcor po o tempo associado a execucao do corpo da funcao (e que ` depende, em geral, dos valores daqueles argumentos) e c inv e uma constante associada a invocacao da funcao. `

5.4 Funcoes recursivas


A determinacao do tempo associado ao processamento de funcoes denidas recursivamente, leva, numa primeira fase, a uma denicao recursiva desse tempo. Uma segunda fase correspon de a determinacao de uma express o analtica que caracterize de forma equivalente a funcao ` a denida recursivamente. Consideremos a seguinte denicao recursiva da funcao somaNaturais: somaNaturais=Function[n,If[n==0,0,n+somaNaturais[n-1]]] e a quest o de determinar o tempo da execucao de somaNaturais[m], em funcao do natural a m, conte do da vari vel m. u a Se m = 0 a invocacao factorial[m] demora um tempo c0 correspondente a determinacao da ` express o argumento (este tempo e irrelevante), mais o tempo associado a invocacao da funcao, a ` mais o tempo associado a determinacao do corpo da funcao, para este argumento. Este ultimo ` corresponde a testar a condicao do If e avaliar a express o 0. a [ - ]) Se m > 0 a invocacao factorial[m] demora carg +cinv +ccond +T ( + (onde o valor de n e m) considerando-se a determinacao da express o argumento, a invocacao a da funcao, o teste do If e a determinacao da express o n+somaNaturais[n-1]. Quanto a a T( + [ - ]) demorar c + T ( a n [ - ]) + c que corresponde a ` + determinacao dos argumentos da soma e ao c lculo da soma. Temos assim (juntando as diversas a constantes envolvidas: T (m) = ; c0 se m = 0 c1 + T (m - 1) se m > 0

Note-se que T (m) = c1 + T (m - 1) = 2 c1 + T (m - 2) = i c1 + T (m - i). Para i = m vem T (m) = m c1 + T (0). Temos assim que T = Q(lm.m) o que indica um comportamento assimpt tico do mesmo tipo que a vers o imperativa (linear). o a

Profundidade de Recurs ao
A profundidade de recurs o corresponde ao n mero de invocacoes de uma funcao recursiva que a u est o pendentes. Por exemplo, a determinacao de somaNaturais[3] necessita de somaNaa turais[2] que necessita de somaNaturais[1] que necessita de somaNaturais[0]. 66

 

 

   

Assim, quando se invoca somaNaturais[0] est o pendentes 4 invocacoes (incluindo soa maNaturais[0]), o que signica uma profundidade de recurs o de 4. A invocacao de a 2 somaNaturais[n] implica uma profundidade de recurs o de n + 1. Por omiss o, o sisa a tema Mathematica dene 256 como a profundidade m xima de recurs o: a a
somaNaturaisRecursiva = Function[n, If[n == 0, 0, n + somaNaturaisRecursiva[n 1]]] Function[n, If[n == 0, 0, n + somaNaturaisRecursiva[n 1]]] somaNaturaisRecursiva[253] 32131 somaNaturaisRecursiva[254]

E, no entanto, possvel alterar este valor. Sugere-se o encapsulamento din amico da vari vel a $RecursionLimit, num comando Block. O encapsulamento din mico signica encapsua lamento no tempo, ou seja, que os novos valores das vari veis no corpo de Block s lhes est o a o a atribudos durante a execucao do corpo de Block. No nal da execucao estas vari veis voltam a a ter os valores que lhes estavam atribudos antes da execucao do corpo de Block.
Block[{$RecursionLimit = }, somaNaturaisRecursiva[254]] 32385

5.5 Comparacao entre as vers es recursiva e imperativa o


No exemplo que temos vindo a seguir da soma de naturais, o comportamento assimpt tico e o id ntico. No entanto isto n o signica que uma das vers es n o seja mais r pida que a outra. e a o a a Este tipo de consideracoes envolve comparacao das diversas constantes (tempos de execucao) envolvidas, e n o ser objecto de estudo aqui. No entanto, e importante notar a diferenca entre a a estas duas funcoes somaNaturais. No primeiro caso (da vers o imperativa) a determinacao a de somaNaturais[n] implica uma unica invocacao desta funcao. No caso recursivo a funcao somaNaturais e invocada recursivamente n + 1 vezes. Assumindo que o tempo as sociado a invocacao da funcao somaNaturais imperativa e semelhante ao tempo necess rio ` a a invocacao da vers o recursiva e que os tempos associados ao restante processamento s o, ` a a tamb m, id nticos, conclui-se que a vers o recursiva, embora tamb m linear, e mais lenta que e e a e a vers o imperativa (pois inclui adicionalmente o factor cinv (n + 1) correspondente as n + 1 a ` invocacoes). No gr co seguinte comparam-se os tempos (em segundos) das invocacao somaNaturais[n] a para as vers es recursiva e imperativa e para diversos valores do argumento. O comportamento o representado e, de facto, linear, sendo a vers o imperativa ligeiramente mais eciente que a a
facto, a profundidade considerada pelo Mathematica n + 2, possivelmente por considerar a evene tualidade de ser necess ario invocar somaNaturais[0-1] (ver a ultima linha If[Hold[0==0,0,0 somaNaturaisRecursiva[0-1]]) na invocac seguinte de somaNaturaisRecursiva[254]). ao
2 De

     

:: "reclim": Recursion depth of 256 exceeded

32385 + If[Hold[0 == 0], 0, 0 + somaNaturaisRecursiva[0 1]]

67

recursiva. Em ap ndice descreve-se a forma como se obt m este tipo de gr cos. e e a


1

0.8

0.6

0.4

0.2

2500

5000

7500

10000

12500

15000

17500

Nota: as estrelas correspondem ao tempo de execucao da vers o recursiva e os losangos ao da a vers o imperativa. a

5.6 Listas
Na sequ ncia ser estudado o comportamento assimpt tico de funcoes com argumento e resule a o tado em listas. O sistema Mathematica e implementado internamente em C e, em particular, as listas s o implementadas sobre vectores em C. Isto signica que as operacoes com resultado a em listas criam um novo vector, que representa a lista resultado. Desta forma as operacoes com resultado em listas dependem (pelo menos) linearmente do comprimento da lista criada.

5.6.1 Eci ncia de algumas funcoes Mathematica e


De seguida ser o referidas algumas operacoes com argumento e/ou resultado em listas e o seu a comportamento em termos de eci ncia. Comecamos por operacoes com argumento em listas e e que n o dependem do comprimento das mesmas. a Comprimento e acesso a elementos Os tempos de execucao das operacoes Length, Part (ou [[...]]) s o independentes do a comprimento da lista em quest o. No primeiro caso sup e-se que a representacao interna das a o listas inclui explicitamente o seu comprimento e, no segundo caso, pressup e-se acesso directo o aos elementos das listas3 . Em geral, o tempo associado as operacoes cujo resultado e uma lista e linear no comprimento ` dessa lista.
3 A resposta do apoio t ecnico da Wolfram foi a seguinte: The Length function requires constant time because the length of a list is typically stored separately in the data structure used to represent the list. Selecting an element from a list (the Part function) requires constant time because indexing can be done by jumping to a particular offset in the array, without the need to scane through each element in the array.

68

Construcao O tempo associado as operacoes que constroem listas (Table, Prepend, Append, In sert, ...) depende linearmente do comprimento da lista resultado. Assim o tempo associado a determinacao da express o Table[i, i,1,N ] que dene uma lista de comprimento N e ` a linear em N. Sendo L o comprimento da lista guardada em l, o tempo associado a determinacao das ex` press es Prepend[l,5], Append[l,5] e Insert[l,1,5] dependem linearmente de o L + 1. Eliminacao de elementos O tempo associado as operacoes que eliminam elementos depende linearmente do comprimento ` da lista resultado. Assim, sendo L o comprimento da lista l, a operacao Rest[l] depende linearmente de L - 1. O mesmo e verdade para Drop[l,-1]. Outros casos ser o referidos a quando necess rio. a Atribuicao A atribuicao a uma vari vel de uma lista j construda e independente do comprimento dessa a a lista. Por exemplo, a atribuicao l=l1 e constante e independente da lista guardada em l1. Comparacao de listas

A comparacao l=== comparacao l== . Outras express oes


Como se referiu, em casos mais complexos, h que determinar o tempo de execucao total coa mo a soma dos tempos envolvidos na determinacao das v rias parcelas. Assim, por exem a plo, sendo L1 o comprimento da lista associada a vari vel , o tempo associado a atribuicao ` a ` l1=Prepend[Table[i, i,1,N ],First[Rest[l1]]] e a soma TRest +cFirst +TT able + TPrepend + c= = [a + b(L1 - 1)] + cFirst + [a + b N] + [a + b (N + 1)] + c= . Este tempo depende linearmente quer de N quer de L.

5.6.2 Supremo na vers imperativa ao


Determina-se de seguida o comportamento assimpt tico da vers o imperativa do supremo de o a uma lista, em funcao do comprimento desta L. O que se refere e o tempo necess rio a execucao a ` de supremo[l], para uma dada lista xa associada a l(ou seja, sem contabilizar o tempo que, eventualmente, tenha sido necess rio para determinar l). a 69

n o depende do comprimento de l. O mesmo n o se passa com a a a

supremo=Function[l,Module[ r,k,comp , r=-Infinity; k=0; comp=Length[l]; cLength While[k!=comp, c4 If[r>l[[k+1]],r=l[[k+1]]] ; c5 ou c5 + c6 k=k+1]; c7 r]] c8

TE cinv c2 c3

# 1 1 1 1 L+1 L L 1

N o h diculdade em preencher o quadro anterior, recordando que o tempo associado a dea a ` terminacao do comprimento da lista cLength e independente do comprimento desta. A guarda do While e testada L + 1 vezes. Quanto ao If[ ] h sempre que testar a condicao (o a que demora c5 ). Consoante a condicao seja verdadeira ou falsa haver ou n o que executar a a r=l[[k+1]]. O tempo desta atribuicao e independente do comprimento da lista, pois, como referimos, o acesso aos elementos e directo. Assim, a execucao do If demora ou c 5 ou c5 + c6 . A an lise desta quest o e abordada de seguida. a a Melhor e pior casos As duas possibilidades de execucao do If levam a considerar dois casos: o melhor caso, em que o mnimo e o primeiro elemento da lista e, portanto, a execucao do If demora sempre c5 ; e o pior caso em que o mnimo e o ultimo elemento da lista, e, portanto, a execucao do If demora sempre c5 +c6 . (Considera-se que a lista e n o vazia, j que o que se pretende e entender a a o comportamento do algoritmo para listas com muitos elementos). Tem-se, para estes casos:
melhor Tsup (L) = cinv + c2 + c3 + cLength + c4 (L + 1) + c5 L + c7 L + c8 = k + k L

pior Tsup (L) = cinv + c2 + c3 + cLength + c4 (L + 1) + (c5 + c6 )L + c7 L + c8 = k + k L

Como em ambos os casos o comportamento e linear, conclui-se que o comportamento as simpt tico de Tsup e sempre linear, ou seja o
melhor pior Tsup = Tsup = Tsup = Q(lL.L)

5.6.3 Supremo na vers imperativa com progresso na lista argumento ao


Nesta nova vers o o progresso e efectuado numa lista lp, que indica quais os elementos que a ainda n o foram analisados. A funcao correspondente e apresentada no quadro seguinte. a

70

supremo=Function[l,Module[ r,lp , r=-Infinity; lp=l; While[Length[lp] != 0, If[r>First[lp],r=First[lp]] ; lp=Rest[lp]]; r]]

TE cinv c2 c3 c4 c5 ou c5 + c6 c7 LRl p + c 7 c8

# 1 1 1 L+1 L L 1

Nota-se que o tempo de execucao da atribuicao lp=l e considerado constante e independente do comprimento da lista l e que o tempo de execucao do teste Length[lp] != 0 e, tamb m, e independente de lp (pois o tempo da determinacao de Length[lp] e independente de lp). O tempo de execucao do teste r>First[lp] e tamb m constante, pois o acesso ao primeiro e elemento n o depende do comprimento da lista. a Finalmente, a diferenca importante relativamente a solucao anterior e a determinacao da ex ` press o Rest[lp] na atribuicao lp=Rest[lp]. A determinacao de Rest[lp] correspona de a construcao de uma nova lista para que e necess rio um tempo linear no comprimento L Rl p ` a de Rest[lp]. Este comprimento varia entre L - 1 na primeira iteracao e 1 - 1 na ultima. Tem-se assim
melhor Tsup (L) = cinv + c2 + c3 + c4 (L + 1) + c5 L + (c7 LRl p + c ) + c8 7 L-1 LRl p =0

Quanto ao somat rio tem-se: o (c7 Ll p +


L-1

c ) 7

LRl p =0

melhor Desta forma Tsup (L) = k + k L + k L2 tem um comportamento quadr tico em L: a melhor Tsup = Q(lL.L2 )

= c7 LRl p +
L-1 LRl p =0

O pior caso e semelhante e assim esta vers o da funcao supremo e quadr tica em L. a a Claramente a solucao anterior e melhor em termos de eci ncia. No gr co seguinte comparam e a se os tempos de execucao (em segundos) das duas vers es do supremo para listas entre 1000 o e 14 000 elementos, ordenados por ordem crescente (pior caso). As estrelas correspondem a ` vers o quadr tica (progresso em listas) e os losangos a vers o linear (progresso em ndice). a a ` a

c 7

LRl p =0

1 = c7
L-1

(L - 1)(L) + c L 7 2

71

3.5 3 2.5 2 1.5 1 0.5

2000

4000

6000

8000

10000

12000

14000

5.6.4 Supremo recursivo


Vamos tamb m considerar diversas solucoes recursivas para o problema da determinacao do e supremo. Solucao exponencial Em primeiro lugar, uma solucao conceptualmente natural, que e a seguinte:
supremo1 = Function[l, If[l === {}, -Infinity, If[First[l] > supremo1[Rest[l]], First[l], supremo1[Rest[l]]]]]

A determinacao do comportamento assimpt tico desta funcao passa tamb m pelo comporta o e mento no melhor e pior casos, que se denem em termos do comprimento L da lista argumento. Melhor caso
melhor Para o melhor caso temos Tsup1 (0) = c0 , onde c0 inclui a invocacao da funcao, o teste da melhor guarda, e a determinacao da express o correspondente. Para L 0 vem Tsup1 (L) = cinv + a melhor cl==={} + cFirst[l] + [a + b(L - 1)] + Tsup1 (L - 1) + c> + cFirst[l] . O termo [a + b(L - 1)] vem de se melhor determinar Rest[l] e o termo Tsup1 (L - 1) vem da determinacao do supremo de Rest[l]. Em resumo: melhor Tsup1 (L) = ;

c0 se L = 0 melhor c1 + c2 L + Tsup1 (L - 1) se L 0

A solucao (iterativa) desta recorr ncia e como se segue: e


melhor melhor melhor Tsup1 (L) = c1 + c2 L + Tsup1 (L - 1) = 2c1 + c2 L + c2 (L - 1) + Tsup1 (L - 2) = ...

N o e difcil concluir (e pode ser estabelecido por inducao) que a 72

melhor Tsup1 (L)

Fazendo i = L vir a
L-1

Ou seja:

melhor Tsup1 (L) = c1 L + c2 (L - k) + c0 = c0 + c1 L + c2 L2 - c2 k = c0 + c1 L + c2 L2 - c2 L-1 k=0 k=0 melhor Tsup1 = Q(lL.L2 )

melhor = ic1 + c2 (L - k) + Tsup1 (L - i) i-1 k=0

L(L - 1) 2

E importante notar que comportamento quadr tico para o melhor caso vem da determinacao de a Rest[l]. Pior Caso Quanto ao pior caso vir Tsup1 (0) = c0 mas, para L 0, tem-se agora a Tsup1 (L) = cinv +cl==={} +cFirst[l] +aRest +bRest (L-1)+Tsup1 (L-1)+c> +aRest +bRest (L-1)+Tsup1 (L-1) ou seja Tsup1 (L) = ;
pior pior pior pior pior pior

c0 se L = 0 pior c1 + c2 L + 2Tsup1 (L - 1) se L 0

A solucao (iterativa) desta recorr ncia e: e Tsup1 (L) = c1 + c2 L + 2Tsup1 (L - 1) = c1 + c2 L + 2c1 + 2c2 (L - 1) + 4Tsup1 (L - 2) = ... e assim
pior Tsup1 (L) pior pior

Quando i = L tem-se nalmente


pior Tsup1 (L) L-1 L-1 k

Ou seja:

= c1 2 + 2k c2 (L - k) + 2L c0 = c1 (2L - 2) + (2L+1 - (L + 2))c2 + 2L c0


k=1 k=0

= 2 c1 + 2k c2 (L - k) + 2i Tsup1 (L - i)
i-1 i-1 k pior k=0 k=0

Tsup1 = Q(lL.2L )

pior

Esta situacao e catastr ca em termos de eci ncia e decorre do facto de se determinar duas o e vezes o supremo1[Rest[l]]. Dada a diferenca fundamental entre o melhor e pior casos, seria importante vericar qual o caso m dio. N o o faremos aqui (n o e difcil vericar que e do e a a mesmo tipo do pior caso). O que nos interessa e encontrar solucoes melhores para esta quest o. a 73

Solucao quadr tica a Nesta solucao evita-se a dupla avaliacao de supremo[Rest[l]] guardando este resultado numa vari vel auxiliar. a
supremo2 = Function[l, Module[{s}, If[l == {}, -Infinity, s = supremo2[Rest[l]]; If[First[l] > s, First[l], s]]]]

N o e difcil vericar que, neste caso, a Tsup2 (L) = ;


pior

c0 se L = 0 pior c1 + c2 L + Tsup2 (L - 1) se L 0

pelo que a nova solucao e sempre quadr tica em L. (O melhor caso e semelhante). a De qualquer forma existe ainda uma diferenca importante face a primeira vers o imperativa, ` a que era linear em L. Como se referiu n o h necessariamente diferenca essencial entre o coma a portamento assimpt tico das vers es recursivas e imperativas, pelo que a diferenca agora notada o o dever ter outra causa. Como j se referiu a causa e o facto de se utilizar progresso em listas, a a ou seja porque se determina Rest[l]. E, no entanto, possvel escrever vers es recursivas da funcao supremo, percorrendo a lista com o um ndice, em vez de a percorrer usando Rest[l]. Solucao linear A solucao linear evita a avaliacao de Rest[l] porque considera uma representacao das listas semelhante a que j se apresentou com vectores em C. Assim, a lista original l e associado um ` a ` incio e um m, o que permite representar Rest[l] como sendo a mesma lista, mas com o incio adiantado de 1. A nova solucao utiliza uma funcao auxiliar que progride no incio da lista original.
supremo3 = Function[l, Module[{auxsupremo}, auxsupremo = Function[{incio, fim}, Module[{s}, If[incio == fim + 1, -Infinity, s = auxsupremo[incio + 1, fim]; If[l[[incio]] > s, l[[incio]], s]]]]; auxsupremo[1, Length[l]]]]

Para esta solucao Tsup3 (L) = cinv + caux... + Tauxsupremo(1,L) , onde caux... refere a constante relativa a ` atribuicao do nome auxsupremo a funcao correspondente. ` Quanto a Tauxsupremo(1,l) e f cil vericar que o seu tempo de execucao depende da diferenca a fim+1-incio (com incio=1 e fim=L) e facilmente se chega a
pior

pior

pior

74

A solucao desta recorr ncia j foi apresentada a prop sito da funcao somaNaturais e obt m e a o e pior pior pior pior se Tauxsupremo (L) = k0 + k1 L. Recordando que Tsup3 (L) = cinv + caux.. + Tauxsupremo (L) vir Tsup3 (L) = a k0 + k1 L, ou seja, como se pretendia, linear em L. O melhor caso e semelhante e omite-se. Comparacao entre a solucao linear e a quadr tica a No gr co seguinte mostram-se os tempos de execucao (em segundos) dos piores casos das a solucoes linear e quadr tica para listas entre 100 e 8 000 elementos. a
5 4 3 2 1 2000 4000 6000 8000

pior Tauxsupremo (L) = ;

c0 se L = 0 pior c1 + Tauxsupremo (L - 1) se L 0

Comparacao entre as solucoes lineares recursiva e imperativa No gr co seguinte mostram-se os tempos de execucao (em segundos) dos piores casos das a solucoes lineares recursiva e imperativa para listas entre 100 e 14 000 elementos. Como se espera, embora do mesmo tipo, a solucao imperativa e mais r pida que a recursiva. a
3.5 3 2.5 2 1.5 1 0.5

2000

4000

6000

8000

10000

12000

14000

5.6.5 Outras representacoes


Uma outra possibilidade de melhorar a eci ncia de algorimos sobre listas e considerar outras e representacoes. Uma representacao util e a que se exemplica de seguida: em vez de utilizar 75

a lista {4, 3, 2, 1} pode utilizar-se a lista (de listas) {4, {3, {2, {1, {}}}}}. Desta forma cada lista (` a excepcao da lista vazia) tem dois elementos: o valor e a lista restante. A funcao seguinte determina o supremo de uma lista (nesta representacao) em tempo linear (no n mero de elementos a percorrer): u
supremo=Function[ll,Module[ s ,If[ll=== , -Infinity, s=supremo[ll[[2]]]; If[s>ll[[1]],s,ll[[1]]]]]]

No gr co seguinte apresentam-se os tempos de execucao da funcao anterior para o pior caso da a determinacao do supremo de listas (na representacao referida) contendo at 15.000 elementos: e

3 2.5 2 1.5 1 0.5 2000 4000 6000 800010000 12000 14000

5.6.6 Pesquisa
No caso da pesquisa h duas situacoes a ter em consideracao: determina-se o tempo quando a a pesquisa tem sucesso e o tempo quando a pesquisa n o tem sucesso. a Sucesso Comecemos pela primeira situacao. Como o tempo de execucao depende da posicao em que se encontrar o elemento x que se pesquisa, vamos determin -lo assumindo que a posicao em que a se encontra (primeiro) o elemento x e a posicao i (com 1 i L). Temos assim:

TE pesquisa=Function[ l,x ,Module[ r,k,comp , cinv r=False; c2 k=0; c3 comp=Length[l]; k1 While[k!=comp && Not[r], c4 r= (l[[k+1]]==x) ; c5 k=k+1]; c6 r]] c7

# 1 1 1 1 N(i) N(i) - 1 N(i) - 1 1

76

N o e difcil vericar que o n mero de vezes N(i) que e executada a guarda do While e N(i) = a u i + 1. Temos assim Tpesq (L, i) = a + bi. Melhor e pior casos No melhor caso (i = 1) vir Tpesq (L) = a . No pior caso (i = L) vir Tpesq (L) = a + bL. a melhor a pior Conclumos que o comportamento assimpt tico no pior caso e linear em L e que no melhor caso o e constante. Vale assim a pena determinar o caso m dio. e Caso m dio e O caso m dio corresponde a m dia dos tempos de execucao para as diversas listas de come ` e primento L. Se n o existe informacao adicional sobre a distribuicao dos elementos da lista, a o elemento a pesquisar pode estar em qualquer posicao, sem que se prera uma a outra. Isto signica que a probabilidade de x se encontrar numa posicao i e igual a de se encontrar numa ` outra i . Temos portanto que esta probabilidade e p(i) = 1/ L. A m dia dos tempos e e Tpesq (L) = Tpesq (L, i) p(i) =
L L i=1 i=1 L

Tpesq (L, i) L

Tem-se assim:
L

Conclui-se que o tempo deste algoritmo de pesquisa e, em m dia, linear em L: e Tpesq = Q(lL.L) Insucesso

a + bi a L b b 1 Tpesq (L) = = + i = a + L(L + 1) = a + b L L L L i=1 L 2 i=1

O caso de o elemento n o se encontrar na lista e exactamente o pior caso analisado anteriora mente, e, portanto, linear em L.

5.6.7 Pesquisa Recursiva


Vamos agora determinar o tempo de execucao da vers o recursiva do algoritmo de pesquisa, a separando este estudo, mais uma vez nos dois casos j referidos, de sucesso e de insucesso. a 77

Como j vimos, por raz es de eci ncia, e conveniente representar a recurs o por interm dio a o e a e de ndices representando o incio e o m da lista argumento. E essa a solucao que utilizaremos:
pesquisa2 = Function[{l, x}, Module[{auxpesquisa}, auxpesquisa = Function[{incio, fim}, If[incio == fim + 1, False, Or[l[[incio]] == x, auxpesquisa[incio + 1, fim]]]]; auxpesquisa[1, Length[l]]]]

Sucesso Omite-se o estudo do melhor e pior casos. O caso m dio e analisado de seguida. e
i Primeira solucao A primeira solucao corresponde a considerar os tempos Tpesq (L) correspon dentes a execucao da funcao pesquisa, sabendo que o elemento x se encontra na posicao i da ` lista argumento (a lista n o pode ser vazia, neste caso). a i i Para tal h que notar primeiro que Tpesq (L) = c + Tauxpesquisa(1,L) (onde a constante c inclui a a invocacao e a atribuicao auxpesquisa = ...). i Quanto a determinacao de Tauxpesquisa(1,L) e conveniente determinar primeiro a express o de ` a i Tauxpesquisa( j,L) com j i. Se i = j, vir a i Tauxpesquisa(i,L) = cinv + c== + c== = c1

pois x encontra-se na posicao inicial. Nota-se que a avaliacao do Or e sequencial, pelo que, se l[[inicio]] == x o resultado e True sem que se tenha de avaliar o segundo argumento do Or. Se j < i vir a
i i i Tauxpesquisa( j,L) = cinv + c== + c== + Tauxpesquisa( j+1,L) = c1 + Tauxpesquisa( j+1,L)

Facilmente se conclui que


i i i i Tauxpesquisa( j,L) = c1 + Tauxpesquisa( j+1,L) = c1 + c1 + Tauxpesquisa( j+2,L) = kc1 + Tauxpesquisa( j+k,L)

Quando j + k = i vir a
i i Tauxpesquisa( j,L) = (i - j)c1 + Tauxpesquisa(i,L) = (i - j + 1)c1

Portanto
i Tauxpesquisa(1,L) = ic1

Assim
i Tpesq (L) = c + ic1

Nota-se que o melhor caso corresponde a i = 1 (constante) e o pior a i = L (linear).

78

i Finalmente, o valor m dio de Tpesq (L) e a m dia dos diversos Tpesq (L). Recordando que assumie e mos que a probabilidade de x se encontrar em i e 1/ L tem-se L pesq (L) = i=1 (c + ic1 ) = c + c1 (L + 1) T L 2

Desta forma a funcao pesquisa tem um comportamento assimpt tico linear para o caso m dio: o e Tpesq = Q(lL.L) Segunda solucao A segunda solucao e obtida observando que a probabilidade de x se encon trar na primeira posicao e 1/ L e a probabilidade de se encontrar noutra posicao e (L - 1)/ L. Seja 1 Tauxpesquisa (1, L) o tempo da execucao da funcao auxpesquisa quando x se encontra na primeira posicao e T auxpesquisa (1, L) a m dia dos tempos de execucao da funcao auxpesquisa quando e x n o se encontra na primeira posicao. a A m dia dos tempos de execucao ser a soma destes tempos, pesada pelas respectivas probabie a lidades: Tauxpesquisa (1, L) =
1 Tauxpesquisa (1, L)

L-1 T (1, L) L auxpesquisa

1 Tem-se que Tauxpesquisa (1, L) = cinv + cI f + c== + cOr = c1 . Por outro lado, T auxpesquisa (1, L) = cinv + cI f + c== + cOr + cinicio+1 + c f im + Tauxpesquisa (2, L) = c2 + Tauxpesquisa (2, L). Ora, o tempo m dio Tauxpesquisa (2, L) de processamento da lista original desde a posicao 2 at a posicao L e e e` id ntico ao tempo m dio de processamento de uma lista de comprimento L - 1. Desta forma, e e T auxpesquisa (1, L) = c2 + Tauxpesquisa (2, L) = c2 + Tauxpesquisa (1, L - 1).

Vem ent o a

c L-1 Tauxpesquisa (1, L) = 1 + (c - 2 + Tauxpesquisa (1, L - 1)) L L que e equivalente a LTauxpesquisa (1, L) = c1 + c2 (L - 1) + (L - 1)Tauxpesquisa (1, L - 1)

Designando f(L) = LTauxpesquisa (1, L) a equacao anterior escreve-se: f(L) = c1 + c2 (L - 1) + f(L - 1) Esta recorr ncia em f resolve-se por iteracao obtendo-se f(L) = a + bL2 . Como f(L) = e LTauxpesquisa (1, L) vir que Tauxpesquisa (1, L) e linear em L. O resto da resolucao e como se aprea sentou na primeira solucao obtendo-se Tpesq = Q(lL.L) Insucesso A situacao de insucesso deixa-se como exerccio. 79

5.6.8 Comparacao entre a vers imperativa e a recursiva ao


Apresenta-se o gr co dos tempos de execucao da pesquisa, no pior caso, para as vers es ima o perativa e recursiva:
2.5 2 1.5 1 0.5 5000 10000 15000 20000 25000

5.7 Teorema principal


O teorema principal e um instrumento util na determinacao de uma express o analtica explcita a para funcoes dedas por recorr ncias do tipo T (n) = aT (n/ b) + f (n) e ser necess rio quando e a a discutirmos a eci ncia de algoritmos de ordenacao. e

Seja T : IN IR uma func positiva e crescente (em sentido lato) que satisfaz a recorr ao encia T (n) = aT (n/ b) + f (n) (para todo o n n0 ), onde a, b IR+ .
log Se existe e > 0 tal que f = O(ln.nlogb (a)-e ) ent T = Q(ln.n b (a) ) ao

Se f = Q(ln.nlogb (a) ) ent T = Q(ln. log(n) nlogb (a) ) ao 2 Se existe e > 0 tal que f = W(ln.nlogb (a)+e ) e $0c1 <1 $n1 "nn1 a f (n/ b) c f (n) ent T = ao Q(ln. f (n))

A prova deste teorema pode ser encontrada em [2]. No enunciado do teorema anterior pode substituir-se a recorr ncia T (n) = aT (n/ b) + f (n) por T (n) = aT (dn/ bt) + f (n) ou por T (n) = e aT (`n/ bp) + f (n). (Recorda-se que, para x IR + , dxt = max{n IN0 : n x} e que `xp = min{n IN0 : n x}.)

5.8 Algoritmos de ordenacao


Vamos considerar o comportamento assimpt tico dos algoritmos de ordenacao Insercao Dio recta, Quicksort e Merge Sort. Considera-se na an lise de eci ncia deste algoritmos que n o existe informacao adicional sobre a e a os elementos das listas a ordenar, nem de como eles se comparam uns com os outros. 80

Um elemento arbitr rio x numa lista l (em determinada posicao k), ir ocupar uma posicao nal a a p na lista depois ordenada (posicao essa que depende do seu relacionamento com os outros elementos de l). Assumimos, de acordo com o que se disse acima, que a probabilidade de esta posicao nal p ser uma determinada posicao entre 1 e L (o comprimento de l) e 1/ L. Isto corresponde a armar que todas as posicoes s o equiprov veis, pois n o existe raz o para a a a a preferir uma a outra.

5.8.1 Insercao directa


De seguida apresenta-se o quadro relativo aos tempos de execucao do algoritmo de insercao directa. Antes de o comentar e conveniente recordar que, em cada execucao do ciclo interior, se assume que a lista est ordenada at a posicao k, encarregando-se o ciclo interior de a ordenar a e` at a posicao k + 1. Para este prop sito o elemento l[[k + 1]] e deslocado para a esquerda at e` o e car na posicao que lhe corresponde. Sendo pk+1 a posicao nal do elemento l[[k + 1]] (entre 1 e k + 1) n o e difcil concluir que a guarda do ciclo interior e executada um n mero de vezes que a u depende quer de k quer de pk+1 . Esse n mero de vezes e designado por N(k, pk+1 ). O n mero u u total de vezes que a guarda do ciclo interior e executada e a soma de N(k, p k+1 ) para cada k desde4 k = 1 at k = L - 1. e Esclarecido este ponto o quadro seguinte e de preenchimento f cil, recordando as hip teses a o j explicitadas sobre o comportamento assimpt tico de funcoes Mathematica sobre listas, em a o particular que a determinacao do comprimento e o acesso a elementos s o constantes que n o a a dependem do comprimento da lista em quest o. a Insercao Directa TE # k=1; c1 1 While[k<Length[l], c2 L+1 elemento=l[[k+1]]; c3 L i=k+1; c4 L L-1 While[i>1 && l[[i-1]]> elemento, c5 N(k, pk+1 ) k=1 l[[i]]=l[[i-1]]; c6 L-1 (N(k, pk+1 ) - 1) k=1 i=i-1]; c7 L-1 (N(k, pk+1 ) - 1) k=1 l[[i]]=elemento; c8 L k=k+1] c9 L Falta agora determinar o valor de N(k, pk+1 ), que, depois de alguma reex o e, simplesmente, a N(k, pk+1 ) = (k + 1 - pk+1 ) + 1. Melhor e pior casos O melhor caso corresponde a pk+1 = k + 1 (para todo o k) que e a situacao em que o elemento l[[k + 1]] ca na posicao que j ocupava. Isto signica que a lista j se encontrava ordenada. a a
discuss do comportamento assimpt ao otico s interessam listas de comprimento grande, pelo que o podemos assumir L > 1.
4 Nesta

81

O pior caso corresponde a pk+1 = 1 (para todo o k) que signica que o elemento l[[k + 1]] era menor que todos os anteriores e ir ser colocado no incio da lista. Esta situacao corresponde a a ` lista estar ordenada por ordem decrescente. Sendo assim temos
melhor Tins (L)

Para o pior caso vir a


pior

= c1 + c2 (L + 1) + c3 L + c4 L + c5 1 + c8 L + c9 L = a + bL
L-1 k=1 L-1 L-1

Tins (L) = c1 + c2 (L + 1) + c3 L + c4 L + c5 (k + 1) + (c6 + c7 ) k + c8 L + c9 L = a + bL + gL2


k=1 k=1

Caso m dio e

Para a an lise do caso m dio utiliza-se o valor m dio de N(k, pk+1 ) = (k + 1 - pk+1 ) + 1, para a e e cada k. Ora pk+1 e a posicao nal do elemento l[[k + 1]] (que vai ser analisado) na sublista da lista original que vai das posicoes 1 at k + 1. N o existe raz o para preferir alguma daquelas e a a posicoes a outra, pelo que existe igual probabilidade de pk+1 ocupar uma das posicoes entre 1 e 1 k + 1. Essa probabilidade e, evidentemente, k+1 . Desta forma o valor m dio de N(k, pk+1 ) = (k + 1 - pk+1 ) + 1 e e (k + 1 - pk+1 ) + 1 1 N(k, pk+1 ) = =k+2N(k) = p k+1 k+1 k + 1 p =1 k+1 p =1 p =1
k+1 k+1 k+1
k+1 k+1 k+1

e assim

N(k) = k + 2 -

1 (k + 2)(k + 1) k + 2 = k+1 2 2

Quanto ao tempo m dio de processamento do algoritmo de insercao directa tem-se e Tins (L) = c1 + c2 (L + 1) + c3 L + c4 L + c5 N(k) + (c6 + c7 ) (N(k) - 1) + c8 L + c9 L
L-1 L-1 k=1 k=1 L-1 L-1

ou seja

k+2 k Tins (L) = c1 + c2 (L + 1) + c3 L + c4 L + c5 + (c6 + c7 ) + c8 L + c9 L = a + b L + g L2 2 2 k=1 k=1 Em resumo


pior melhor Tins = Q(lL.L) e Tins = Tins = Q(lL.L2 )

82

5.8.2 Quicksort
A vers o deste algoritmo que iremos considerar e a seguinte: a quicksort=Function[l,Module[ x , If[l=== , , x=First[l]; Join[quicksort[Select[l,Function[y,y<x]]], Select[l,Function[y,y==x]], quicksort[Select[l,Function[y,y>x]]]]]]] O estudo da eci ncia deste algoritmo pressup e, por raz es de simplicidade, que n o existem e o o a elementos repetidos na lista original. A quest o mais relevante neste algoritmo e a de determinar qual a relacao entre as sublistas dos a elementos respectivamente estritamente menores e maiores que x. Pior caso A pior situacao corresponde a x ser o mnimo (ou o m ximo) da lista. Nesta situacao a lista a dos elementos estritamente superiores a x ou a lista dos elementos estritamente inferiores a x, tem comprimento L - 1 (se L for o comprimento da lista original). O pior caso corresponde a ` repeticao recursiva desta situacao, ou seja, escolha repetida ou do mnimo ou do m ximo das a listas que s o recursivamente argumento da funcao quicksort. a Considerando que determinacao de cada Select e linear em L, que a juncao destas tr s listas e tem comprimento L e que, portanto, a determinacao de Join e tamb m linear em L vem (para e L 0):
pior pior pior

Tquick (L) = cinv + c=== + c= + TSelects + c0 + Tquick (L - 1) + TJoin = a + bL + Tquick (L - 1)

onde c0 e o tempo associado a avaliacao de quicksort[ `


pior

A solucao desta recorr ncia tem como resultado Tquick = Q(lL.L2 ). e Melhor caso Quanto ao melhor caso e obtido quando (recursivamente) se divide a lista original em duas, ou seja quando o elemento escolhido e recursivamente a mediana da lista em quest o. a Tem-se
melhor melhor melhor Tquick (L) = cinv + c=== + c= + TSelects + Tquick (d(L - 1)/ 2t) + Tquick (`(L - 1)/ 2p) + TJoin

e, nalmente L melhor Tquick (L) a + b L + 2Tmelhor (d t) 2 83

].

melhor Recorrendo ao teorema principal obt m-se Tquick = Q(lL.L log2 (L)). e

Caso M dio e Para o caso m dio consideramos as diversas possibilidades de comparacao do elemento escoe lhido x com os outros elementos da lista. Estas possibilidades s o caracterizadas por um ndice 5 a i que indica quantos elementos s o menores ou iguais a x na lista argumento (recorda-se que a assumimos serem todos distintos). Claramente 1 i L e qualquer destas L situacoes e equiprov vel. Fixado um i, o tempo a i Tquick (L) da execucao desta funcao e, assim, cinv + c=== + c= mais o tempo da determinacao dos v rios Select, mais o tempo da determinacao da funcao quicksort em listas de comprimento a i - 1 (dos menores que x) e L - i (dos maiores que x) mais o tempo de Join. Em m dia o e tempo da determinacao da funcao quicksort em listas de comprimento i - 1 e L - i e Tquick (i - 1) e Tquick (L - i) respectivamente, pelo que, xado i o tempo m dio de execucao e, Tquick (L) = e i cinv + c=== + c= + a + bL + Tquick (i - 1) + Tquick (L - i), onde o termo a + bL e a soma da contribuicao dos tempos dos v rios Select e do Join. a Finalmente, o tempo m dio de execucao da funcao quicksort e a m dia dos tempos (m dios) e e e para cada i, ou seja: Tquick (L) =
L i=1

Tquick (i - 1) + Tquick (L - i) + a + bL L
Tquick (i-1)+Tquick (L-i) L

A ultima igualdade decorre de o segundo somat rio ser igual ao primeiro o o que se pode concluir com a mudanca de vari vel k = L - i + 1 (e trocando a ordem dos termos a somados). Temos assim Tquick (L) = a + bL + 2
L i=1

(i-1) T a+bL+2 L quickL . i=1

Tem-se ainda Tquick (L) = a + bL + L i=1

= a + bL + L i=1

Tquick (i-1) L

+ L i=1

Tquick (L-i) L

Tquick (i - 1) L

Para L - 1 vir a

Tquick (L - 1) = a + b(L - 1) +

2 = a + bL + Tquick (i - 1) L i=1
L

Multiplicando a primeira igualdade por L e a segunda por L - 1 obt m-se e LTquick (L)-(L-1)Tquick (L-1) = (a+bL)L-(a+b(L-1))(L-1)+2( Tquick (i-1)- Tquick (i-1))
L L-1 i=1 i=1

2 T (i - 1) L - 1 i=1 quick
L-1

o que implica

LTquick (L) - (L - 1)Tquick (L - 1) = (a + bL)L - (a + b(L - 1))(L - 1) + 2Tquick (L - 1)

A estat stica de ordem i de x em l a posic de x em l depois de l ser ordenada. Assim i - 1 e indica quantos e ao elementos de l s menores que x. O ao ndice i referido precisamente esta estat e stica.
5

84

e ainda LTquick (L) - (L + 1)Tquick (L - 1) = (a + bL)L - (a + b(L - 1))(L - 1) = a + b + 2bL Dividindo por L(L + 1) obt m-se e Tquick (L) L+1 Designando
Tquick (L) L+1

Tquick (L - 1) L

a + b + 2bL L(L + 1)

por f(L) temos a recorr ncia e f(L) = f(L - 1) + a + b + 2bL L(L + 1)

cuja solucao e f(L) = f(1) +


L-1 i=0 L-1 0

a + b + 2b(L - i) (L - i)(L - i + 1)

e e aproximada pelo integral correspondente: f(L) = f(1) +


Tquick (L) L+1

(onde, por comodidade se fez x = L - i).

O integral tem como solucao ((a + b)ln(x) + (b - a)ln(x + 1))|L que e Q(lL.ln(L)). 1 Como f(L) = tem-se nalmente6 Tquick = Q(lL.L log2 (L))

L a + b + 2b(L - i) a + b + 2bx di = f(1) + dx (L - i)(L - i + 1) x(x + 1) 1

5.8.3 MergeSort
Recorda-se a funcao que ordena por fus o bin ria e que depende da funcao combina. a a ordena=Function[l,Module[ m , If[Length[l]<=1,l, m=Quotient[Length[l]+1,2]; combina[ordena[Take[l,m]],ordena[Drop[l,m]]]]]] Tem-se para o tempo de execucao desta funcao (passo) Tmerge (L) = cinv + c= + a + bL + Tmerge (dL + 1/ 2t) + T (L - dL + 1/ 2t) + Tcombina (L)
a relac entre logaritmos de bases distintas. ao

6 Recorde

85

onde o termo a + bL decorre da determinacao de Take e Drop. A equacao que nos interessar a e Tmerge (L) a + bL + 2Tmerge (dL/ 2t) + Tcombina (L) A depend ncia da funcao combina e fundamental. Uma vers o j apresentada e a seguinte: e a a combina=Function[ l1,l2 , If[l1=== ,l2, If[l2=== ,l1, If[First[l1]<First[l2], Prepend[combina[Rest[l1],l2],First[l1]], Prepend[combina[l1,Rest[l2]],First[l2]]]]]] A funcao combina depende dos comprimentos L1 e L2 das listas argumentos e tem-se (no passo): Tcombina (L1 + L2 ) = cinv + c=== + c=== + c< + a + b(L1 + L2 ) + Tcombina (L1 + L2 - 1) onde o termo a + b(L1 + L2 ) tem duas contribuicoes: a determinacao de Rest (que constr i o uma lista de comprimento L1 - 1 ou L2 - 1) e a determinacao de Prepend que constr i uma o lista de comprimento L1 + L2 - 1 + 1. Designando L = L1 + L2 tem-se Tcombina (L) = a + b L + Tcombina (L - 1) Esta recorr ncia tem uma solucao quadr tica em L. Desta forma, com esta solucao, vir para e a a a funcao ordena Tmerge (L) = 2T (L/ 2) + a1 + b1 L + c1 L2 com solucao quadr tica (pelo teorema a principal). Importante E, no entanto, importante notar que n o e difcil encontrar uma funcao combina, com dea pend ncia linear em L1 + L2 (com inspiracao na vers o C desta funcao). e a Nesse caso para a funcao ordena ter-se- Tmerge (L) 2Tmerge (L/ 2) + a + b L, com solucao em a Tmerge = Q(lL.L log2 (L)) (tamb m pelo teorema principal). e A funcao combina alternativa apresenta-se de seguida. Na nova vers o utiliza-se uma funcao a recursiva combinaaux que percorre as duas listas a combinar utilizando ndices de nicio e m para cada uma delas. Esta funcao altera colateralmente uma lista lr que, inicialmente, e preenchida a zeros, e que, no nal, conter o resultado da combinacao. a Em cada invocacao de combinaaux e preenchida uma posicao de lr. A posicao a preencher e dada pelo ultimo argumento (o), que e o ndice onde se coloca o valor agora determinado. O caso base da execucao de combinaaux corresponde a uma das duas listas originais ter sido totalmente processada faltando acrescentar os elementos da outra.

86

combina = Function[{l1, l2}, Module[{lr, combinaaux}, combinaaux = Function[{i1, w1, f1, i2, w2, f2, o}, If[i1 f1 && i2 f2, If[w1[[i1]] w2[[i2]], lr[[o]] = w1[[i1]]; combinaaux[i1 + 1, w1, f1, i2, w2, f2, o + 1], lr[[o]] = w2[[i2]]; combinaaux[i1, w1, f1, i2 + 1, w2, f2, o + 1]], lr = Join[Take[lr, o 1], Take[l1, {i1, f1}], Take[l2, {i2, f2}]]]]; lr = Table[0, {i, 1, Length[l1] + Length[l2]}]; combinaaux[1, l1, Length[l1], 1, l2, Length[l2], 1]; lr]]

Ilustre-se esta funcao:


combina[Table[i, {i, 1, 40}], Table[2i, {i, 1, 10}]] {1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}

E importante notar que, na funcao anterior, al m de se percorrerem as listas argumento por e interm dio de ndices, tamb m se percorre a lista resultado com um ndice o. Uma solucao ale e ternativa que seria comecar com lr= e executar em cada passo da recurs o Append do valor a conveniente levaria tamb m a uma solucao quadr tica (porque o comportamento assimpt tico e a o desta operacao Append e linear no comprimento da lista resultado). Na gura seguinte encontra-se o gr co dos tempos de processamento da combinacao de duas a listas iguais (o que corresponde ao pior caso), de comprimentos em absissas.
10 8 6 4 2 5000 10000 15000

87

5.9 Programacao Funcional


As funcoes pr -denidas em Mathematica e outras denidas utilizando programacao funcional e (destacando-se pela sua utilidade os operadores Map e Apply) t m comportamentos muito e superiores aos das funcoes at agora apresentadas, em termos de eci ncia. e e Embora o comportamento assimpt tico da determinacao do m ximo, ou mnimo ou da pesquio a sa em listas n o ordenadas seja necess riamente linear, as funcoes pr -denidas (Max, Min, a a e MemberQ) ou outras denidas usando este paradigma, s o muito mais ecientes. Ilustramos a este facto com o algoritmo de pesquisa.

Pesquisa funcional
Uma vers o funcional da pesquisa em listas e a funcao seguinte, onde, numa primeira fase se a constr i a lista Map[Function[y, y == x], la] que, em cada posicao tem ou True o ou False consoante o elemento da lista argumento la, na mesma posicao, e igual ou n o ao a valor de x. O resultado e a disjuncao (Or) destes valores l gicos. o
pesquisaF = Function[la, x, Apply[Or, Map[Function[y, y == x], la]]]

O comportamento assimpt tico desta funcao e linear no comprimento da lista original pois o inclui a construcao da lista Map[Function[y, y == x], la]. Tamb m a determinacao e da disjuncao destes valores e, no pior caso de serem todos False, linear. Veremos, de seguida, como o tempo de execucao desta funcao compara com o tempo de execucao das vers es imperativa e recursiva seguintes: o
pesquisaI = Function[{la, x}, Module[{r, i}, r = False; i = 0; While[i < Length[la] && !r, r = (la[[i + 1]] == x); i = i + 1]; r]] pesquisaR = Function[{l, x}, Module[{auxpesquisa}, auxpesquisa = Function[{inicio, l, fim}, If[inicio == fim + 1, False, Or[l[[inicio]] == x, auxpesquisa[inicio + 1, l, fim]]]]; auxpesquisa[1, l, Length[l]]]]

No gr co seguinte apresentam-se os tempos de execucao destas tr s funcoes, no pior caso, a e para listas de comprimento at 20.000: e

88

1.75 1.5 1.25 1 0.75 0.5 0.25 5000 10000 15000

Os losangos correspondem a vers o recursiva, as estrelas a imperativa e os quadrados corres` a ` pondem a vers o funcional da pesquisa. ` a No gr co seguinte incluiu-se tamb m os tempos de execucao da funcao pr -denida Mema e e berQ:
1.75 1.5 1.25 1 0.75 0.5 0.25 5000 10000 15000

5.10 Eci ncia em C e


No caso do C as consideracoes de eci ncia s o, em geral, semelhantes as apresentadas para o e a ` Mathematica, sendo as operacoes sobre tipos de dados elementares (inteiros, reais, aponta dores) de duracao independente do valor dos argumentos. Quanto as operacoes sobre vectores ` h que ter em consideracao que o acesso aos elementos e directo. Para as listas ligadas h que a a notar que, embora o tempo necess rio a atribuicao din mica de mem ria seja proporcional a a ` a o ` mem ria pedida, nas aplicacoes que vimos e, em geral, solicita-se de cada vez uma quantidade o xa de mem ria pelo que o tempo que lhe corresponde deve ser considerado constante. o

89

You might also like