Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a...

8
Aula 5 Análise de Complexidade do QuickSort Quick Sort O QuickSort é um algoritmo muito eficiente que se deve a Hoare. O algoritmo é recursivo e baseia- se num método de partição. public static void swap(int vec[],int a,int b) {//troca elem da posição a com posição b - O(1) int tmp = vec[a]; vec[a] = vec[b]; vec[b] = tmp; } public static int partition(int vec[], int left, int right) { 1 int i=left, j=left + 1; 2 while(j<=right) { 3 if (vec[j]<=vec[left]){ 4 i++; 5 swap(vec,i,j);} 6 j++;} 7 swap(vec,left, i); 8 return i; } public static void quickSort(int vec[], int left, int right) { //sobreposição em Java int r; if (right > left) { r = partition(vec,left,right); quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); } } public static void quickSort(int vec[]) { quickSort(vec, 0, vec.length-1); } Comecemos por examinar o método de partição.

Transcript of Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a...

Page 1: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

Aula 5Análise de Complexidade do QuickSort

Quick Sort

O QuickSort é um algoritmo muito eficiente que se deve a Hoare. O algoritmo é recursivo e baseia-se num método de partição.

public static void swap(int vec[],int a,int b) {//troca elem da posição a com posição b - O(1) int tmp = vec[a]; vec[a] = vec[b]; vec[b] = tmp;}

public static int partition(int vec[], int left, int right) {1 int i=left, j=left + 1; 2 while(j<=right) { 3 if (vec[j]<=vec[left]){ 4 i++; 5 swap(vec,i,j);} 6 j++;} 7 swap(vec,left, i); 8 return i; }

public static void quickSort(int vec[], int left, int right) { //sobreposição em Java int r; if (right > left) { r = partition(vec,left,right); quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); }}

public static void quickSort(int vec[]) { quickSort(vec, 0, vec.length-1);}

Comecemos por examinar o método de partição.

Page 2: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

PC 6V= 6 5 3 1 8 7 2 4i=3 j=4

O método particiona o vetor em duas partes, a parte com elementos menores ou iguais ao pivot (vec[left]) e a parte como elementos superiores. A nova posição do pivot é o valor retornado pela função. Esta posição é depois usada para continuar a ordenar o vector.

Assim facilmente se obtém o Quicksort:

2 Lecture5AMC2020.nb

Page 3: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

PC 1V= 1 2 3 4 5 6 8 7i=6 j=7RecSt= {{0, 7}, {6, 7}}

A demonstração da correção do QuickSort é feita por indução, assumindo a correção do partition.

Teo: O Algoritmo QuickSort ordena o vetor por ordem crescente.

Prova: Prova por indução completa

Base Vec tem comprimento 0 ou 1, done!HI Quicksort ordena qq vec de tamanho <nTese QuickSort ordena corretamente um vetor de dimensão n?

Assumindo que partition está correto, logo após o if o vec tem todos elementos menores (ou iguais) que vec[i] de vec[0] a vec[r-1] e todos os maiores que vec[i] de vec[ r+1] até vec[n-1], por HI, o Quicksort ordena bem todos os tamanho <n, logo vai ordenar bem de 0 a r-1 e de r+1 até n-1, pois estes vetores têm tamanho < que n.Done!

Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos.

Def. Uma função f(n)∈Θ(g(n)) se f(n)∈O(g(n)) e g(n)∈O(f(n))

Exemplo: seja p(n) um polinómio positivo de grau k, entãop(n) ∈ Θnk.

As árvores de recursão permitem visualizar o número de chamadas recursivas e o custo em cada chamada.

Considere a por exemplo a recursão T (n) = 2 T(n /2) + n2

Lecture5AMC2020.nb 3

Page 4: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos.

Def. Uma função f(n)∈Θ(g(n)) se f(n)∈O(g(n)) e g(n)∈O(f(n))

Exemplo: seja p(n) um polinómio positivo de grau k, entãop(n) ∈ Θnk.

As árvores de recursão permitem visualizar o número de chamadas recursivas e o custo em cada chamada.

Considere a por exemplo a recursão T (n) = 2 T(n /2) + n2

Da análise da árvore concluímos que

T(n)=∑i=0log(n)n2 2i

somaSum[r^i, {i, 1, t}]

r -1 + rt

-1 + r

somaSum[n^2 / 2^i, {i, 0,

logaritmoLog[2, n]}]

expande fatoresExpand[%]

-n + 2 n2

Considere agora T(n) = T(n /3) + T(2 n /3) + n

T(n)=n∑i=1log3/2(n)O(1)

Teorema Mestre Sejam a≥1 e b>1 constantes, f(n) uma função e T(n) definida sobre os números naturais tal que

T(n) =a T(n/b)+f(n)

onde n/b pode ser ⌊n/b⌋ ou ⌈n/b⌉. Então T(n) ∈ Θnlogb a log(n) desde que f(n) ∈ Θnlogb a .

Prova. (Esquiço)

4 Lecture5AMC2020.nb

Page 5: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

Teorema Mestre Sejam a≥1 e b>1 constantes, f(n) uma função e T(n) definida sobre os números naturais tal que

T(n) =a T(n/b)+f(n)

onde n/b pode ser ⌊n/b⌋ ou ⌈n/b⌉. Então T(n) ∈ Θnlogb a log(n) desde que f(n) ∈ Θnlogb a .

Prova. (Esquiço)

Θnlogb a + ∑j=0logb(n)-1 aj Θn bjlogb a =

= Θnlogb a + ∑j=0logb(n)-1 aj Θn bjlogb a

= Θnlogb a + ∑j=0logb(n)-1 Θnlogb a aj aj

= Θnlogb a logb(n)

public static void quickSort(int vec[], int left, int right) { int r; if (right > left) { r = partition(vec,left,right); quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); }}

Análise no melhor caso

O partition(vec,lef,right) é sempre balançado, logo

T(n)=2T(n/2)+Θ(n)

Pelo Teorema Mestre (com a=b=2)

T(n) ∈ Θ(n log(n))

Análise no pior caso

O partition(vec,lef,right) é completamente enviesado, logo

T (n) = T (n - 1) + Θ(n) = ∑k=1n Θ(k)= Θ(∑k=1

n k) = Θn2).

Lecture5AMC2020.nb 5

Page 6: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

O partition(vec,lef,right) é completamente enviesado, logo

T (n) = T (n - 1) + Θ(n) = ∑k=1n Θ(k)= Θ(∑k=1

n k) = Θn2).

