Você está na página 1de 59

Heaps e Árvores Binárias 1 / 59

Heaps e Árvores Binárias

Eduardo Camponogara

Departamento de Automação e Sistemas


Universidade Federal de Santa Catarina

6 de abril de 2009
Heaps e Árvores Binárias 2 / 59
Sumário

Introdução

Heapsort

Árvores Binárias
Heaps e Árvores Binárias 3 / 59
Introdução

Sumário

Introdução

Heapsort

Árvores Binárias
Heaps e Árvores Binárias 4 / 59
Introdução

Introdução

Heap
Heap Sort é algoritmo de ordenação
◮ Como o Merge Sort, Heap Sort ordena n números em tempo
Θ(n lg n)
◮ Ordena no local, necessitando apenas um número constante
de variáveis de armazenamento.
A estrutura de dados heap, além de permitir a implementação
do algoritmo Heap Sort, também pode ser utilizada como uma fila
de prioridades eficiente.
Heaps e Árvores Binárias 5 / 59
Heapsort

Sumário

Introdução

Heapsort

Árvores Binárias
Heaps e Árvores Binárias 6 / 59
Heapsort
Heaps

Heaps
Um heap (binário) é uma estrutura de dados que pode ser vista
como uma árvore binária completa.
1
16

2 3
14 10

4 5 6 7 1 2 3 4 5 6 7 8 9 10
8 7 9 3 16 14 10 8 7 9 3 2 4 1

8 9 10
2 4 1
Heaps e Árvores Binárias 7 / 59
Heapsort
Heaps

Heaps

Heaps
◮ Cada nó da árvore corresponde a um elemento do vetor que
amazena o valor do nó.
◮ A árvore é completa em todos os nı́veis com excessão do nı́vel
mais baixo, o qual é completado da esquerda para a direita.
Heaps e Árvores Binárias 8 / 59
Heapsort
Heaps

Heaps

Representação de Um Heap
Um vetor A que armazena um heap é um objeto com dois
atributos:
◮ length[A]: número de elementos do vetor
◮ heap size[A]: número de elementos do heap armazenados em
A.
Heaps e Árvores Binárias 9 / 59
Heapsort
Heaps

Heaps
Representação de Um Heap

◮ A raiz da árvore é A[1].


◮ Dado o ı́ndice i de um vértice, podemos calcular os seguintes
ı́ndices.

Parent(i)
return ⌊i/2⌋

Left Child(i)
return 2i

Right Child(i)
return 2i + 1
Heaps e Árvores Binárias 10 / 59
Heapsort
A Propriedade Heap

A Propriedade Heap

Propriedade Heap
Para que um vetor A seja heap, cada nó i, com excessão da raiz,
deve satisfazer a seguinte propriedade:

A[i] ≤ A[Parent(i)]

◮ O valor de cada nó é no máximo o valor do seu pai


◮ O maior elemento do heap está na raiz
◮ As subárvores a partir de qualquer nó possuem valores
menores ou iguais ao valor do nó
Heaps e Árvores Binárias 11 / 59
Heapsort
A Propriedade Heap

A Propriedade Heap

Altura da Árvore
◮ altura de um nó da árvore é o número de arestas no caminho
mais longo do nó até uma folha da árvore.
◮ altura da árvore é a altura do nó raiz.
◮ Uma vez que um heap induz uma árvore binária completa, sua
altura é Θ(lg n).
Heaps e Árvores Binárias 12 / 59
Heapsort
A Propriedade Heap

A Propriedade Heap

Mantendo a Propriedade Heap

◮ O procedimento Heapify é fundamental na manipulação de


heaps.
◮ A entrada é o vetor A e um ı́ndice do vetor.
◮ Quando é chamado, assume-se que as árvores com raiz em
Left Child(i) e Right Child(i) são heaps, todavia o elemento
A[i] pode ser menor do que seus filhos, desta forma violando a
propriedade heap
◮ O procedimento Heapify recupera a propriedade heap da
árvore com raiz em i.
Heaps e Árvores Binárias 13 / 59
Heapsort
A Propriedade Heap

A Propriedade Heap
Heapify

Heapify(A, i)
l ← Left Child(i)
r ← Right Child(i)
if l ≤ heap size[A] & A[l] > A[i]
largest ← l
else
largest ← i
if r ≤ heap size[A] & A[r ] > A[largest]
largest ← r
if largest 6= i
exchange A[i] ↔ A[largest]
Heapify(A, largest)
Heaps e Árvores Binárias 14 / 59
Heapsort
A Propriedade Heap

A propriedade heap

Exemplo
1 1
16 16
2 3 2 3
4 10 14 10

