204
Algoritmos de Ordenação e Pesquisa Marco Antonio Moreira de Carvalho Algoritmos e Estrutura de Dados

Algoritmos de Ordenação e Pesquisa - DECOM … Ordenação e Pesquisa ! Os elementos são chamados de chaves; ! Pode haver chaves de valores idênticos; ! Os valores não necessariamente

Embed Size (px)

Citation preview

Algoritmos de Ordenação e Pesquisa

Marco Antonio Moreira de Carvalho Algoritmos e Estrutura de Dados

2

Bibliografia Básica

l  Cormen, Leiserson, Rivest. Introduction to Algorithms. 2nd edition. MIT Press, 2001. Capítulos 2, 6, 7, 8.

l  Aho, Alfred V., Hopcroft, John F., Ullman, Jeffrey D., Data Structure and Algorithms, Massachusetts: Addison-Wesley, 1987. Capítulo 8.

3

Ordenação e Pesquisa

l  Considerando um conjunto de dados: l  Organizá-los de acordo com algum critério (>, <, ≥, ≤,

etc.); ou l  Encontrar algum que atenda um critério específico

(maior, menor, =, etc.). l  Estas tarefas devem ser realizadas eficientemente

l  O tempo para executá-las depende da quantidade de dados envolvidos.

l  Aplicação direta: Organização e manipulação de dados.

4

Ordenação e Pesquisa

l  Os elementos são chamados de chaves; l  Pode haver chaves de valores idênticos; l  Os valores não necessariamente são sequenciais. l  Chaves podem ser números, strings, registros, etc.

5

Estrutura de Dados

l  Vetores l  Mantêm uma série de elementos sequenciais

mantidos em uma ordem linear como um único, porém, com possibilidade de acesso individual;

l  Cada elemento possui um índice que indica sua posição no vetor e permite acessá-lo diretamente;

l  Vetores tem tamanhos fixos.

0 1 2 3 4 5 4 8 15 16 23 42

Índice

Valor

6

Pesquisa

l  Dado um conjunto de n chaves {k1, k2, …, kn}: l  Determinar a existência e/ou determinar a posição de

determinada chave ki; l  Determinar a maior, a menor, etc.

l  Dada a sequência de chaves abaixo, como determinar a existência da chave 8? Não sabemos se as chaves estão ordenadas…

? ? ? ? ? ?

7

Métodos de Pesquisa

l  Pesquisa Sequencial

l  Pesquisa Binária

8

Pesquisa Sequencial

l  Método intuitivo: l  Dada uma chave k, compará-la a cada chave no

vetor, caso haja uma igual, a chave está no vetor l  Caso todas as chaves tenham sido comparadas e não

houve nenhuma igual, a chave não existe no vetor.

42 16 4 15 8 23

k = 8

Chave encontrada!

9

Pesquisa Sequencial Código int Sequencial(int A[], int n, int k, int *posicao)!{! int i;! int achou = 0;!! for(i=0; i<n; i++)! if(A[i] == k)! {! *posicao = i;! achou = 1;! }!! return achou;!

}!

!!!!//sinaliza se a chave foi encontrada!!//para cada chave!//compara com a chave de busca!!//se encontrou!//armazena a posição!!//indica se encontrou ou não!

10

Pesquisa Sequencial Complexidade int Sequencial(int A[], int n, int k, int *posicao)!{! int i;! int achou = 0;!! for(i=0; i<n; i++)! if(A[i] == k)! {! *posicao = i;! achou = 1;! }! return achou;!}!

Custo Repetições !!c1 ! !n!c2 !!n-1!

Tempo = Θ(n)

11

Pesquisa Sequencial

l  Exercício l  Como torná-la mais rápida?

l  2 versões. l  Qual é a complexidade desta pesquisa sequencial

aprimorada? l  Se o elemento procurado for o primeiro? l  Se o elemento procurado for o último? l  E na média?

12

Pesquisa Binária

l  Assume que as chaves estão ordenadas l  A partir disto, é possível diminuir o espaço de busca,

restringindo-o por faixas de valores. l  Divide-se o problema ao meio seguidas vezes, até

que a chave desejada seja encontrada ou determine-se sua inexistência.

13

Pesquisa Binária

l  Determina a chave central do vetor; l  Caso a chave pesquisada não seja a central, compare

seus valores l  Se a chave pesquisada for menor, volte ao primeiro passo,

porém, considere o vetor do início até o ponto da chave central; l  Se a chave pesquisada for maior, volte ao primeiro passo,

porém, considere o vetor do ponto da chave central até o final.

4 8 15 16 23 42 49 51 62 70

k = 8

14

Pesquisa Binária

l  Determina a chave central do vetor; l  Caso a chave pesquisada não seja a central, compare

seus valores l  Se a chave pesquisada for menor, volte ao primeiro passo,

porém, considere o vetor do início até o ponto da chave central; l  Se a chave pesquisada for maior, volte ao primeiro passo,

porém, considere o vetor do ponto da chave central até o final.

4 8 15 16 23 42 49 51 62 70

k = 8

15

Pesquisa Binária

l  Determina a chave central do vetor; l  Caso a chave pesquisada não seja a central, compare

seus valores l  Se a chave pesquisada for menor, volte ao primeiro passo,

porém, considere o vetor do início até o ponto da chave central; l  Se a chave pesquisada for maior, volte ao primeiro passo,

porém, considere o vetor do ponto da chave central até o final.

4 8 15 16 23 42 49 51 62 70

k = 8

16

Pesquisa Binária

l  Determina a chave central do vetor; l  Caso a chave pesquisada não seja a central, compare

seus valores l  Se a chave pesquisada for menor, volte ao primeiro passo,

porém, considere o vetor do início até o ponto da chave central; l  Se a chave pesquisada for maior, volte ao primeiro passo,

porém, considere o vetor do ponto da chave central até o final.

4 8 15 16 23 42 49 51 62 70

k = 8

Chave encontrada!

17

Pesquisa Binária - Código

int PesquisaBinaria( int A[], int k, int n)!{! int esquerda = 0; ! int direita = n-1; ! int meio;!! while (esquerda <= direita) ! {! meio = (esquerda+direita)/2;! !! ! if (k == A[meio])!

return meio;! else if (k < A[meio])! direita = meio-1;! else! esquerda = meio+1;! }! return -1; !}!

