• Nenhum resultado encontrado

Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

N/A
N/A
Protected

Academic year: 2021

Share "Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio"

Copied!
33
0
0

Texto

(1)

Programação II

Ordenação

(sort)

Bruno Feijó

(2)

Quick Sort

(3)

Algoritmo Quick Sort (recursivo)

O algoritmo de Quick Sort foi desenvolvido por Sir Charles Hoare (Tony Hoare), em 1960, aos 26 anos. Suponha que você sabe colocar um dos elementos x do vetor (por exemplo, o primeiro) numa posição tal que todos os elementos antes são menores ou iguais a x e todos os elementos depois dele são maiores (note que, nesta tarefa, não importa se alguns elementos trocam de posição):

n elementos

5

4 3 7 1 2 6 9 1 4 3

5

7 6 9

x

x

≤ x >x ≤ 5 >5 2

Vamos denominar o elemento x escolhido de pivô e chamar esta etapa da ordenação de PARTIÇÃO. Neste caso, se você souber ordenar o subvetor esquerdo e o subvetor direito, você terá o vetor inicial completamente ordenado! Isto nos leva a definir uma função recursiva quicksort na qual o caso-base é um vetor com 1 ou nenhum elemento (e, neste caso, nada é preciso fazer) e o caso geral é fazer a partição seguida da chamada da função para o subvetor esquerdo e da chamada da função para o subvetor direito:

quicksort do vetor

se n>1 então

PARTIÇÃO com pivô x

quicksort do subvetor à esquerda de x quicksort do subvetor à direita de x

No próximo slide estão sugeridos um processo simples e direto para a PARTIÇÃO e uma maneira de se referenciar aos subvetores à esquerda e à direita de x.

(4)

Algoritmo Quick Sort (recursivo)

25 48 37 12 57 86 33 92 a b a b troca e incr/decr 12 48 a

b não troca nem in/decr

a b troca pivô 12 25 37 48 57 86 33 92 12 25 37 57 86 33 92

x

a b a b a b b

...

a

v

a

> x

v

b

≤ x

se a < b, troca e incrementa

se b < a, troca pivô x com

v

b

v

b

x

v

a

região dos ≤ x região dos > x

posição correta de x subvetor subvetor 0 a b n - a

repete processo para cada subvetor

caminham até que decr b se vb> x incr a se va≤ x b b b

quicksort(n,v)

se n <= 1 então retorna

x = v

0

a = 1 b = n-1

faça

enquanto a < n e v

a

x

a = a + 1

enquanto v

b

> x

b = b - 1

se a < b então troca v

a

com v

b

e a= a+1 e b= b-1

enquanto a ≤ b

troca pivô x com v

b

quicksort(b, subvetor esquerdo)

quicksort(n-a, subvetor direito)

Para a PARTIÇÃO, podemos ir caminhando com os índices do vetor:

fica repetindo até que

(5)

Código Quick Sort

25 48 37 12 57 86 33 92 a b a b 12 48 a b a b 12 25 37 48 57 86 33 92 12 25 37 57 86 33 92 quicksort(n,v) se n <= 1 então retorna x = v0 a = 1 b = n-1 faça enquanto a < n e va≤x a = a + 1 enquanto vb> x b = b - 1

se a < b então troca vacom vb e a= a+1 e b= b-1 enquanto a ≤ b

troca pivô x com vb

quicksort(b, subvetor esquerdo) quicksort(n-a, subvetor direito)

void quicksort(int n, int * v) { int x = v[0]; int temp; int a = 1; int b = n-1; if (n<=1) return; do {

while (a < n && v[a] <= x) a++; while (v[b] > x) b--; if (a < b) { temp = v[a]; v[a] = v[b]; v[b] = temp; a++; b--; } } while (a <= b); v[0] = v[b]; v[b] = x; quicksort(b,v); quicksort(n-a,&v[a]); }

Pa

rt

içã

o

(6)

Generalizando o Algoritmo Quick Sort