4 5 6 7 4 5 6 7
14 7 9 3 4 7 9 3
8 9 10 8 9 10
2 8 1 2 8 1
Heaps e Árvores Binárias 15 / 59
Heapsort
A Propriedade Heap

A propriedade heap
Exemplo
1
16
2 3
14 10
4 5 6 7
8 7 9 3
8 9 10
2 4 1

O tempo de execução da operação Heapify é precisamente a altura


da árvore enraizada no nó i. Portanto O(h) = O(lg n)
Heaps e Árvores Binárias 16 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

◮ Podemos utilizar o procedimento Heapify para converter um


vetor A[1, . . . , n], com n = length[A] em um heap.
◮ Como os elementos do subvetor A[(⌊n/2⌋ + 1), . . . , n] são
folhas da árvore, podemos iniciar o procedimento no nó ⌊n/2⌋
◮ Cada Heapify executa em O(lg n), portanto, o Build Heap
executa em tempo O(n lg n).

Build Heap(A)
heap size[A] ← length[A]
for j ← ⌊heap size[A]/2⌋ downto 1
Heapify (A, j)
Heaps e Árvores Binárias 17 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

Exemplo

A 4 1 3 2 16 9 10 14 8 7
1
1 4
4
2 3
2 3 1 3
1 3 ⇒
4 5 6 7
4 5 6 7 2 16 9 10
2 16 9 10
8 9 10
8 9 10 14 8 7
14 8 7
Heaps e Árvores Binárias 18 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

Exemplo
1 1
4 4
2 3 2 3
1 3 1 3

4 5 6 7 4 5 6 7
2 16 9 10 14 16 9 10
8 9 10 8 9 10
14 8 7 2 8 7
Heaps e Árvores Binárias 19 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

Exemplo
1 1
4 4
2 3 2 3
1 3 1 10

4 5 6 7 4 5 6 7
14 16 9 10 14 16 9 3
8 9 10 8 9 10
2 8 7 2 8 7
Heaps e Árvores Binárias 20 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

Exemplo
1 1
4 4
2 3 2 3
1 10 16 10

4 5 6 7 4 5 6 7
14 16 9 3 14 7 9 3
8 9 10 8 9 10
2 8 7 2 8 1
Heaps e Árvores Binárias 21 / 59
Heapsort
Construindo Um Heap

Construindo Um Heap

Exemplo
1 1
4 16
2 3 2 3
16 10 14 10

4 5 6 7 4 5 6 7
14 7 9 3 8 7 9 3
8 9 10 8 9 10
2 8 1 2 4 1
Heaps e Árvores Binárias 22 / 59
Heapsort
Algoritmo de Ordenação

Algoritmo de Ordenação

O algoritmo Heapsort

Heapsort(A)
Build Heap(A)
for i ← length[A] downto 2
exchange A[1] ↔ A[i]
heap size[A] ← heap size[A] − 1
Heapify(A, 1)

◮ O algoritmo Heapsort executa em tempo O(n lg n)


Heaps e Árvores Binárias 23 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

16 14

14 10 8 10

8 7 9 3 4 7 9 3

2 4 1 2 1 16
Heaps e Árvores Binárias 24 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

14 10

8 10 8 9

4 7 9 3 4 7 1 3

2 1 16 2 14 16
Heaps e Árvores Binárias 25 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

10 9

8 9 8 3

4 7 1 3 4 7 1 2

2 14 16 10 14 16
Heaps e Árvores Binárias 26 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

9 8

8 3 7 3

4 7 1 2 4 2 1 9

10 14 16 10 14 16
Heaps e Árvores Binárias 27 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

8 7

7 3 4 3

4 2 1 9 1 2 8 9

10 14 16 10 14 16
Heaps e Árvores Binárias 28 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

7 4

4 3 2 3

1 2 8 9 1 7 8 9

10 14 16 10 14 16
Heaps e Árvores Binárias 29 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

4 3

2 3 2 1

1 7 8 9 4 7 8 9

10 14 16 10 14 16
Heaps e Árvores Binárias 30 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

3 2

2 1 1 3

4 7 8 9 4 7 8 9

10 14 16 10 14 16
Heaps e Árvores Binárias 31 / 59
Heapsort
Algoritmo de Ordenação

Heapsort

Exemplo

2 1

1 3 2 3

4 7 8 9 4 7 8 9

10 14 16 10 14 16
Heaps e Árvores Binárias 32 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Fila de prioridades
◮ Uma fila de prioridades é uma estrutura de dados para
manter um conjunto dinâmico S de elementos, cada um com
um valor associado, chamado de chave.
◮ As operações são:
◮ Insert(S, x): insere um elemento em S
◮ Maximum(S): retorna o elemento de maior chave de S
◮ Extract Max(S): extrai o elemento de maior chave de S
◮ Uma aplicação é o escalonamento de tarefas em um
computador de memória compartilhada.
Heaps e Árvores Binárias 33 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Extrair o máximo