!!!//determina onde começa a busca!//determina onde termina a busca!//determina a chave central!!//enquanto houver mais que !//uma chave no intervalo!//calcula a chave central!!//testa se a central é a procurada!!//compara se é menor!!//caso contrário é maior!!!//retorna -1 se não encontrou!

18

Pesquisa Binária - Complexidade l  Melhor Caso

l  A chave pesquisada é a primeira chave central: Θ(1); l  Pior Caso

l  A chave procurada não existe no vetor, todas as divisões terão de ser feitas.

⎩⎨⎧

Θ+

=Θ=

.)1()2/(,1)1(

)(casosoutrosnosnT

nsenT

19

Teorema Mestre Resumido

l  Alguns algoritmos têm sua complexidades determinadas através de recorrências da forma

)()(.3)log()(.2

1),()(.1 log

kk

kk

ak

nnTentãobaSennnTentãobaSe

bparannTentãobaSe b

Θ∈<

Θ∈=

>Θ∈>

knbnaTnT += )/()(

l  O Teorema Mestre estabelece três casos que podem ser simplificados:

20

Pesquisa Binária - Complexidade

l  Pelo segundo caso do Teorema Mestre, temos que no pior caso a complexidade da Pesquisa Binária é

)(log)()1()2/()(

nOnTnTnT

=

Θ+=

21

Ordenação

l  Dado um conjunto de n chaves {k1, k2, …, kn}, organizá-las tal que k’1 ≤ k’2 ≤ … ≤ k’n.

l  Por exemplo, dado (5, 3, 1, 2, 4), n = 5, temos 1 ≤ 2 ≤ 3 ≤ 4 ≤ 5.

l  Como ordenar a sequência de chaves abaixo?

15 23 4 42 8 16

4 8 15 16 23 42

22

Ordenação - Tipos

l  Ordenação Interna l  Todas as chaves na memória principal – facilidade de

acesso. l  Ordenação externa

l  Chaves na memória principal e em memória externa – movimentação de chaves entre as duas.

l  Diferentes métodos para cada tipo.

23

Ordenação - Propriedades

l  Estabilidade l  Manutenção da ordem relativa entre chaves de

mesmo valor; l  Especialmente importante para casos em que cada

elemento possui mais de uma chave. l  Adaptabilidade

l  Métodos adaptáveis têm o tempo de execução reduzido caso a entrada já esteja ordenada.

24

O que é importante saber sobre cada método l  Funcionamento; l  Tipo de ordenação efetuada; l  Complexidade

l  Comportamento de acordo com o caso, em termos da quantidade de chaves.

l  Estabilidade; l  Adaptabilidade; l  Especificidades;

25

Métodos de Ordenação

l  Bubble Sort (Método Bolha) l  Insertion Sort (Método de Inserção) l  Selection Sort (Método de Seleção) l  Quicksort l  Heapsort l  Bucket Sort (Bin Sort) l  Radix Sort l  Merge Sort (Ordenação por Intercalação)

26

Bubble Sort (Método Bolha) l  O método mais simples:

l  Suponha chaves em um vetor vertical A. Valores baixos são “leves” e valores altos são “pesados”. Como bolhas, os valores “leves” sobem no vetor um por vez, ao passo que os “pesados” descem.

l  Operação Troca(A[i], A[j]): os elementos das posições i e j trocam de posição.

27

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 ?

2 ?

3 3

4 1

Comparação: 1 e 3

Posição Chave

Troca(A[4], A[3])

28

Bubble Sort – Procedimento de Troca Troca(int *i, int *j) { int temp; temp = *i; *i = *j; *j = temp; }

1 ?

2 2

3 1

4 3

Comparação: 1 e 2

Posição Chave

Troca(A[3], A[2])

29

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 4

2 1

3 2

4 3

Comparação: 1 e 4

Posição Chave

Troca(A[2], A[1])

30

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 4

3 2

4 3

A chave mais “leve” chegou ao topo.

Posição Chave

Não será utilizada em futuras comparações.

31

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 4

3 2

4 3

Comparação: 3 e 2

Posição Chave

Não há troca.

32

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 4

3 2

4 3

Comparação: 2 e 4

Posição Chave

Troca(A[3], A[2])

33

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 2

3 4

4 3

A segunda mais leve chegou à sua posição.

Posição Chave

34

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 2

3 4

4 3

Comparação: 3 e 4

Posição Chave

Troca(A[4], A[3])

35

Bubble Sort - Funcionamento

l  O vetor é analisado comparando-se pares de chaves;

l  A mais “leve” sobe, a mais “pesada” desce;

l  Caso já estejam na posição correta, o próximo par é analisado.

1 1

2 2

3 3

4 4

Posição Chave

Chaves ordenadas.

36

Bubble Sort - Código

for(i=0; i<n-1; i++)!{! for(j=n-1; j>i; j--)! if(A[j] < A[j-1])! Troca(&A[j], &A[j-1]);!}!

// Para cada “bolha”, exceto a última!

// Percorre o vetor, exceto as chaves já !// ordenadas!

// Compara os pares!

// Se for mais “leve”, troca as posições!

37

Bubble Sort – Complexidade

1 for(i=0; i<n-1; i++)! {!2 for(j=n-1; j>i; j--)!3 if(A[j] < A[j-1])!4 Troca(&A[j], &A[j-1]);! }!

Custo Repetições !c1 ! !n!!c2 !!n-i!c3 !!n-i!!c4 ! !n-i!

38

Bubble Sort – Complexidade

nccccnccc⎟⎠

⎞⎜⎝

⎛ ++++⎟

⎞⎜⎝

⎛ ++=

2243212432

⎟⎟⎠

⎞⎜⎜⎝

⎛ −+⎟⎟⎠

⎞⎜⎜⎝

⎛ −+⎟⎟⎠

⎞⎜⎜⎝

⎛ −+=

222

2

4

2

3

2

21nncnncnncnc

∑ ∑∑−

=

=

=

−+−+−+1

1

1

143

1

121 )()()(

n

i

n

i

n

iincincincnc

Tempo = O(n2)

⎟⎠

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+=

2)1(

2)1(

2)1(

4321nncnncnncnc

39

Bubble Sort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n2). l  Quantidade de dados: Poucos. l  Especificidades: Complexidade fixa e código