O desenvolvimento apresentado nos slides anteriores refere-se à ordenação em ordem CRESCENTE de um vetor de INTEIROS. Uma primeira generalização é perceber que a partição divide o vetor em

elementos que atendem o critério de ordenação à direita do pivô e elementos que NÃO atendem à esquerda. Por exemplo, a ilustração da partição para uma ordem DECRESCENTE seria:

5

4 3 7 1 2 6 9 7 9 6

5

2 3 4

≥ 5 <5 1

O critério de ordenação pode ser definido numa função auxiliar de comparação que é usada em dois momentos no algoritmo de quick sort, sendo um momento a negação do outro (operador !):

static int cmpInt(int a, int b) {

return a < b; }

void quicksort(int n, int * v) { int x = v[0]; int temp; int a = 1; int b = n-1; if (n<=1) return; do {

while (a < n && !cmpInt(v[a],x)) a++; while (cmpInt(v[b],x)) b--; if (a < b) { temp = v[a]; v[a] = v[b]; v[b] = temp; a++; b--; } } while (a <= b); v[0] = v[b]; v[b] = x; quicksort(b,v); quicksort(n-a,&v[a]); }

(7)

Exercícios

struct dados { int idade; int peso; };

typedef struct dados Dados;

[1] Escreva programa completo que ordena um vetor de ponteiros para

estrutura Dados através do Quick Sort (e usando função de comparação), de acordo

o seguinte critério: primeiro em ordem crescente da idade e depois em ordem

crescente do peso.

Sugestão para teste:

Dados tab[] = {{20,50},{10,30},{25,40},{18,65},{10,40},{18,60}}; Dados * v[] = {tab,tab+1,tab+2,tab+3,tab+4,tab+5};

(8)
(9)

Ponteiros para Funções

Em C é possível definir ponteiros para funções que podem ser colocados em

vetores, passados para funções e retornados por funções

No exemplo a seguir, a função opera(m, x, y, func) recebe um ponteiro de função

como um de seus argumentos (func) e retorna m

×

func(x,y). Devemos notar que o

nome da função mult é um ponteiro quando escrevemos opera(2,3,5,mult);

#include <stdio.h>

int mult(int x,int y);

int soma(int x, int y);

int opera(int m, int x, int y, int(*func)(int, int));

int main(void) { int a, b; a = opera(2,3,5,mult); b = opera(2,3,5,soma); printf("%d %d\n",a,b); return 0; }

int mult(int x,int y) {

return x*y; }

int soma(int x, int y) {

return x+y; }

int opera(int m,int x,int y,int(*func)(int, int)) {

return m*func(x,y); }

Saída:

30 16

Se argumentos são ponteiros, usamos const quando queremos garantir que a função func não modificará os valores que são apontados: int(*func)(const int *, const int *))

(10)

Quick Sort da stdlib do C

void qsort(void * v, int n, int tam, int (*cmp)(const void *, const void *)); v: vetor de ponteiros genéricos

n: número de elementos do vetor

tam: tamanho em bytes de cada elemento (use sizeof para especificar) cmp: ponteiro para função que compara elementos genéricos

int nome(const void * a, const void * b);

deve retornar <0 se a<b, >0 se a>b e 0 se a == b

const é para garantir que a função não modificará os valores dos elementos

static int compFloat(const void * a, const void * b) {

/* converte os ponteiros genericos */

float * aa = (float *)a; float * bb = (float *)b;

/* faz a comparacao com (*aa) e (*bb) retornando -1,0, ou 1 */ if (*aa > *bb) // atenção para o *

return 1; else if (*aa < *bb) return -1; else return 0; }

(11)

Exemplo Quick Sort da stdlib

#include <stdlib.h>

int main(void) {

...

Pessoa tab[] = {{"Diana Maria",22}, ...}; Pessoa * v[] = {tab,tab+1, ...};

...

QsortPessoa(n,tabPessoa); // ordenacao com Quick Sort

... }