Heap Extract Max(A)


if heap size[A] < 1
error(”underflow”)
max ← A[1]
A[1] ← A[heap size[A]]
heap size[A] ← heap size[A] − 1
Heapify(A, 1)
return max

◮ O tempo de execução é O(lg n)


Heaps e Árvores Binárias 34 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Inserir novo elemento


1) Expandimos o tamanho do heap introduzindo o novo elemento
2) Navegamos através da árvore até que o elemento atinja a
posição correta para manter a propriedade heap.
Heaps e Árvores Binárias 35 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Inserir novo elemento

Heap Insert(A, key )


heap size[A] ← heap size[A] + 1
i ← heap size[A]
while i > 1 & A[Parent(i)] < key
A[i] ← A[Parent(i)]
i ← Parent(i)
A[i] ← key

◮ O procedimento executa em tempo O(lg n)


Heaps e Árvores Binárias 36 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Exemplo

16 16

14 10 14 10

8 7 9 3 8 7 9 3

2 4 1 2 4 1 15
Heaps e Árvores Binárias 37 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Exemplo

16 16

14 10 14 10

8 7 9 3 8 15 9 3

2 4 1 15 2 4 1 7
Heaps e Árvores Binárias 38 / 59
Heapsort
Fila de prioridades

Heap como uma fila de prioridades

Exemplo

16 16

14 10 15 10

8 15 9 3 8 14 9 3

2 4 1 7 2 4 1 7
Heaps e Árvores Binárias 39 / 59
Árvores Binárias

Sumário

Introdução

Heapsort

Árvores Binárias
Heaps e Árvores Binárias 40 / 59
Árvores Binárias

Árvores Binárias de Pesquisa

Introdução
◮ Árvores binárias de pesquisa são estruturas de dados que
suportam muitas das operações executadas sobre conjuntos
dinâmicos
◮ Operações: Search, Minimum, Predecessor , Insert e Delete
◮ As Operações levam tempo proporcional à altura da árvore.
◮ Para uma árvore binária completa de n nós, tais operações
levam Θ(lg n).
◮ Todavia, se a árvore é uma lista de nós, as operações podem
levar Θ(n) no pior caso.
Heaps e Árvores Binárias 41 / 59
Árvores Binárias

Árvores Binárias de Pesquisa

Introdução
◮ A altura de árvores binárias construı́das randomicamente
é O(lg n), o que garante que as operações levem Θ(lg n).
◮ Na prática, não podemos garantir que as árvores são
construı́das randomicamente.
◮ Entretanto, existem implementações de árvores binárias
balanceadas, que garantem uma altura O(lg n) para a árvore,
tais como Red-Black Trees, AVL Trees e B-Trees.
Heaps e Árvores Binárias 42 / 59
Árvores Binárias

Árvores Binárias de Pesquisa


O que é árvore binária de pesquisa?
Toda árvore binária que satisfaz a propriedade árvore-binária de
pesquisa:
◮ Seja x um vértice qualquer da árvore binária de pesquisa
◮ Se y é um nó da subárvore da esquerda, então key [y ] ≤ key [x]
◮ Se y é um nó da subárvore da direita, então key [y ] ≥ key [x]

≤ ≥
Heaps e Árvores Binárias 43 / 59
Árvores Binárias

Árvores Binárias de Pesquisa

Exemplos

2
5
3

3 7 7

5 8
2 5 8

5
Heaps e Árvores Binárias 44 / 59
Árvores Binárias
Inorder walk

Árvores Binárias de Pesquisa

Inorder tree walk


A propriedade árvore-binária de pesquisa nos permite imprimir
todas as chaves da árvore binária em ordem com um simples
algoritmo recursivo.

Inorder Walk(T , x)
if x 6= NIL
Inorder Walk( T , left[x] )
print(key [x])
Indorder Walk( T , right[x] )

A chamada Indorder Walk( T , root[T ] ) é executada em tempo


Θ(n), retornando para os exemplos anteriores 2, 3, 5, 5, 7, 8.
Heaps e Árvores Binárias 45 / 59
Árvores Binárias
Buscas

Árvores Binárias de Pesquisa

Busca em uma árvore


As operações:
◮ Search(T , k)
◮ Minimum(T )
◮ Maximum(T )
◮ Predecessor (T , x) e
◮ Sucessor (T , x)
são executadas em tempo O(h), onde h é a altura da árvore T .
Heaps e Árvores Binárias 46 / 59
Árvores Binárias
Buscas

Busca em uma árvore