compacto. l  Estabilidade: Sim. l  Adaptabilidade: Não. A implementação clássica

realiza a mesma quantidade de operações mesmo se as chaves já estiverem ordenadas.

40

Insertion Sort (Método de Inserção) l  Analogia com a

organização de cartas de baralho na mão;

l  Cartas são recebidas e colocadas na mão aleatoriamente;

l  Durante a organização, cada carta é colocada no seu lugar certo, uma por vez, deslocando as demais.

Extraído de Cormen, Leiserson, Rivest, (2001).

41

Insertion Sort - Funcionamento

l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas.

l  Caso já esteja na posição certa, passa-se ao próximo par.

6 4 ? ? ? ?

Chave 4 na posição errada.

42

Insertion Sort - Funcionamento

6 ? ? ? ?

Move-se as outras chaves para abrir o espaço. Valor da chave é armazenado. 4

l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas.

l  Caso já esteja na posição certa, passa-se ao próximo par.

43

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 6 ? ? ? ?

Valor da chave armazenada é inserido na posição certa.

44

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 6 7 ? ? ?

Chaves nas posições corretas.

45

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 6 7 5 ? ?

Chaves 5 na posição errada

46

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 6 7 ? ?

Move-se as outras chaves para abrir o espaço. Valor da chave é armazenado. 5

47

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 5 6 7 ? ?

Valor da chave armazenada é inserido na posição certa.

48

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 5 6 7 1 ?

Chave na posição errada.

49

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

4 5 6 7 ?

Move-se as outras chaves para abrir o espaço. Valor da chave é armazenado. 1

50

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

1 4 5 6 7 ?

Valor da chave armazenada é inserido na posição certa.

51

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

1 4 5 6 7 2

Chave na posição errada.

52

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

1 4 5 6 7

Move-se as outras chaves para abrir o espaço. Valor da chave é armazenado. 2

53

Insertion Sort - Funcionamento l  Compara-se os pares de chaves; l  Cada chave é colocada na posição correta

l  Para isso, outras são movidas. l  Caso já esteja na posição certa, passa-se ao

próximo par.

1 2 4 5 6 7

Valor da chave armazenada é inserido na posição certa. Chaves ordenadas.

54

Insertion Sort - Código

int ChaveAtual;!!for(j=1; j<n; j++)!{! ChaveAtual = A[j];! i = j-1;!! !

while(i>=0 && A[i] > ChaveAtual)! {! A[i+1] = A[i];! i--;! }!! A[i+1] = ChaveAtual;!}!

//Variável auxiliar para as comparações!

//Para cada uma das chaves, exceto a última!

//Chave comparada atualmente!

//Compara com as demais chaves!

//Abre o espaço entre as chaves maiores !

//Insere a chave na posição correta!

55

Insertion Sort - Complexidade

1 for(j=1; j<n; j++)! {!2 ChaveAtual = A[j];!3 i = j-1;!! !

4 while(i>=0 && A[i] > ChaveAtual)!! {!

5 A[i+1] = A[i];!6 i--;!! }!

!7 A[i+1] = ChaveAtual;! }!

Custo Repetições c1 ! !n!!c2 !!n-1!c3 !!n-1!!!c4 ! !j!!c5 ! !j-1 !!c6 ! !j-1 !!!!c7 ! !n-1!

56

Insertion Sort - Complexidade

∑ ∑∑−

=

=

=

−+−+−++−+−+1

17

1

165

1

14321 )1()1()1()()1()1(

n

j

n

j

n

jncjcjcjcncncnc

)(222222 74327654

3212654 ccccncccccccnccc

+++−⎟⎠

⎞⎜⎝

⎛+++++++⎟

⎞⎜⎝

⎛++=

Pior caso = O(n2)

7765433221 2)1(

2)1(1

2)1( cncnncnncnnccnccncnc −+⎟

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+

+−+−+=

57

Insertion Sort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n2). l  Quantidade de dados: Poucos. l  Especificidades: A complexidade, apesar de alta,

não é fixa. l  Estabilidade: Sim. l  Adaptabilidade: Sim.

58

Selection Sort (Método de Seleção)

l  Princípio simples; l  A cada iteração procura a chave de menor valor ainda

não ordenada; l  Depois de encontrada, ela é inserida na posição correta

do vetor.

59

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

? ? ? ? ?

? Menor chave

? Posição

60

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 ? ? ? ?

6 Menor chave

1 Posição

61

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 4 ? ? ?

4 Menor chave

2 Posição

62

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 4 3 ? ?

3 Menor chave

3 Posição

63

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 4 3 5 ?

3 Menor chave

3 Posição

64

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 4 3 5 1

1 Menor chave

5 Posição

65

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

6 4 3 5

1 Menor chave

5 Posição

66

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 6 4 3 5

3 Menor chave

4 Posição Acelerando…

67

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 6 4 5

3 Menor chave

4 Posição

68

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 6 4 5

? Menor chave

? Posição

69

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 6 4 5

4 Menor chave

4 Posição Acelerando…

70

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 6 5

4 Menor chave

4 Posição

71

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 4 6 5

? Menor chave

? Posição

72

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 4 6 5

5 Menor chave

5 Posição Acelerando…

73

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 4 6

5 Menor chave

5 Posição

74

Selection Sort - Funcionamento

l  A cada iteração procura a chave de menor valor ainda não ordenada;

l  Depois de encontrada, ela é inserida na posição correta.

1 3 4 5 6

Chaves ordenadas.

75

Selection Sort - Código

for(i=0; i<n-1; i++)! {! MenorChave = A[i];!! indice = i;!

!! for(j=i+1; j<n; j++)!! {!! if(A[j] < MenorChave)!! ! {!! ! MenorChave = A[j];!! ! indice = j;!! ! }!! }!

!! Troca(&A[i], &A[indice]);!

}!

//para cada uma das chaves,!//exceto a última!//inicializa o menor valor!//e menor índice!!//Entre as chaves não ordenadas!!

//Procura a menor!!//atualiza as variáveis!!

!!//Troca de lugar com a primeira!//chave não ordenada!

76

Selection Sort - Complexidade

for(i=0; i<n-1; i++)! {! MenorChave = A[i];!! indice = i;!

!! for(j=i+1; j<n; j++)!! {!! if(A[j] < MenorChave)!! ! {!! ! MenorChave = A[j];!! ! indice = j;!! ! }!! }!

!! Troca(&A[i], &A[indice]);!

}!