int compPessoa(const void * a, const void * b) {

Pessoa ** aa = (Pessoa **)a; Pessoa ** bb = (Pessoa **)b; int cmp = strcmp((*aa)->nome,(*bb)->nome); if (cmp>0 || (cmp==0 && ((*aa)->idade>(*bb)->idade))) return 1; else if (cmp<0 || (cmp==0 && ((*aa)->idade<(*bb)->idade))) return -1; else return 0; }

void QsortPessoa(int n, Pessoa ** v) {

qsort(v,n,sizeof(Pessoa *),compPessoa); }

(12)
(13)
(14)

Bubble Sort – Ordem Crescente

Apenas de interesse didático e de referência

A idéia é ir comparando dois vizinhos e trocando o menor pelo maior até

que o maior de todos fica no final (como se o maior fosse uma “bolha”

que sobe até o topo)

0 1 1 2 j j+1

...

...

0 1 j j+1

...

passo 1

passo 2

passo 3

...

1 2

...

(15)

Exemplo Bubble Sort – Passo 1 e Passo 2

25 48

37 12 57 86 33 92

25x48

25

48 37

12 57 86 33 92

48x37 troca

25 37

48 12

57 86 33 92

48x12 troca

25 37 12

48 57

86 33 92

48x57

25 37 12 48

57 86

33 92

57x86

25 37 12 48 57

86 33

92

86x33 troca

25 37 12 48 57 33

86 92

86x92

25 37 12 48 57 33 86

92

final do passo 1

o maior elemento, 92, já está na sua posição final

25 37

12 48 57 33 86

92

25x37

25

37 12

48 57 33 86

92

37x12 troca

25 12

37 48

57 33 86

92

37x48

25 12 37

48 57

33 86

92

48x57

25 12 37 48

57 33

86

92

57x33 troca

25 12 37 48 33

57 86

92

57x86

25 12 37 48 33 57

86 92

final do passo 2

o segundo maior elemento, 86, já está na sua posição final

n = 8 elementos

n 1 c om p ar aç õe s ( i. e . 7 ) n 2 c om p ar aç õe s ( i. e . 6 )

(16)

Bubble Sort – Passo 3 e Passo 4

25 12

37 48 33 57

86 92

25x12 troca

12

25 37

48 33 57

86 92

25x37

12 25

37 48

33 57

86 92

37x48

12 25 37

48 33

57

86 92

48x33 troca

12 25 37 33

48 57

86 92

48x57

12 25 37 33 48

57 86 92

final passo 3

Idem para 57.

12 25 37 33 48 57 86 92

12x25

12 25 37 33 48 57 86 92

25x37

12 25 37 33 48 57 86 92

37x33 troca

12 25 33 37 48 57 86 92

37x48

12 25 33 37 48 57 86 92

final do passo 4

Idem para 48.

Não irá trocar mais.

Veja isto no próximo passo

n 3 (= 5 ) n 4 (= 4 )

(17)

Bubble Sort – Passos 5, 6 e 7

12 25 33 37 48 57 86 92

12x25

12 25 33 37 48 57 86 92

25x33

12 25 33 37 48 57 86 92

33x37

12 25 33 37 48 57 86 92

final do passo 5

Idem para 37.

12 25

33

37 48 57 86 92

12x25

12

25 33

37 48 57 86 92

25x33

12 25

33 37 48 57 86 92

final do passo 6

Idem para 33.

12 25

33 37 48 57 86 92

12x25

12

25 33 37 48 57 86 92

final do passo 7

Idem para 25 e, conseqüentemente, 12.

12 25 33 37 48 57 86 92

final da ordenação

Passo 5 sem troca!

Os dois próximos

passos são

desperdícios!

n 5 (= 3 ) n 6 (= 2 ) n 7 (= 1 )

(18)

Algoritmo de Bubble Sort – Solução Conceitual

bolhaInt(vetor v de inteiros, n) i = n-1

para cada i, enquanto i>0

haTroca= 0 // p/rastrear trocas j = 0

para cada j, enquanto j<i

se compInt(vj,vj+1) é VERDADE troca vj e vj+1

haTroca= 1; // marca troca incrementa j de 1

if haTroca é zero retorna

