Upload
internet
View
109
Download
2
Embed Size (px)
Citation preview
Métodos de Classificação por Seleção: HeapSort
Prof. Alexandre Parra Carneiro da Silva
Principais Métodos Classificação por Trocas Classificação por Seleção
Classificação por Seleção Caracteriza-se por identificar, a cada
iteração, a chave de menor (maior) valor na porção do vetor ainda não ordenada e colocá-la em sua posição definitiva.
HeapSort Utiliza uma estrutura de dados (heap) para
organizar a informação durante a execução do algoritmo.
Um heap é uma estrutura de dados baseada em árvore binária que segue um critério (ou condição) bem-definido(a).
Estruturalmente, deve ser uma árvore quase completa: o último nível pode não conter os nós mais
à direita.
Condição de Heap Os dados armazenados em um heap
devem satisfazer a seguinte condição: Todo nó deve ter valor maior ou igual com
relação aos seus filhos (Heap Máximo).
A condição não determina nenhuma relação entre os filhos de um nó (não confundir com árvore binária de pesquisa).
Exemplo de um Heap Máximo
Como representar Heaps ? Podemos representar heaps como árvores binárias ou vetores.
A idéia é linearizar a árvore por níveis.
Relacionando os nós do Heap A representação em vetores permite
relacionar os nós do heap da seguinte forma: raiz da árvore: primeira posição do vetor filhos de um nó na posição i: posições 2i e 2i+1 pai de um nó na posição i: posição i / 2
1
2 3
4 5 6 7
8 9 10
Procedimentos sobre Heaps
Heapify Garante a manutenção da propriedade do
Heap. Complexidade O(log2n). Build-Heap
Produz um heap a partir de um vetor não ordenado. Complexidade O(n).
Heapsort Procedimento de ordenação.
Complexidade(nlog2n).
Procedimento Heapfy Reorganiza heaps (Objetivo: manter a condição).
Assume que as árvores binárias correspondentes a Esq(i) e Dir(i) são heaps, mas A[i] pode ser menor que seus filhos.
Exemplo:
16
9 3
10
2 1 8
7 14
1
2 3
4 5 6 7
8 9 10
4i
16
9 3
10
2 1 8
7
14
1
2 3
4 5 6 7
8 9 10
4i
16 4 10 14 7 9 3 2 8 1
Procedimento Build-Heap Utiliza o procedimento Heapify de forma bottom-up para transformar um vetor A[1..n] em um heap com n elementos.
A[([n/2]+1)] a A[n] correspondem às folhas da árvore e portanto são heaps de um elemento.
Basta chamar Heapify para os demais elementos do vetor A, ou seja, de A[(n/2)] a 1.
Exemplo de Build-Heap Vetor: 16 4 10 14 7 9 3 2 8 1
16
9 3
10
2 1 8
7 14
1
2 3
4 5 6 7
8 9 10
4i
16
9 3
10
2 1 8
7
14
1
2 3
4 5 6 7
8 9 10
4i
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
Exercício em Sala 1. Utilize o procedimento Build-Heap para
construir um heap a partir do vetor.
4 1 3 2 16 9 10 14 8 71
Procedimento HeapSort1) Constrói um heap a partir de um vetor de entrada
(Build-Heap).
2) Como o maior elemento está localizado na raiz (A[1]), este pode ser colocado em sua posição final, trocando-o pelo elemento A[n].
3) Reduz o tamanho do heap de uma unidade, chama Heapify(A,1) e após término de Heapfy(A,1) repete-se o passo anterior (2), até que o heap tenha tamanho = 2.
Exemplo de HeapSort (1/2)
Resultado do Build-Heap sobre o vetor
é:
16 4 10 14 7 9 3 2 8 1
16 14 10 8 7 9 3 2 4 1
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
Exemplo de HeapSort (2/2) Aplicando o procedimento HeapSort sobre o
vetor resultado do Build-Heap anterior, temos:
16 14 10 8 7 9 3 2 4 1
1
8 9
3
10 16
4 7
2
1
2 3
4 5 6 7
8 9 10
14
1 2 3 4 7 8 9 10 14 16
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10
4
Exercício em Sala Utilize o procedimento HeapSort sobre o
resultado do Build-Heap do vetor 4 1 3 2 16 9 10 14 8 71
HeapSort - Análise de Desempenho (1/3)
Procedimento HeapfyProc heapify ( A, i ) begin e Esquerda(i); d Direita(i); maior i; if (e heap_size[A] and A[e] > A[maior]) then maior e; /* filho da esquerda é maior */ if (d heap_size[A] and A[d] > A[maior]) then maior d; /* filho da direita é maior */ if (maior i) then begin exchange(A[i] A[maior]); heapify(A, maior); end end.
Complexidade: O(log2n) – cada troca e comparação tem custo O(1). No máximo ocorrem log2n trocas. Ocorrem duas comparações (entre chaves) a cada chamada da função heapfy.
HeapSort - Análise de Desempenho (2/3)
Procedimento Build-HeapProc build-heap ( A ) begin heap_size[A] length[A]; for i [length[A]/2] downto 1 do
heapify(A, i);end.
Complexidade: A princípio o procedimento Build-Heap executa o procedimento heapfy para os elementos dos vetor que estão nas posições entre [n/2,1]. Portanto, a complexidade esperada da construção do heap é (n/2*log2 n). No entanto, a complexidade é (n).
HeapSort - Análise de Desempenho (3/3)
Procedimento HeapSortProc heapsort (A) begin build_heap(A); for i length[A] downto 2 do begin exchange(A[i] A[1]); heap_size[A] heap_size[A] –1; heapify(A,1); end end.
Complexidade Total do HeapSort: Etapas:
- Construção do Heap O(n)- Ordenação
a) Troca(raiz, final do segmento não-ordenado) O(1)
b) AjustaElemento(raiz) O(log n)Executa os passos (a) e (b) n -1 vezes (n-1). log n O(n log n)
Portanto: complexidade total é de O(n log n)
Estudo de Caso de Heap Fila de Prioridades – estrutura de dados para
manutenção de um conjunto com S elementos, cada um valor de chave, e que suporta as seguintes operações:
Insere_Heap(S,x): Insere o elemento x no conjunto S. O(log2n)
Máximo(S): Retorna o elemento de S com maior valor de chave. O(1)
Extrai_Max(S): Remove de S o elemento com o maior valor de chave e o retorna. O(log2n)
Procedimento Insere_Heap(S,x)1) Apontar para a próxima posição do S após o seu último
elemento (p);2) Verificar se p > 1 AND se a chave (key) que se
encontra no pai do nó apontado por p é menor do que a chave (x) a ser inserida em S. Caso as duas condições anteriores sejam verdadeiras, então key é inserida na posição p de S e p aponta agora para a antiga posição onde se encontrava a chave key. Repita este passo, até que pelo menos uma das duas condições for falsa.
3) Caso pelo menos uma das condições citadas no item 2 for falsa, então x é inserida em S na posição p
Exemplo de Insere_Heap (1/3) Vetor original: Inserir a chave número 11.
16 4 10 14 7 9 3 2 8 1
16
9 3
10
2 1
14 7
4
1
2 3
4 5 6 7
8 9 10 8
Vetor original
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
Vetor após Build-Heap
11
???
Exemplo de Insere_Heap (2/3)
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
Vetor após Build-Heap
p = 5 16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
Insere o valor da posição 5 do vetor na posição p do vetor
7
1111
16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4p aponta para a
próxima posição do vetor após o último elemento do vetor
p = 11
Exemplo de Insere_Heap (3/3)
p = 5 16
9 3
10
2 1
8 7
14
1
2 3
4 5 6 7
8 9 10 4
O valor no nodo pai do nodo apontado por p é menor que 11 (ou seja, o valor da chave a ser inserida) ? Não
7
11
p = 5 16
9 3
10
2 1
8 11
14
1
2 3
4 5 6 7
8 9 10 4 7
11
Então, insere a chave 11 na posição p do vetor.
O que temos então !?
Temos um build-heap
Procedimento Extrai_Max(S)
1)Primeiramente verifica se o conjunto S não está vazio.
2) Atribui o maior valor que está na raiz, ou seja, na 1ª posição do conjunto à max.
3) O último elemento de S é inserido na posição da raiz. Logo em seguida, decrementa-se S de uma unidade.
4) Aplicar o procedimento Heapfy a partir da 1ª posição de S, ou seja, Heapfy(S,1).
5) Retorna o valor atribuído à max.
Exemplo de Extrai_Max max = 16
7
11
Vetor na condição Build-Heap está vazio ? Não, então atribui o valor da raiz a max.
16
9 3
10
2 1
8 11
14
1
2 3
4 5 6 7
8 9 10 4
7
9 3
10
2 1
8 11
14
1
2 3
4 5 6 7
8 9 10 4
Inserido o valor do último elemento do vetor na raiz. Decrementado de uma unidade o vetor.
max = 16
Aplicado o procedimento Heapfy no vetor a partir da primeira posição.
14
9 3
10
2 1
8 7
11
1
2 3
4 5 6 7
8 9 10 4
max = 16