c1 ! ! !n!!c2 ! ! !n-1!c3 ! ! !n-1!!c4 ! ! !n-i!!c5 ! ! !n-i !!!c6 ! ! !n-i !!c7 ! ! !n-i!!!!c8 ! ! !n-1!!

Custo Repetições

77

Selection Sort - Complexidade

)1()()()()()1()1( 8

1

1

1

17

1

165

1

14321 −+−+−+−+−+−+−+ ∑ ∑∑∑

=

=

=

=

ncincincincincncncncn

i

n

i

n

i

n

i

88765433221 2)1(

2)1(

2)1(

2)1( cncnncnncnncnnccnccncnc −+⎟

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+⎟⎠

⎞⎜⎝

⎛ −+−+−+

)(22222222 83287654

32127654 cccnccccccccncccc

++−⎟⎠

⎞⎜⎝

⎛++++++++⎟

⎞⎜⎝

⎛+++

Tempo = O(n2)

78

Selection Sort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n2). l  Quantidade de dados: Poucos. l  Especificidades: A complexidade é fixa. l  Estabilidade: Depende da implementação. A

apresentada é estável. l  Adaptabilidade: Não.

79

Quicksort

l  Provavelmente o mais eficiente para ordenação interna;

l  Baseado no paradigma “Dividir-e-Conquistar”; l  Divide o problema original em problemas menores,

semelhantes. l  Procedimento recursivo; l  Complexidade varia com o caso; l  Funcionamento não trivial como os anteriores.

80

Quicksort

l  Três passos básicos: l  Dividir:Escolha uma chave pivô e divida o vetor em

dois subvetores (possivelmente vazios) tal que as chaves do subvetor à esquerda sejam menores que a chave pivô, que por sua vez é menor que as chaves do subvetor à direita;

l  Conquistar: Ordene os subvetores recursivamente, dividindo-os também;

l  Combinar: Uma vez que todos os subvetores estejam ordenados, o vetor original também estará.

81

Quicksort - Funcionamento

l  Escolhe-se o pivô: primeira chave do vetor (existem outras estratégias);

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 ? ? ? ? ? ? ? ?

Pivô Chave 1 permanecerá à esquerda.

82

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 4 ? ? ? ? ? ? ?

Pivô Chave 4 permanecerá à direita.

Divisão

83

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 4 1 ? ? ? ? ? ?

Pivô Chave 1 permanecerá à esquerda.

Divisão

84

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 4 5 ? ? ? ? ?

Pivô Chave 4 permanecerá à direita.

Divisão

85

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 4 5 9 ? ? ? ?

Pivô Chave 9 permanecerá à direita.

Divisão

86

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 4 5 9 2 ? ? ?

Pivô Chave 2 permanecerá à esquerda.

Divisão

87

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 2 5 9 4 6 ? ?

Pivô Chave 6 permanecerá à direita.

Divisão

88

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 2 5 9 4 6 5 ?

Pivô Chave 5 permanecerá à direita.

Divisão

89

Quicksort - Funcionamento

l  Percorre-se o vetor de esquerda a direita, comparando-se as chaves;

l  Menores para a esquerda, maiores para a direita.

3 1 1 2 5 9 4 6 5 3

Pivô Chave 5 permanecerá à direita.

Divisão

90

Quicksort - Funcionamento

l  Inserir o pivô na posição correta.

3 1 1 2 5 9 4 6 5 3

Pivô Divisão

91

Quicksort - Funcionamento

l  Inserir o pivô na posição correta; l  Agora o vetor deve ser dividido em duas partes:

l  Do início a antes do pivô; l  De depois do pivô ao final.

2 1 1 3 5 9 4 6 5 3

92

Quicksort - Funcionamento

l  Cada metade do vetor é submetida ao mesmo processo individualmente, podendo ser dividida novamente;

l  No fim, junta-se as partes ordenadas.

2 1 1

Pivô

1 1 2

93

Quicksort - Funcionamento

2 1 1 3 5 9 4 6 5 3

2 1 1 5 9 4 6 5 3

1 1 2 3 4 5 6 5 9

1 1 3 4 6 5 9

1 1 3 4 5 6 9

3 1 4 1 5 9 2 6 5 3

94

int Particao(int A[], int esquerda, int direita) !{! int i;! int j;! ! i = esquerda;! for(j=esquerda+1; j<=direita; j++) ! {! if (A[j] < A[esquerda]) !! {!

i++;! Troca(&A[i], &A[j]);! }! }!! Troca(&A[esquerda], &A[i]);! ! return i;!}! !

Quicksort - Código

!!!!//variável de controle!//percorre o subvetor!!//se a chave analisada!//for menor que o pivô!!//troca as chaves de !//posição!!!//insere o pivô na !//posição correta!

95

Quicksort - Código

Quicksort(int A[], int esquerda, int direita) !{! int p;! ! if (direita > esquerda) ! {! p = Dividir(A, esquerda, direita);! Quicksort(A, esquerda, p-1);! Quicksort(A, p+1, direita);! }!}!

!//pivô!!//se o subvetor não !//for vazio !//ele é ordenado!//divide em parte esquerda!//e parte direita!

96

int Particao(int A[], int esquerda, int direita) !{! int i;! int j;! ! i = esquerda;! 1 for(j=esquerda+1; j<=direita; j++) ! {! 2 if (A[j] < A[esquerda]) !! {!

3 i++;! 4 Troca(&A[i], &A[j]);! }! }!! Troca(&A[esquerda], &A[i]);! ! return i;!}! !

Quicksort - Complexidade

!!!c1 ! ! !n!!c2 ! ! !n-1!!c3 ! ! !n-1!c4 ! ! !n-1!

Custo Repetições

Tempo = Θ(n)

97

Quicksort - Complexidade

l  Suponha que para ordenar n chaves, a complexidade é dada pela recorrência

T(n) = T(i)+T(n-i-1) + Θ(n) l  Em que i representa o tamanho da partição obtida e

T(0) = Θ(1). l  O pior caso do Quicksort ocorre quando as

partições nunca são eficientes: o vetor é dividido em um parte com n-1 chaves e outra com 0 chaves, ou seja, não há partição efetiva em nenhuma das chamadas recursivas;

l  Isto ocorre quando o vetor já está ordenado;