decrementa i de 1

DICAS PARA A IMPLEMENTAÇÃO: - Use for para os loops.

- Para trocar vj e vj+1use uma variável auxiliar. - A função de comparação deve retornar VERDADE (valor diferente de zero) ou FALSO (zero).

- Os argumentos desta função são do mesmo tipo do vetor.

- Geralmente definimos esta função como sendo static. Função static é invisível fora do arquivo no qual é declarada.

- Este algoritmo é geral. Só muda o que está em

vermelho e itálico.

O critério de ordenação é definido dentro

desta função comp

Int

que compara dois

elementos do vetor (no caso, 2 inteiros).

Ordem Crescente:

static int compInt(int a, int b) {

return a > b; }

Ordem Decrescente:

static int compInt(int a, int b) {

return a < b; }

(19)

Código bolhaInt – Ordem Crescente

void bolhaInt(int * v, int n) { int i,j,haTroca; int temp; for (i=n-1;i>0;i--) { haTroca= 0; for (j=0;j<i;j++) { if (compInt(v[j],v[j+1])) { temp = v[j]; v[j] = v[j+1]; v[j+1] = temp; haTroca= 1; } } if (haTroca==0) return; } } bolhaInt(vetor v de inteiros, n)

i = n-1

para cada i, enquanto i>0 haTroca= 0

j = 0

para cada j, enquanto j<i

se compInt(vj,vj+1) é VERDADE troca vj e vj+1

haTroca= 1; // marca troca incrementa j de 1

if haTroca é zero retorna

decrementa i de 1

static int compInt(int a, int b) {

return a > b; }

Para outros tipos, só muda o que está em vermelho e itálico

troca

Depois faça para vetor de strings (bolhaStr), ordem crescente. Resposta no próximo slide!

(20)

Código bolhaStr – Ordem Crescente