Search
Dados um ponteiro para a raiz T e uma chave k, o procedimento
Search(T ,k) retorna um ponteiro para um objeto com a chave k se
um existe, ou NIL caso contrário.

Search(T , k)
if x = NIL or key [x] = k
return x
if k < key [x]
Search(left[x], k)
else
Search(right[x], k)
Heaps e Árvores Binárias 47 / 59
Árvores Binárias
Buscas

Busca em uma árvore


acements
Exemplo

15

6 18

3 7 17 20

2 4 13

A busca pela chave 13, segue o caminho 15 → 6 → 7 → 13.


Heaps e Árvores Binárias 48 / 59
Árvores Binárias
Mı́nimo e Máximo

Mı́nimo e Máximo

O elemento cuja chave é mı́nima pode ser encontrado ao ao


seguirmos a cadeia ”left child”a partir da raiz até que NIL seja
encontrado. Para o máximo, o precedimento é semelhante.

Mı́nimo Máximo

Minimum(x) Maximum(x)
while left[x] 6= NIL while right[x] 6= NIL
x ← left[x] x ← right[x]
return x return x
Heaps e Árvores Binárias 49 / 59
Árvores Binárias
Sucessor e Predecessor

Sucessor e Predecessor

◮ O sucessor de um nó x é o nó y com a menor chave key [y ]


que seja maior do que key [x].
◮ A estrutura da árvore binária nos permite encontrar o sucessor
de um nó x, sem fazer nenhuma comparação de chaves.
◮ Se a sub-árvore à direita de x é não-vazia, então o sucessor de
x é o elemento mı́nimo desta sub-árvore.
◮ Caso contrário, o sucessor de x é o ancestral mais próximo de
x cujo filho da esquerda é também um ancestral de x.
Heaps e Árvores Binárias 50 / 59
Árvores Binárias
Sucessor e Predecessor

Sucessor

Successor(x)
if right[x] 6= NIL
return Minimum(right[x])
y ← p[x]
while y 6= NIL & x = right[y ]
x ←y
y ← p[y ]
return y
Heaps e Árvores Binárias 51 / 59
Árvores Binárias
Sucessor e Predecessor

Sucessor
acements
Exemplo

15

6 18

3 7 17 20

2 4 13

◮ O sucessor de 13 é 15
Heaps e Árvores Binárias 52 / 59
Árvores Binárias
Inserção de Objetos

Inserção de Objetos
Insert
Insert (Continuation)
Insert(T , z)
y ← NIL p[z] ← y
x ← root[T ] if y = NIL
while x 6= NIL root[T ] ← z
y ←x else
if key [z] < key [x] if key [z] < key [y ]
x ← left[x] left[y ] ← z
else else
x ← right[x] right[y ] ← z
endif endif
endwile endif
Heaps e Árvores Binárias 53 / 59
Árvores Binárias
Inserção de Objetos

Inserção de Objetos

Exemplo
◮ Inserção de 13

12

5 18

2 9 15 19

13 17
Heaps e Árvores Binárias 54 / 59
Árvores Binárias
Deleção

Deleção

O procedimento de deleção de um nó z consiste em 3 casos.


a) Se z não tem filhos, modificar o pai de z, p[z], para que este
aponte para NIL.
b) Se z possui apenas um filho, fazemos o pai de z apontar para
o filho de z.
c) Se z possui dois filhos, colocamos no lugar de z o seu
sucessor, o que com certeza não possui filho à esquerda.
Heaps e Árvores Binárias 55 / 59
Árvores Binárias
Deleção

Deleção
Caso a: z não possui filhos

15 15

5 16 5 16

3 12 20 3 12 20

10 13 z 18 23 10 18 23

6 6

7 7
Heaps e Árvores Binárias 56 / 59
Árvores Binárias
Deleção

Deleção
Caso b: z possui um filho

15
15

5 20
5 16 z

3 12 20 3 12 18 23

10 13 18 23 10 13

6
6

7
7
Heaps e Árvores Binárias 57 / 59
Árvores Binárias
Deleção

Deleção

Caso c: z possui dois filhos

15
6 y 15
5 z 16
5 z 16
3 12 20
⇒ 3 12 20
10 13 18 23
10 13 18 23
y 6
7
7
Heaps e Árvores Binárias 58 / 59
Árvores Binárias
Deleção

Deleção

Caso c: z possui dois filhos

6 y 15 15

5 z 16 6 16

3 12 20 ⇒ 3 12 20

10 13 18 23 10 13 18 23

7 7
Heaps e Árvores Binárias 59 / 59
Árvores Binárias
Deleção

Heaps e Árvores Binárias

◮ Fim!
◮ Obrigado pela presença

Você também pode gostar