98

Quicksort - Complexidade

l  No pior caso, para i=0, temos então:

⎡ ⎤2/n

)()()()1()(

2nOnTnnTnT

=

Θ+−=

l  No melhor caso, para i= ou -1 (partição perfeita), temos:

)log()(

)(2

2)(

)(122

)(

nnOnT

nnTnT

nnnTnTnT

=

Θ+⎟⎠

⎞⎜⎝

⎛≤

Θ+⎟⎠

⎞⎜⎝

⎛ −−+⎟⎠

⎞⎜⎝

⎛≤

(Pelo Teorema Mestre, caso 2)

⎣ ⎦2/n

99

Quicksort - Complexidade

l  Para o caso médio, suponhamos que todas as possíveis partições (0 e n-1, 1 e n-2, …, n-1 e 0) possuem a mesma probabilidade de acontecer, ou seja, 1/n para cada;

l  Isto quer dizer que, na árvore de recursão, partições boa e ruins se alternarão aleatoriamente em cada nível;

l  É razoável pensar que elas se alternam em cada nível deterministicamente no caso médio.

100

Quicksort - Complexidade

n

0 n-1

Θ(n) n

(n-1)/2

Θ(n)

(n-1)/2

l  A pior partição l  A melhor partição

101

Quicksort - Complexidade

l  Uma má partição seguida por uma boa partição

n

n-1

Θ(n)

(n-1)/2[(n-1)/2]-1

0

l  Temos 3 subvetores, obtidos aos custos Θ(n)+Θ(n-1) = Θ(n)

l  O custo das boas partições absorvem o das más.

102

Quicksort - Complexidade

l  Logo, se a complexidade para boas partições é Θ(nlogn), para o caso médio temos uma constante maior, resultando ainda em O(nlogn).

l  Esta não é uma prova da complexidade, é uma intuição sobre a mesma, que pode ser confirmada matematicamente.

103

Quicksort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n2) no pior caso e O(nlogn) no melhor caso

e também no caso médio. l  Quantidade de dados: Muitos. l  Especificidades: Estratégias de seleção de pivô e partição

podem influenciar o tempo de execução. Apesar de ser quadrático no pior caso, o caso médio justifica sua utilização.

l  Estabilidade: Depende da partição. A versão apresentada é instável. Uma versão in place é estável. Infelizmente, métodos eficientes são instáveis.

l  Adaptabilidade: Não.

104

Heapsort

l  Utiliza uma estrutura de dados específica: o Heap l  Árvore binária completa em todos os níveis, exceto

o último (possivelmente); l  Também pode ser visto como um vetor e possui as

seguintes propriedades: l  A raiz da árvore é armazenada em A[1]; l  Para um dado nó i:

l  O seu nó pai é ; l  Seu filho à esquerda é 2i; l  Seu filho à direita é 2i+1;

⎣ ⎦2/i

105

Heapsort - Heaps 16

10

9 3

14

8 7

2 4 1

1

2 3

4 5 6 7

8 9 10

1423978101416 1423978101416

1 2 3 4 5 6 7 8 9 10

Θ(lgn)

106

Heaps

l  Os heaps podem ser máximos ou mínimos; l  Raiz com o maior valor e pais com valor ≥ que os

filhos – MaxHeap. l  Raiz com o menor valor e pais com valor ≤ que os

filhos – MinHeap. l  No Heapsort, chaves são inseridas em um heap

máximo; l  Ao serem retiradas do heap, as chaves estarão

ordenadas; l  É necessário manter as propriedades do heap

durante as inserções e exclusões.

107

Heapsort – Funcionamento

l  Utiliza 3 operações sobre heaps: l  MAX-HEAPIFY: mantém a propriedade do heap

máximo; l  BUILD-MAX-HEAP: produz um heap a partir de um

vetor de entrada; l  HEAPSORT: ordena o vetor que representa o heap.

108

Heapsort – MAX-HEAPIFY

l  Cada subárvore deve ser um heap máximo, portanto, um nó pai não pode ser maior que os nós filhos;

l  Caso o nó pai seja menor que um dos filhos, ele trocará de posição com o maior deles;

l  É aplicado recursivamente para garantir que uma mudança realizada não viola a propriedade em outras subárvores.

109

Heapsort – MAX-HEAPIFY

16

10

9 3

4

14 7

2 8 1

1

2 3

4 5 6 7

8 9 10

110

Heapsort – MAX-HEAPIFY

16

10

9 3

14

4 7

2 8 1

1

2 3

4 5 6 7

8 9 10

111

Heapsort – MAX-HEAPIFY

16

10

9 3

14

8 7

2 4 1

1

2 3

4 5 6 7

8 9 10

112

MAX-HEAPIFY - Código

void MAX_HEAPIFY(int A[], int i, int n){! int esquerdo;! int direito;! int maior;!!

esquerdo = 2*i;! direito = 2*i+1;!!

if(esquerdo <= n && A[esquerdo] > A[i])!! maior = esquerdo;!

else!! maior = i;!

!

if (direito <= n && A[direito] > A[maior])!! maior = direito;!

!

if(maior != i) {! Troca(&A[i], &A[maior]);!! MAX_HEAPIFY(A, maior, n);!

}!}!

!!

//determina o filho esquerdo!//determina o filho direito!!!!!//se o filho esquerdo for!//maior que o pai, registra!!//senão!//o maior é o pai mesmo!//se o direito é maior que o maior!!//registra!!//se o maior não é o pai!!//troca as posições!//verifica se a subárvore viola a !//propriedade!!!!

113

MAX-HEAPIFY - Complexidade

l  Θ(1) para fazer as trocas em um mesmo nível; l  Uma subárvore pode ter no máximo tamanho 2n/3; l  No pior caso então, a complexidade é dada pela

