algoritmos de ordenação e pesquisa - decom … ordenação e pesquisa ! os elementos são chamados...
TRANSCRIPT
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…
? ? ? ? ? ?
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
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.
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.
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.
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.
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
Θ=
Θ+=