Análise no caso médio

T (n) = T(n - 1 - i) + T(i) +k n e assumindo que i é equiprovável de 0 a n-1 temos T (n) = 1

n∑i=0n-1T(n - 1 - i) + T(i) + k n = 2

n∑i=0n-1T(i) + k n

ou seja n T(n) =2∑i=0

n-1T(i) +k n2 (a)

também temos (n-1)T(n-1)=2∑i=0

n-2T(i) +k (n - 1)2 (b)

Subtraindo (b) a (a) n T(n)-(n-1)T(n-1)=2 T(n-1) +k n2 - k(n - 1)2=2 T(n-1)+ 2 k n - k nT(n)=(n+1) T(n-1)+2 k n -k dividindo ambos os lados por n*(n+1) T(n)/(n+1)=T(n-1)/n + 2k/(n+1)-k/(n(n+1)) g(n)=T(n)/(n+1) g(0)=T(0) g (n) = g (n - 1) + 2 k / (n + 1) - k/(n(n+1)) g(n)=T(0)+2k∑j=1

n+11/j -k∑j=1n 1/(j(j+1))

Note que: ∫1

n+1 1x

dx ≤ ∑j=1n+1 1

j≤ 1 + ∫2

n+1 1x-1

dx logo ∑j=1n+1 1

j∈ Θ(log(n))

∫1

n 1x(x+1)

dx ≤ ∑j=1n 1

j j+1≤ 1 /2 + ∫2

n+1 1x(x-1)

dx logo ∑j=1n+1 1

j j+1∈ Θ(1)

6 Lecture5AMC2020.nb

Page 7: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

In[20]:=gráficoPlot[{1 / (x (x + 1)), 1 / (

inteiro infe⋯Floor[x]

inteiro inferiorFloor[x + 1]), 1 / (x (x - 1))}, {x, 1, 5}]

Out[20]=

2 3 4 5

0.2

0.4

0.6

0.8

1.0

In[1]:=gráficoPlot[{1 / x, 1 /

inteiro inferiorFloor[x], 1 / (x - 1)}, {x, 1, 10}]

Out[1]=

2 4 6 8 10

0.2

0.4

0.6

0.8

1.0

In[14]:= 1

n+1 1

x (x + 1)ⅆx

Out[14]= ConditionalExpression[Log[2] + Log[1 + n] - Log[2 + n], Re[n] > -1 || n ∉ ℝ]

In[19]:=limiteLimit[

logaritmoLog[2] +

logaritmoLog[1 + n] -

logaritmoLog[2 + n], n →

infinitoInfinity]

Out[19]= Log[2]

In[15]:= 2

n+1 1

x(x - 1)ⅆx

Out[15]= ConditionalExpressionLog2 n

1 + n, Re[n] > 1 && Im[n] ⩵ 0

2

n+1 1

x - 1ⅆx

ConditionalExpression[Log[n], Re[n] > 0 || n ∉ Reals]

1

n+1 1

xⅆx

ConditionalExpression[Log[1 + n], Re[n] > -1 || n ∉ Reals]

Concluímos queg(n)=T (n)/(n + 1) = Θ (log (n)) e logoT (n) = Θ (n log (n))

Lecture5AMC2020.nb 7

Page 8: Aula 5 Análise de Complexidade do QuickSort · Vamos agora estudar as ferramentas para analisar a complexidade de algoritmos recursivos. Def. Uma função f(n)∈Θ(g(n)) se f(n)

Concluímos queg(n)=T (n)/(n + 1) = Θ (log (n)) e logoT (n) = Θ (n log (n))

8 Lecture5AMC2020.nb