recorrência

)(log)(

)1(32)(

nOnT

nTnT

==

Θ+⎟⎠

⎞⎜⎝

⎛=

(Pelo teorema mestre, caso 2)

114

Heapsort – BUILD-MAX-HEAP

l  Utiliza o procedimento anterior para transformar um vetor em um heap máximo;

l  É aplicado de baixo para cima na árvore; l  Da metade do vetor em diante estão as folhas da

árvore, então o procedimento é aplicado deste ponto para trás no vetor;

l  A propriedade do heap é mantida pelo procedimento anterior.

115

Heapsort – BUILD-MAX-HEAP

4

3

9 10

1

2 16

14 8 7

1

2 3

4 5 6 7

8 9 10

4 1 3 2 16 9 10 14 8 7

116

Heapsort – BUILD-MAX-HEAP 4

3

9 10

1

2 16

14 8 7

1

2 3

4 5 6 7

8 9 10

117

Heapsort – BUILD-MAX-HEAP 4

3

9 10

1

14 16

2 8 7

1

2 3

4 5 6 7

8 9 10

118

Heapsort – BUILD-MAX-HEAP 4

10

9 3

1

14 16

2 8 7

1

2 3

4 5 6 7

8 9 10

119

Heapsort – BUILD-MAX-HEAP 4

10

9 3

16

14 7

2 8 1

1

2 3

4 5 6 7

8 9 10

120

Heapsort – BUILD-MAX-HEAP 16

10

9 3

14

8 7

2 4 1

1

2 3

4 5 6 7

8 9 10

121

BUILD-MAX-HEAP - Código

void BUILD_MAX_HEAP(int A[],int n)!{! int i;!! for(i=n/2; i>0; i--)! MAX_HEAPIFY(A, i, n);!}!

!

//Para cada uma das subárvores,!//verifica corrige a propriedade !//do heap!//folhas não são verificadas!

122

BUILD-MAX-HEAP Complexidade l  Aparentemente, a complexidade é O(nlogn); l  Porém, analisando-se a quantidade máxima de nós

por nível do heap, e a quantidade de níveis, é possível provar que a complexidade do procedimento pode ser limitada por O(n);

l  Em outras palavras, construir um heap a partir de um vetor aleatório é possível em tempo linear.

123

Heapsort - Funcionamento

l  Inicialmente constrói um heap (BUILD-MAX-HEAP); l  A maior chave estará na raiz do heap, então ela

será a última chave na ordenação – ela é removida do heap;

l  A nova raiz pode violar a propriedade do heap, portanto, aplica-se o procedimento MAX-HEAPIFY;

l  Agora, a segunda maior chave está na raiz, ela será a penúltima na ordenação final;

l  E assim por diante… l  A árvore diminui a cada remoção.

124

Heapsort - Funcionamento 16

10

9 3

14

8 7

2 4 1

125

Heapsort - Funcionamento 14

10

9 3

8

4 7

2 1 16i

Como esta chave veio parar aqui?

126

Heapsort - Funcionamento 10

9

1 3

8

4 7

2 16i

14

127

Heapsort - Funcionamento 9

3

1 2

8

4 7

10 16i

14

128

Heapsort - Funcionamento 8

3

1 9

7

4 2

10 16

i

14

129

Heapsort - Funcionamento 7

3

8 9

4

1 2

10 16

i

14

130

Heapsort - Funcionamento 4

3

8 9

2

1 7

10 16

i

14

131

Heapsort - Funcionamento 3

1

8 9

2

4 7

10 16

i

14

132

Heapsort - Funcionamento 2

3

8 9

1

4 7

10 16

i

14

133

Heapsort - Funcionamento

1

3

8 9

2

4 7

10 16

i

14

1 2 3 4 7 8 9 10 14 16

134

Heapsort - Código

void HEAPSORT(int A[], int n)!{! int i;!! BUILD_MAX_HEAP(A, n-1);!! for(i=n-1; i>0; i--)! {! Troca(&A[1], &A[i]);!! MAX_HEAPIFY(A, 1, i-1);!

}!}!

!!

!!//constrói o heap inicial!!//para cada chave!//coloca a raiz do heap na !//posição correta da ordenação!//verifica e corrige a!//propriedade do heap!

135

Heapsort - Complexidade

void HEAPSORT(int A[], int n)!{! int i;!! BUILD_MAX_HEAP(A, n-1);!! for(i=n-1; i>0; i--)! {! Troca(&A[1], &A[i]);!! MAX_HEAPIFY(A, 1, i-1);!

}!}!

O(n) ! !1!!c1! ! !n!!!

c3! ! !n-1!O(logn) ! !n-1!!!!!!

Custo Repetições

136

Heapsort - Complexidade

nnnccnn

nnncncncnnnncncn

log)1(log)1(loglog)1(log)1(

31

331

31

=

+++−=

−+−++=

−+−++

Tempo = O(nlogn)

137

Heapsort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(nlogn) no pior caso. l  Quantidade de dados: Muitos. l  Especificidades: Melhor complexidade, porém, uma

boa implementação do Quicksort é melhor na prática, devido a questões de hardware (cache).

l  Estabilidade: Não. l  Adaptabilidade: Não.

138

Bucket Sort (Bin Sort)

l  Pressupõe que a entrada consiste em números inteiros distribuídos uniformemente sobre um intervalo l  Ou seja, que há um limite nos valores das chaves.

l  O intervalo é então dividido em n subintervalos de tamanhos iguais, os chamados buckets (baldes);

l  Cada chave vai para o balde correspondente à sua faixa de valor l  Considerando a uniformidade da distribuição, não

esperamos muitas chaves em um mesmo balde.

139

Bucket Sort – Funcionamento

l  Cada balde é posteriormente ordenado, isoladamente dos demais;

l  Considerando o limite [0,1), e chaves com dois dígitos decimais, determinamos o número de baldes como 10 (0, …9).

l  A função para determinação do índice balde correto é ;

⎣ ⎦][iAn×

140

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 /

A

B

141

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 8 / 9 /

A

B

0,78 /

142

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 / 3 / 4 / 5 / 6 / 7 8 / 9 /

A

B

0,78 /

0,17 /

143

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 / 3 4 / 5 / 6 / 7 8 / 9 /

A

B

0,78 /

0,17 /

0,39 /

144

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9 /

A

B

0,78 /

0,17 /

0,39 /

0,26 /

145

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9 /

A

B

0,72

0,17 /

0,39 /

0,26 /

0,78 /

146

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9

A

B

0,72

0,17 /

0,39 /

0,26 /

0,78 /

0,94 /

147

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9

A

B

0,72

0,17 /

0,39 /

0,21

0,78 /

0,94 /

0,26 /

148

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9

A

B

0,72

0,12

0,39 /

0,21

0,78 /

0,94 /

0,26 /

0,17 /

149

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 / 7 8 / 9

A

B

0,72

0,12

0,39 /

0,23

0,78 /

0,94 /

0,26 /

0,17 /

0,21

150

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 7 8 / 9

A

B

0,72

0,12

0,39 /

0,23

0,78 /

0,94 /

0,26 /

0,17 /

0,21

0,68 /

151

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 7 8 / 9

A

B

0,72

0,12

0,39 /

0,23

0,78 /

0,94 /

0,26 /

0,17 /

0,21

0,68 /

Balde desordenado.

152

Bucket Sort – Funcionamento

0,78 0,17 0,39 0,26 0,72 0,94 0,21 0,12 0,23 0,68

0 / 1 2 3 4 / 5 / 6 7 8 / 9

A

B

0,72

0,12

0,39 /

0,21

0,78 /

0,94 /

0,26 /

0,17 /

0,23

0,68 /

153

Bucket Sort – Pseudo Código

void BucketSort(int A[], int n)!{! int i;!! for(i=0; i<n; i++)! InserirLista (B[int floor(n*A[i])], A[i]);!! for(i=0; i<n-1; i++)!! InsertionSortLista(&B[i])!

! ConcatenarListasEncadeadas(n-1);!}!

154

Bucket Sort – Complexidade

void BucketSort(int A[], int n)!{! int i;!! for(i=0; i<n; i++)! InserirLista…!! for(i=0; i<n-1; i++)!! InsertionSortLista(&B[i]);!

! ConcatenarListasEncadeadas(n-1);!}!

!!c1! ! !n!O(1) ! !n-1!!c3! ! !n-1!O(ni

2) ! !n-1!

Custo Repetições

155

Bucket Sort - Complexidade

l  O custo das sucessivas chamadas a ordenação por inserção pode ser calculado pela recorrência

∑−

=

+Θ=1

0

2 )()()(n

iinOnnT

l  Em que ni denota a quantidade de chaves no balde i; l  Tomando as expectativas de ambos os lados e usando a

linearidade de expectativa, temos:

+Θ=

+Θ=

⎥⎦⎤

⎢⎣⎡ +Θ=

1

0

2

1

0

2

1

0

2

])[()(

)]([)(

)()()]([

n

i

n

i

n

i

nEOn

nOEn

nOnEnTE

156

Bucket Sort - Complexidade

l  O valor esperado para é 2-1/n; l  Substituindo na última equação, temos

][ 2inE

)()/12()( nnOnn Θ=−×+Θ

l  Desta maneira, o Bucket Sort é linear; l  Pode ser provado que, mesmo a entrada não sendo

uma distribuição uniforme o Bucket Sort ainda executará em tempo linear.

157

Bucket Sort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n). l  Quantidade de dados: Muitos, porém, com valores

limitados. l  Especificidades: Pressupõe características da

entrada, e a implementação depende de tais características. Um Bucket Sort com apenas dois buckets é na verdade o Quicksort (com pivoteamento ruim).

l  Estabilidade: Depende do algoritmo de ordenação interna dos buckets.

l  Adaptabilidade: Depende do algoritmo de ordenação interna dos buckets.

158

Radix Sort

l  Utiliza o conceito do Bucket Sort; l  Pressupõe que as chaves de entrada possuem

limite no valor e no tamanho (quantidade de dígitos);

l  É essencial utilizar um segundo algoritmo estável para realizar a ordenação;

l  Ordena números um digito de cada vez; l  A partir do menos significativo; l  Ou a partir do menos significativo.

159

Radix Sort

l  Como os valores possuem limite, e a quantidade de dígitos é fixa, é possível aplicar o Bucket Sort para cada nível; l  Cria-se um balde para cada possível valor dos dígitos

(0-9, ao invés de para cada faixa de valores), de modo a não ser necessário ordenar os baldes internamente.

l  O Bucket Sort é linear neste caso, uma vez que não é necessário ordenar os baldes isoladamente.

160

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

161

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

7 2 03 5 54 3 64 5 76 5 73 2 98 3 9

162

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

7 2 03 5 54 3 64 5 76 5 73 2 98 3 9

163

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

7 2 03 5 54 3 64 5 76 5 73 2 98 3 9

7 2 03 2 94 3 68 3 93 5 54 5 76 5 7

164

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

7 2 03 5 54 3 64 5 76 5 73 2 98 3 9

7 2 03 2 94 3 68 3 93 5 54 5 76 5 7

165

Radix Sort - Funcionamento

l  A partir dos dígitos menos significativos, ordene as chaves.

3 2 94 5 76 5 78 3 94 3 67 2 03 5 5

7 2 03 5 54 3 64 5 76 5 73 2 98 3 9

7 2 03 2 94 3 68 3 93 5 54 5 76 5 7

3 2 93 5 54 3 64 5 76 5 77 2 08 3 9

166

Radix Sort – Pseudo Código

l  Como dito anteriormente, o Radix Sort consiste em usar um outro método de ordenação (estável) para ordenar as chaves em relação a cada dígito;

l  O código, portanto, é muito simples:

RadixSort(A[], d)!{! for(i=0; i<d; i++)! BucketSort(A, d);!}!

l  Em que d é o dígito em relação ao qual as chaves serão ordenadas.

167

Radix Sort - Complexidade

l  Considerando n chaves de d dígitos e valores até k, temos:

))(( knd +Θ

l  Quando d é constante e k = O(n), que é o caso quando usamos o Bucket Sort, temos:

)(nΘ

168

Radix Sort – Resumo

l  Tipo de Ordenação: Interna. l  Complexidade: O(n). l  Quantidade de dados: Muitos, porém, com chaves de

tamanhos limitados. l  Especificidades: Pressupõe características da entrada, e a

implementação depende de tais características. l  Estabilidade: Usando o dígito menos significativo sim, usando o

mais significativo, não. l  Especificidades: Apesar da complexidade melhor deste

método, na prática o Quicksort ainda é melhor, por fazer melhor uso de cache do computador, além de melhores constantes.

l  Adaptabilidade: Não.

169

Merge Sort (Ordenação por Intercalação) l  Baseado no paradigma Dividir-e-Conquistar

l  Divide o problema original em problemas menores semelhantes;

l  Resolve os problemas menores – mais “fáceis”; l  Combina os problemas menores para formar a

solução para o problema original l  É mais fácil ordenar chaves parcialmente ordenadas.

l  É um algoritmo recursivo.

170

Merge Sort

l  Baseado em dois procedimentos: l  MERGE: Cria dois subvetores, cada um

correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original;

l  MERGE_SORT: Divide o problema original em subproblemas, e usa o procedimento anterior para resolvê-los.

171

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

2 4 5 7 1 2 3 6

p q r

l  p: Limite esquerdo do vetor; l  r: Limite direito do vetor; l  q: Meio do vetor ;

A

⎣ ⎦2/)( rp +

172

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

2 4 5 7 1 2 3 6

2 4 5 7 S 1 2 3 6 S

A

E D

p q r q+1 Sentinela Sentinela

173

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

? ? ? ? ? ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

174

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 ? ? ? ? ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

175

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 2 ? ? ? ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

176

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 2 2 ? ? ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

177

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 2 2 3 ? ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

178

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 2 2 3 4 ? ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

179

Merge Sort - MERGE

l  Cria dois subvetores, cada um correspondente a uma metade do vetor original, depois intercala os menores valores, copiando-os de volta ao vetor original.

1 2 2 3 4 5 ? ?

2 4 5 7 S 1 2 3 6 S

A

E D

180

Merge Sort - MERGE

l  S é um valor suficientemente grande, tal que, sempre que comparado, será maior que o elemento original do vetor.

1 2 2 3 4 5 6 ?

2 4 5 7 S 1 2 3 6 S

A

E D

181

Merge Sort - MERGE

l  Para que funcione, o vetor original deve ter subvetores ordenados;

l  Para isso, aplica-se recursivamente o algoritmo l  Quando chegar ao ponto deste exemplo, os subvetores estarão

ordenados.

1 2 2 3 4 5 6 7

2 4 5 7 S 1 2 3 6 S

A

E D

182

MERGE - Código MERGE(int A[], int p, int q, int r)!{! n1 = q-p+1;! n2 = r-q;!! for(i=0; i<n1; i++)! E[i] = A[p+i];! for(i=0; i<n2; i++)!

! D[i] = A[q+i+1];!! E[n1] = INT_MAX;! D[n2] = INT_MAX;! i = j = 0;!! for(k=p; k<=r; k++)! if(E[i] <= D[j]) ! {!

! ! A[k] = E[i]; i++;!! }!! else ! {!! A[k] = D[j]; j++;!! }!

}!

//define o tamanho dos subvetores !//esquerdo e direito!!//preenche o subvetor esquerdo!!//preenche o subvetor direito!!!//sentinela esquerda!//sentinela direita!!!//Intercala as menores chaves!!!//e copia para o vetor original!

Exercício: Alocação dos vetores E e D dinamicamente, e posterior liberação da memória.

183

MERGE - Complexidade MERGE(int A[], int p, int q, int r)!{! n1 = q-p+1;! n2 = r-q;!! for(i=0; i<n1; i++)! E[i] = A[p+i];! for(i=0; i<n2; i++)!

! D[i] = A[q+i+1];!! E[n1] = INT_MAX;! D[n2] = INT_MAX;! i = j = 0;!! for(k=p; k<=r; k++)! if(E[i] <= D[j]) ! {!

! ! A[k] = E[i]; i++;!! }!! else ! {!! A[k] = D[j]; j++;!! }!

}!

!!!c1 ! ! !(n/2)+1!!c2 ! ! !(n/2)+1!!!!!!!c3 ! ! !n!!!!

Custo Repetições

Tempo = Θ(n)

184

Merge Sort – MERGE_SORT

l  Divide o vetor ao meio recursivamente até que não seja mais possível l  Subvetor com apenas uma chave.

l  Na volta das chamadas recursivas, combina e ordena os últimos 2 subvetores l  Na primeira vez, dois subvetores de apenas uma

chave. l  Os subvetores vão aumentando de tamanho, até

formar o vetor original.

185

MERGE_SORT

5 2 4 7 1 3 2 6

186

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

187

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

188

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

Intercala

189

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

190

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

Intercala

191

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

192

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74Intercala

193

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

194

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

195

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

1 3

Intercala

196

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

1 3 2 6

Intercala

197

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

1 3 2 6Intercala

198

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

1 3 2 6

1 2 3 6

Intercala

199

MERGE_SORT

5 2 4 7 1 3 2 6

1 3 2 6 5 2 4 7

5 2 4 7

5 2

2 5

74

2 4 5 7

1 3 2 6

1 3 2 6

1 2 3 6

1 2 2 3 4 5 6 7

200

MERGE_SORT - Código

!

MERGE_SORT(int A[], int p, int r)!{! int q;!! if(p < r)! {! q = (p+r)/2;!! MERGE_SORT(A, p, q);!! MERGE_SORT(A, q+1, r);!! MERGE(A, p, q, r);!

}!}!!!!

l  Primeira chamada: MERGE_SORT(A, 0, n-1);!

//dividir!//conquistar!!//combinar!

201

Merge Sort - Complexidade

l  A análise da complexidade do Merge Sort é baseada nos três passos do paradigma: l  Dividir – D(n); l  Conquistar; l  Combinar – C(n).

l  Em se tratando de um algoritmo recursivo, a complexidade é definida por uma recorrência:

⎩⎨⎧

++

=Θ=

.)()()2/(2,1)1(

)(casosoutrosnosnCnDnT

nsenT

202

Merge Sort - Complexidade

l  Claramente, dividir o problema leva tempo constante, logo:

)2/(2 nT

l  Para resolver dois subproblemas, que consistem na metade do problema original, temos:

l  Para combinar os subproblemas, usamos o procedimento MERGE, que conforme vimos, possui complexidade:

)()( nOnC =

)1()( Θ=nD

203

Merge Sort - Complexidade

l  Voltando à recorrência, temos então:

⎩⎨⎧

Θ+

=Θ=

.)()2/(2,1)1(

)(casosoutrosnosnnT

nsenT

l  De acordo com o Teorema Mestre, caso 2 temos que:

)log()()()2/(2)(

nnnTnnTnT

Θ=

Θ+=

204

Merge Sort – Resumo

l  Tipo de Ordenação: Interna/Externa. l  Complexidade: Θ(nlogn). l  Quantidade de dados: Muitos. l  Especificidades: Alto consumo de memória, devido às

várias chamadas recursivas. l  Estabilidade: Sim. l  Adaptabilidade:Não.