Vectores: Algortmos de Ordeação (2) Algortmos e Estruturas de Dados 2009/2010 Ordeação por Partção (Quck Sort) Algortmo (ordeação por partção): 1. Caso básco: Se o úmero () de elemetos do vector (a) a ordear for muto pequeo, usar outro algortmo (sertosort) 2. Passo de partção: 2.1. Escolher um elemeto arbtráro (x) do vector (chamado pvot) 2.2. Partr o vector cal em dos sub-vectores (esquerdo e dreto), com valores x o sub-vector esquerdo e valores x o sub-vector dreto (podedo exstr um 3º sub-vector cetral com valores =x) 3. Passo recursvo: Ordear os sub-vectores esquerdo e dreto, usado o mesmo método recursvamete Algortmo recursvo baseado a técca dvsão e coqusta AED - 2009/10 2 1
Exemplo do Passo de Partção x x=4 v: 8 9 2 5 4 6 1 3 7 8 9 2 5 4 6 1 3 7 3 9 2 5 4 6 1 8 7 3 1 2 5 4 6 9 8 7 3 1 2 5 4 6 9 8 7 < 3 1 2 4 5 6 9 8 7 AED - 2009/10 3 x Implemetação da Ordeação por Partção em C++ /* calcula a medaa etre os valores dos dces left, rght, e cetro (left+rght)/2 do vector a */ template <class Comparable> cost Comparable &meda3(vector<comparable> &a, t left, t rght) t ceter = (left+rght) /2; f (a[ceter] < a[left]) swap(a[left], a[ceter]); f (a[rght] < a[left]) swap(a[left], a[rght]); f (a[rght] < a[ceter]) swap(a[ceter], a[rght]); //coloca pvot a poscao rght-1 swap(a[ceter], a[rght-1]); retur a[rght-1]; AED - 2009/10 4 2
Implemetação da Ordeação por Partção em C++ /* Ordea vector(a) etre duas posções dcadas (left e rght). Supõe que os elemetos do vector são comparáves com "<" e copáves com "=". */ template <class Comparable> vod qucksort(vector<comparable> &a, t left, t rght) f (left-rght <= 10) sertosort(a,left,rght); else // calzações // se vector pequeo Comparable x = meda3(a,left,rght); t = left; t = rght-1; // passo de partção // x é o pvot // cotua... AED - 2009/10 5 Implemetação da Ordeação por Partção em C++ for(; ; ) whle (a[++] < x) ; whle (x < a[--]) ; f ( < ) swap(a[], a[]); else break; swap(a[], a[rght-1]); //repoe pvot // passo recursvo qucksort(a, left, -1); qucksort(a, +1, rght); AED - 2009/10 6 3
Programa de teste #clude <ostream.h> #clude <stdlb.h> // Para usar rad() // serr aqu a fução QuckSort vod mprme(cost t v[], t ) for (t = 0; < ; ++) cout << v[] << ' '; cout << '\'; ma() cost t SIZE = 100; t v[size]; for (t = 0; < SIZE; ++) v[] = rad(); mprme(v, SIZE); qucksort(v, 0, SIZE - 1); mprme(v, SIZE); retur 0; AED - 2009/10 7 Aálse da Ordeação por Partção Escolha pvot determa efcêca por caso: pvot é elemeto mas pequeo O(N 2 ) melhor caso: pvot é elemeto médo O(N logn) caso médo: pvot corta vector arbtraramete O(N logn) Escolha pvot má escolha: extremos do vector ( O(N 2 ) se vector ordeado ) aleatóro: evolve mas uma fução pesada recomedado: medaa de três elemetos (extremos do vector e poto médo) AED - 2009/10 8 4
Efcêca da Ordeação por Partção Por caso: cada rectâgulo refere-se a uma chamada recursva Melhor caso: -1 1 /2 /2-2 -3 1... 1 1+log 2 /4 /4... /4 /4 1 1 1 1 1 1 1 1 1 1 profuddade de recursão: tempo de execução total (somado totas de lhas): T() = O[++(-1) +... +2] = O[+(-1)( + 2)/2] = O( 2 ) profuddade de recursão: 1+log 2 (sem cotar com a possbldade de um elemeto ser excluído dos sub-arrays esquerdo e dreto) tempo de execução total (uma vez que a soma de cada lha é ): T() = O[(1+log 2 ) ] = O( log ) AED - 2009/10 9 Complexdade Espacal de QuckSort O espaço de memóra exgdo por cada chamada de qucksort, sem cotar com chamadas recursvas, é depedete do tamaho () do array O espaço de memóra total exgdo pela chamada de qucksort, cludo as chamadas recursvas, é pos proporcoal à profuddade de recursão Assm, a complexdade espacal de qucksort é: O(log ) o melhor caso (e o caso médo) O() o por caso Em cotrapartda, a complexdade espacal de sertosort é O(1) AED - 2009/10 10 5
BucketSort Ordeação lear usa formação adcoal sobre etrada Algortmo vector de etrada: teros postvos ferores a M a = [ A 1, A 2,, A N ] ; A < M calzar um vector de M posções a 0 s cout = [c 1, c 2,, c M ] ; c = 0 Ler vector etrada (a) e para cada valor cremetar a posção respectva o vector cout : cout[a]++ Produzr saída ledo o vector cout Efcêca tempo lear AED - 2009/10 11 Comparação de tempos médos de execução (observados) de dversos algortmos de ordeação Iserto sort Heap sort Merge sort Quck sort Cada poto correspode à ordeação de 100 arrays de teros gerados aleatoramete Fote: Sah, "Data Structures, Algorthms ad Applcatos C++" Método de ordeação por partção (qucksort) é a prátca o mas efcete, excepto para arrays pequeos (até cerca 20 elemetos), em que o método de ordeação por serção (sertosort) é melhor! AED - 2009/10 12 6