void bolhaStr(char ** v, int n) { int i,j,haTroca; char * temp; for (i=n-1;i>0;i--) { haTroca= 0; for (j=0;j<i;j++) { if (compStr(v[j],v[j+1])) { temp = v[j]; v[j] = v[j+1]; v[j+1] = temp; haTroca= 1; } } if (haTroca==0) return; } } int main(void) { char * v[] = {"daniel","ana",...,}; ... bolhaStr(tab, N); ...

static int compStr(char * a, char * b) {

return (strcmp(a,b) > 0); }

troca

strcmp(x,y) é uma função da biblioteca de strings que retorna o seguinte:

< 0 se o primeiro caractere que não casa tem um valor mais baixo em x do que em y

0 se os conteúdos dos dois strings são iguais >0 se o primeiro caractere que não casa tem um

valor mais alto em x do que em y

Por ex.: strcmp("daniel","ana") retorna > 0

strcmp("Ana","ana") retorna < 0 (porque 'A' é menor que 'a' na tabela ASCII

(21)

Exercícios

typedef struct pessoa Pessoa; struct pessoa

{

char * nome; int idade; };

[1] Escreva programa completo, em módulos, que ordena um vetor de ponteiros para

estrutura Pessoa:

usando o seguinte critério: ordem crescente de nome e ordem crescente de idade

(note que há 3 Diana Maria de idades diferentes).

Obs1: evite ninhos de if e use expressões booleanas (com ||, && e !). Obs2: para montar o vetor, declare e inicialize vetores:

Pessoa tab[] = {{"Diana Maria",22}, ...}; Pessoa * v[] = {tab,tab+1, ...};

Obs3: faça uma função auxiliar imprimeVetPessoa que imprime o vetor

Diana Maria 22 Beatrice Dante 30 Ada Eva 30 Diana Maria 26 Beatrice Dante 29 Helena Troia 25 Diana Maria 20 Beatrice Dante 25

(22)

Código bolhaPessoa

void bolhaPessoa(Pessoa ** v, int n) { int i,j,haTroca; Pessoa * temp; for (i=n-1;i>0;i--) { haTroca= 0; for (j=0;j<i;j++) { if (compPessoa(v[j],v[j+1])) { temp = v[j]; v[j] = v[j+1]; v[j+1] = temp; haTroca= 1; } } if (haTroca==0) return; } } struct pessoa { char * nome; int idade; };

typedef struct pessoa Pessoa;

static int compPessoa(Pessoa * a, Pessoa * b) {

int cmp = strcmp(a->nome,b->nome);

return (cmp > 0 || (cmp==0 && (a->idade)>(b->idade))); } int main(void) { ... bolhaPessoa(v, N); ... trocaC

(23)

Algoritmo Genérico

void bolhaGen(void * v, int n, int tam, int(*comp)(const void *, const void *)) { int i,j,haTroca; void * p1; void * p2; for (i=n-1;i>0;i--) { haTroca= 0; for (j=0;j<i;j++) { p1 = acessa(v,j,tam); p2 = acessa(v,j+1,tam); if (comp(p1,p2)) troca(p1,p2,tam); haTroca= 1; } if (haTroca==0) return; } }

static void * acessa(void * v,int i,int tam) {

char * t = (char *)v; // char = 1 byte

t += tam*i;

return (void *)t; }

static void troca(void * a, void * b, int tam) {

char temp;

char * v1 = (char *)a; // troca byte a byte

char * v2 = (char *)b;

int i;

for (i=0; i<tam; i++) { temp = v1[i]; v1[i] = v2[i]; v2[i] = temp; } }

static int compPessoaGen(const void * a, const void * b) {

Pessoa ** aa = (Pessoa **)a; Pessoa ** bb = (Pessoa **)b;

int cmp = strcmp((*aa)->nome,(*bb)->nome);

return (cmp>0 || (cmp==0 && (*aa)->idade > (*bb)->idade)); }

void ordenaPessoa(int n, Pessoa ** v) {

bolhaGen(v,n,sizeof(Pessoa *),compPessoa); }

(24)

Selection Sort

(25)

Conceito do Selection Sort – Ordem Crescente

- Supomos que o maior elemento (max) é o que está na posição 0

- A partir da posição 1, procuramos se há alguém maior (max) do que o valor na posição 0

- trocamos este máximo pelo último

- Deslocamos o fim do vetor para 1 (uma) posição à esquerda

- Repetimos o processo

Note que o processo vai dividindo o vetor em uma parte ordenada e outra não

ordenada. fim fim fim fim fim Um processo equivalente

é trabalhar com o mínimo e trocar com o primeiro. Neste caso, o vetor ordenado vai se

(26)

Selection Sort

void selectionInt(int * v, int n) {

int fim, iMax, i;

int temp;

for (fim = n-1; fim > 0; fim--) {

iMax= 0; /* indice do maior*/ for (i=1;i<=fim;i++) if ( v[i]> v[iMax] ) iMax = i; temp = v[fim]; v[fim] = v[iMax]; v[iMax] = temp; } troca

critério if ( compInt(v[i], v[iMax]) )

static int compInt(int a, int b) {

return a > b; }

Ou usando uma função

para um critério genérico

Implemente a versão que trabalha com o mínimo!

(27)

Complexidade

(28)

Complexidade de Tempo

O tempo gasto por um algoritmo é função do tamanho n da entrada de dados e

depende do número de operações que cada passo do algoritmo executa.

T(n) indica a dimensão este tempo de uma forma geral (e independente de hardware)

No caso do algoritmo Bubble, numa análise aproximada, o passo 1 faz n-1

comparações, o passo 2 faz n-2 comparações, ... . De maneira aproximada, temos:

Isto é igual à soma de uma série aritmética de m termos, onde m = n-1:

Para grandes valores de n (n

→ ∞), esta função é limitada pela função

bn

2

, onde b é

uma constante, i.e.:

Como regra geral, o termo de mais alta ordem de uma função domina sua taxa de

crescimento (i.e., na prática, suprimimos constantes multiplicativas e termos de

baixa ordem para descrever o comportamento limite de uma função)

Dizemos, então, que o algoritmo Bubble tem uma complexidade de tempo quadrática

e usamos a notação do Big O para indicar este limite superior:

O(n

2

)

1

2

)

2

(

)

1

(

)

(

n

=

n

+

n

+

+

+

T

(n-1) + (n-2) + ... + 2 + 1 Série Aritmética Sm = m(a1 + am)/2

am a1 m = n-1 Sm = n(n-1)/2

n

n

n

n

n

T

2

1

2

1

2

/

)

1

(

)

(

=

=

2

2 2

2

1

2

1

)

(

n

n

n

bn

T

=

(29)

Complexidades Comuns (notação Big O)

Notação Big O

O(1)

Tempo constante

O(log n)

Tempo logarítmico

O(n)

Tempo linear

O(n log n)

Tempo loglinear (ou quaselinear)

O(n

2

)

Tempo quadrático

Limite

n

2

n

n

n

T

2

1

2

1

)

(

=

2

Quase linear

n

(30)

Diferença entre n e log n

36 seg

100 anos

94 608 000 000

30

1 ano

946 080 000

21

1 mês

2 592 000

16

1 dia

86 400

12

1 h

3 600

9

10 min

600

6

1 min

60

3 seg

10 seg

10

O(log n)

O(n)

tamanho

(31)

Outras Considerações sobre Complexidade

Na análise de complexidade, procuramos o “Pior Caso”, o “Melhor Caso” e o

“Caso Médio”

Bubble Sort tem o “Melhor Caso” quando a lista já está ordenada. Neste caso, a complexidade de tempo é

O(n)

O “Caso Médio” para Bublle Sort também é

O(n

2

)

Entre algoritmos de mesma complexidade, há diferenças em eficiência

Por exemplo, Selection Sort é similar ao Bubble Sort e ambos tem

O(n

2

)

, isto é: ele faz o

mesmo número de comparações que o Bubble. Entretanto, Selection Sort tem um menor número de comparações e tende a ser aproximadamente 2 vezes mais eficiente. Eficiência não é a mesma coisa que complexidade!

Em geral

uma única operação (ou comando) tem um tempo de execução de

O

(1) – Um loop (laço) que é repetido n vezes tem

O(n)

Dois laços aninhados (nested loops) indo de 1 a

n

tem

O(n

2

)

Se um algoritmo tem vários passos de complexidades diferentes, a complexidade

do algoritmo como um todo é dado pelo máximo.

(32)

Complexidade do Quick Sort – Pior Caso

Esta etapa (que caminha pelo vetor, compara e troca valores) consome um tempo cn (*). As outras duas etapas são as chamadas recursivas. Temos, então:

(*)

o maior valor de cseria para um código que percorresse uma vez o vetor, guardando os elementos menores do que x (e o próprio x) em um vetor temporário, percorresse novamente o vetor, guardando os elementos maiores do que x, e

finalmente copiasse o vetor temporário para o vetor original. Neste caso, o tempo seria 4n(i.e.c= 4).

A primeira etapa do algortimo de sort é colocar o pivô

x

na posição que divide o vetor entre os elementos menores que

x

e os maiores que

x

:

x

k

n-k

cn

k

n

T

k

T

n

T

(

)

=

(

)

+

(

)

+

PIOR CASO: pivô

x

é o menor, em cada passo. Neste caso, k =1 e n-k = n-1 passo 1:

T

(

n

)

=

T

(

1

)

+

T

(

n

1

)

+

cn

passo 2:

T

(

n

)

=

T

(

1

)

+

[

T

(

1

)

+

T

(

n

2

)

+

cn

]

+

cn

=

T

(

n

2

)

+

2

T

(

1

)

+

c

(

n

1

+

n

)

passo 3:

T

(

n

)

=

[

T

(

1

)

+

T

(

n

3

)

+

c

(

n

2

)]

+

2

T

(

1

)

+

c

(

n

1

+

n

)

=

T

(

n

3

)

+

3

T

(

1

)

+

c

(

n

2

+

n

1

+

n

)

passo

i

:

T

(

n

)

=

T

(

n

i

)

+

iT

(

1

)

+

c

(

n

i

+

1

+

+

n

1

+

n

)

...

e considerando que vamos até

n

i

=1

, i.e.

i

= n

1

, temos:

T

(

n

)

=

nT

(

1

)

+

c

(

n

1

)(

n

+

2

)

A soma da série aritmética de

i

termos

n

i+1,...,n

1,n

é:

S

i

=

i

(

2

n

+

1

i

)

/

2

A complexidade é, portanto:

T

(

n

)

=

nT

(

1

)

+

c

(

n

1

)(

n

+

2

)

dn

2

O

( )

n

2 O mesmo vale para pivô

x

sendo o maior.

(33)

Complexidade do Quick Sort – Melhor Caso

MELHOR CASO: pivô

x

divide vetor em duas partes iguais, em cada passo. Neste caso, k =n/2 e n-k = n/2 passo 1:

T

(

n

)

=

T

(

n

/

2

)

+

T

(

n

/

2

)

+

cn

=

2

T

(

n

/

2

)

+

cn

passo 2:

T

(

n

)

=

2

[

2

T

(

n

/

4

)

+

cn

/

2

]

+

cn

=

2

2

T

(

n

/

2

2

)

+

2

cn

passo 3:

T

(

n

)

=

2

2

[

2

T

(

n

/

2

3

)

+

cn

/

2

2

]

+

2

cn

=

2

3

T

(

n

/

2

3

)

+

3

cn

passo

i

:

T

(

n

)

=

2

i

T

(

n

/

2

i

)

+

icn

...

considerando que vamos até

n/2

i

= 1

, i.e.

n

= 2

i , ou seja,

i

= log n

, temos:

Podemos também provar que no CASO MÉDIO (para todas as possíveis configurações de pivô), quick sort tem uma complexidade de tempo de O(n log n).

(

n

n

)

O

n

dn

n

cn

nT

n

T

(

)

=

(

1

)

+

log

log

log

Melhoras no algoritmo podem ser feitas no sentido de reduzir a chance de ocorrer o pior caso. Uma idéia é pegar o pivô aleatóriamente cada vez. Outra idéia é encontrar a mediana do vetor

a ser ordenado cada vez, e usar a mediana como pivô (isto tem um custo extra alto de complexidade constante, mas que pode compensar ). Veja também o método baseado em 3 medianas.

Selection Sort pode ser mais vantajoso para listas pequenas (≤ 30) ou quase ordenadas.

Ironicamente, vetores já ordenados (ou quase ordenados) e com o pivô sendo o primeiro (ou o último) elemento representam situações tipo “pior caso”.

Referências

Documentos relacionados

Sirona Dental Systems GmbH 5 Instruções de cuidados e limpeza para a equipe do consultório Manual de instruções Monitor de 22 polegadas 5.1 Produto de conservação e limpeza. 5

1.1.12 Demonstração de que possui, o PROPONENTE, em seu quadro permanente de pessoal, na data da entrega das propostas, profissional(is) de nível superior, a

Os relatórios de risco são gerados diariamente e circulam por todos os profissionais da LGI responsáveis pelas estratégias, CIO, analistas e compliance, incluindo métricas de risco

Compreende noções de dentro/fora Compreende noções em cima/ em baixo Compreende noções de cheio/vazio Compreende noções de pequeno/grande Compreende noções de claro/escuro

A base da pirâmide, que representa o momento onde há um ambiente cooperativo entre os agentes, prevê aplicação de uma regulação em que as empresas podem ter voz, ajudando o Estado

“Uma vez realizada uma generalização, somente pode ser descrita como boa ou má, não como certa ou errada, uma vez que as alterações introduzidas na informação têm

O aborto não criminalizado constitui-se em um grande responsável pela mortalidade materna, pois se observa uma relação entre as taxas de abortamento e a morte materna.. Quando o

E se, no que toca à viticultura, a aposta nas castas autóctones da região, como a Azal, Avesso ou Lou- reiro seria inevitável, a Quinta da Lixa alberga já, nas suas