You are on page 1of 157

Estruturas de Dados

e
T ecnicas de Programac ao
Vers ao 1.12
Agosto de 2004
Cl audio L. Lucchesi
Tomasz Kowaltowski
INSTITUTO DE COMPUTAC

AO
UNIVERSIDADE ESTADUAL DE CAMPINAS
UNI CAMP
ii
Nenhuma parte destas notas pode ser reproduzida, qualquer que seja a forma
ou o meio, sem a permiss ao, por escrito, de ambos os autores.
Os autores concedem a permiss ao explcita para a utilizac ao e reproduc ao deste
material no contexto do ensino de disciplinas regulares dos cursos de graduac ao
sob a responsabilidade do Instituto de Computac ao da UNICAMP. Qualquer ou-
tra utilizac ao deste material e vedada sem a permiss ao, por escrito, de ambos os
autores.
c Copyright 19972004
Todos os direitos reservados por:
Cl audio L. Lucchesi e Tomasz Kowaltowski
Instituto de Computac ao
UNICAMP
Caixa Postal 6176
13083-970 Campinas, SP
http://www.ic.unicamp.br/{lucchesi,tomasz}
Pref acio
Este texto e o resultado da tentativa de reunir o material preparado pelos autores durante os v arios anos em
que t em ministrado as disciplinas sobre estruturas de dados, na UNICAMP e em v arias outras instituic oes.
Os captulos e sec oes que comp oem o texto est ao em est agios distintos de elaborac ao. Alguns t em apenas
seus ttulos enunciados, outros est ao bastante completos. Os autores esperam que, com o tempo, o texto
possa evoluir para um livro completo.
A preocupac ao principal do texto e com as estruturas de dados fundamentais e os algoritmos para a sua
manipulac ao, incluindo noc oes b asicas de eci encia. Os exemplos procuram utilizar o conceito de tipos
abstratos de dados, sempre que aplic avel. Entretanto, a metodologia de programac ao n ao e um assunto
aprofundado neste texto, j a que trata-se de programac ao em pequena escala (programming-in-the-small).
Apenas a ttulo de completude est a previsto um captulo nal sobre programac ao orientada a objetos.
Os autores decidiram utilizar nos exemplos a linguagem PASCAL, apesar da disseminac ao atual da
linguagem C e dos seus descendentes. A principal raz ao e did atica. Infelizmente, v arios conceitos de
programac ao que s ao razoavelmente simples e claros em PASCAL, s ao mais obscuros ou inexistentes em C.
Entre eles, podemos citar o conceito geral de tipos e os mecanismos de passagem de par ametros. N ao temos
d uvida que qualquer aluno de Computac ao que domine estes conceitos numa linguagem, possa aprender
facilmente qualquer outra linguagem de programac ao.
Durante os v arios anos em que foi acumulado este material, muitos colegas e alunos contriburam com
observac oes e sugest oes, e n ao seria possvel agradecer explicitamente a todos eles. Os autores gostariam
de destacar, entretanto, as contribuic oes do saudoso Claudinho Claudio Sergio Da R os de Carvalho cuja
morte prematura interrompeu o projeto de coautoria, numa primeira tentativa de organizar um texto como
este.
Cl audio L. Lucchesi e Tomasz Kowaltowski
Campinas, SP, Marco de 1997
iii
iv
Sum ario
Pref acio iii
1 Introduc ao 1
1.1 An alise de algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Tipos primitivos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Execuc ao de programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Tipos abstratos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2 Estruturas Seq uenciais 9
2.1 Representac ao linearizada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Formas especiais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Estruturas ligadas 13
3.1 Listas ligadas simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Listas circulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Listas duplamente ligadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4 Exemplo 1: manipulac ao de polin omios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.5 Exemplo 2: matrizes esparsas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.6 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4 Estruturas Lineares 25
4.1 Estruturas lineares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2 Pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.3 Exemplo de aplicac ao: manipulac ao de express oes . . . . . . . . . . . . . . . . . . . . . . 31
4.4 Filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5 Recurs ao 39
5.1 Recurs ao e repetic ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.2 Eliminac ao da recurs ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.3 Exemplo: an alise sint atica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
v
vi SUM

ARIO
6

Arvores bin arias 51
6.1 Denic oes, terminologia e propriedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.2 Implementac ao de arvores bin arias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.3 Percurso de arvores bin arias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.4 Exemplo de aplicac ao: arvores de busca . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.5 Exercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
7

Arvores gerais 75
7.1 Denic oes e terminologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2 Representac ao de arvores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
7.3 Percursos de orestas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
7.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
8

Arvores de busca 81
8.1

Arvores de altura balanceada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.2

Arvores de tipo B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
8.3

Arvores digitais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.4 Filas de prioridade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
9 Listas Gerais 107
9.1 Conceitos e implementac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.2 Exemplo: polin omios em m ultiplas vari aveis . . . . . . . . . . . . . . . . . . . . . . . . . 112
9.3 Exercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
10 Espalhamento 115
10.1 Conceitos b asicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.2 Func oes de espalhamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.3 Enderecamento aberto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.4 Encadeamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
10.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
11 Gerenciamento de Mem oria 121
11.1 Gerenciamento elementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
11.2 Contagem de refer encias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
11.3 Coleta de lixo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
11.4 Alocac ao de blocos de mem oria vari aveis . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
11.5 Alocac ao controlada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
11.6 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
12 Processamento de Cadeias e Textos 133
12.1 Representac ao de cadeias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
12.2 Noc oes de compactac ao de cadeias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
12.3 Busca de padr oes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
12.4 Noc oes de criptograa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
12.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
SUM

ARIO vii
13 Algoritmos de Ordenac ao 135
13.1 Ordenac ao por transposic ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
13.2 Ordenac ao por inserc ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
13.3 Ordenac ao por selec ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
13.4 Ordenac ao por intercalac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
13.5 Ordenac ao por distribuic ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
13.6 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
14 Programac ao Orientada a Objetos 143
14.1 Conceitos b asicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
14.2 Implementac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
14.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
viii SUM

ARIO
Lista de Figuras
1.1 Registros de ativac ao para o Prog. 1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Registros de ativac ao e heap para o Prog. 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Registros de ativac ao para o Prog. 1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1 Representac ao de uma matriz esparsa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.1 O problema de torres de Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.1

Arvore geneal ogica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.2

Arvore de descendentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.3 Exemplo de arvore bin aria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.4

Arvores bin arias distintas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.5 Representac ao de arvores bin arias com campos esq e dir . . . . . . . . . . . . . . . . . . . 56
6.6

Arvore bin aria com o campo pai. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.7

Arvore bin aria completa de altura 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.8

Arvore bin aria quase completa de altura 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.9

Arvore bin aria de busca contendo n umeros . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.10

Arvore bin aria de busca contendo nomes dos meses . . . . . . . . . . . . . . . . . . . . . . 69
7.1 Exemplo de arvore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
7.2 Uma oresta com tr es arvores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
7.3 Representac ao bin aria de uma oresta com tr es arvores . . . . . . . . . . . . . . . . . . . . 77
8.1 Exemplos de arvores AVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.2

Arvores de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
8.3 Funcionamento esquem atico de discos magn eticos . . . . . . . . . . . . . . . . . . . . . . 89
8.4 Exemplo de arvore B de ordem 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.5 Exemplo de arvore digital . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
8.6 Representac ao modicada de arvore digital . . . . . . . . . . . . . . . . . . . . . . . . . . 99
8.7 Exemplo de aut omato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.8 Exemplo de la de prioridade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.9 Operac ao de subida de um elemento no heap . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.10 Operac ao de descida de um elemento no heap . . . . . . . . . . . . . . . . . . . . . . . . . 102
9.1 Implementac ao compartilhada de listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
9.2 Implementac ao de listas com c opia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
ix
x LISTA DE FIGURAS
9.3 Representac ao dos polin omios em m ultiplas vari aveis . . . . . . . . . . . . . . . . . . . . . 113
10.1 Resultados das t ecnicas de enderecamento aberto . . . . . . . . . . . . . . . . . . . . . . . 118
11.1 Blocos em uso e disponvel (marcas de fronteira) . . . . . . . . . . . . . . . . . . . . . . . 128
11.2

Arvore para o sistema de blocos conjugados com m = 4 . . . . . . . . . . . . . . . . . . . 129
11.3 Blocos em uso e disponvel (sistema conjugado) . . . . . . . . . . . . . . . . . . . . . . . . 130
11.4

Arvore para blocos conjugados de Fibonacci com F
7
= 13 . . . . . . . . . . . . . . . . . . 131
Lista de Programas
1.1 Procedimento Ordena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Exemplo de programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Exemplo de programa com alocac ao de mem oria din amica . . . . . . . . . . . . . . . . . . 5
1.4 Exemplo de programa recursivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1 Rotinas para listas ligadas simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2 Rotinas para listas ligadas circulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Busca com sentinela numa lista circular . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4 Rotinas para listas circulares duplamente ligadas . . . . . . . . . . . . . . . . . . . . . . . 18
3.5 Func ao de soma de polin omios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.6 Recuperac ao de valor e atribuic ao em matriz esparsa . . . . . . . . . . . . . . . . . . . . . 24
4.1 Implementac ao ligada de pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.2 Implementac ao seq uencial de pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.3 Soluc ao do problema de balanceamento de par enteses . . . . . . . . . . . . . . . . . . . . . 30
4.4 Transformac ao da notac ao inxa para p os-xa . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.5 Implementac ao ligada de las . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.6 Implementac ao seq uencial de las . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.1 C alculo da func ao fatorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.2 C alculo da s erie de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.3 Soluc ao do problema de torres de Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.4 Exemplo de recurs ao m utua . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.5 Esboco de um procedimento recursivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.6 Esboco da transformac ao do procedimento recursivo do Prog. 5.5 . . . . . . . . . . . . . . . 44
5.7 Transformac ao inxa para p os-xa (vers ao incompleta) . . . . . . . . . . . . . . . . . . . . 46
5.8 Procedimeto Fator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.1 Procedimento de inserc ao ` a esquerda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.2 Procedimento de percurso recursivo em pr e-ordem . . . . . . . . . . . . . . . . . . . . . . 60
6.3 Procedimento de percurso em largura utilizando uma la . . . . . . . . . . . . . . . . . . . 60
6.4 Pr e-ordem com pilha explcita obtida por transformac ao . . . . . . . . . . . . . . . . . . . . 62
6.5 Pr e-ordem com pilha explcita an aloga ao percurso em largura . . . . . . . . . . . . . . . . 63
6.6 Pr e-ordem mais eciente com pilha explcita . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6.7 P os-ordem com pilha explcita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.8 Algoritmo de Deutsch, Schorr e Waite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.9 Busca e inserc ao numa arvore bin aria de busca . . . . . . . . . . . . . . . . . . . . . . . . 70
6.10 Pr e-ordem com pilha explcita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.11 Algoritmo de Lindstrom e Dwyer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
xi
xii LISTA DE PROGRAMAS
8.1 Esboco da rotina de busca e inserc ao em arvore AVL . . . . . . . . . . . . . . . . . . . . . 86
8.2 Rotina de busca e inserc ao em arvoreB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
8.3 Esboco da rotina auxiliar de busca e inserc ao em arvoreB . . . . . . . . . . . . . . . . . . . 92
8.4 Operac oes b asicas para heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.5 Rotinas de manipulac ao de heaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
9.1 Contagem de atomos de uma lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
9.2 Contagem de atomos de uma lista vers ao mais geral . . . . . . . . . . . . . . . . . . . . . 111
11.1 Gerenciamento elementar de mem oria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
11.2 Rotina de desalocac ao para contagem de refer encias . . . . . . . . . . . . . . . . . . . . . . 123
11.3 Algoritmo de marcac ao de uma estrutura . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
11.4 Coleta de n os marcados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
11.5 Rotinas de compactac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
13.1 Algoritmo bubblesort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
13.2 Algoritmo quicksort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
13.3 Ordenac ao por inserc ao simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
13.4 Ordenac ao por selec ao simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
13.5 Algoritmo heapsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
13.6 Ordenac ao iterativa por intercalac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
13.7 Ordenac ao recursiva por intercalac ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
14.1 Exemplo de utilizac ao de objetos (continua) . . . . . . . . . . . . . . . . . . . . . . . . . . 144
14.2 Exemplo de utilizac ao de objetos (continuac ao) . . . . . . . . . . . . . . . . . . . . . . . . 145
Captulo 1
Introduc ao
O objetivo deste Captulo e introduzir ou rever alguns conceitos que ser ao fundamentais para o resto do
texto. Est ao, entre eles, noc oes elementares de eci encia de algoritmos, implementac ao de tipos primitivos
na mem oria do computador, din amica de execuc ao de programas e tipos abstratos de dados.
1.1 An alise de algoritmos
Um dos aspectos mais importantes do desenvolvimento de algoritmos e a escolha correta da estrutura de
dados a ser utilizada para representar os objetos a serem manipulados. Tomemos o seguinte exemplo de
problema: achar o k- esimo elemento de uma seq u encia. Conforme a escolha da estrutura, h a duas maneiras
obvias de resolver o problema:
...
x := a[k]
...
...
p := a; i := 1;
while i=k do
begin
p := p.prox;
i := i+1
end;
x := p.info
...
O primeiro trecho o faz em tempo constante; no segundo, o n umero de operac oes e proporcional ao valor de
k.
Este tipo de an alise de eci encia de programas pode ser realizado de v arias maneiras. Consideremos os
exemplos:
...
x := a+b
...
...
for i:=1 to n do
x := a+b
...
...
for i:=1 to n do
for j:=1 to n
x := a+b
...
(a) (b) (c)
1
2 CAP

ITULO 1. INTRODUC

AO
Realizaremos dois tipos de an alise para os tr es exemplos. Na primeira, contaremos apenas o n umero de
atribuic oes explcitas executadas; na segunda, mais detalhada, contaremos as atribuic oes, as operac oes
aritm eticas e as comparac oes. Adotaremos uma hip otese simplicadora, supondo que cada uma destas
operac oes consome uma unidade de tempo. Supondo as implementac oes padr ao de comandos em PASCAL
e n 0, obteramos ent ao os seguintes resultados:
a b c
an alise simples 1 n n
2
an alise detalhada 2 5n + 2 5n
2
+ 5n + 2
(Lembre que o comando for inclui o comando de incremento de i equivalente ao comando i := i+1 includo
nesta contagem.)
Para valores crescentes de n, predominam os termos de ordem mais alta, assim que podemos adotar os
resultados 5n e 5n
2
para as duas ultimas entradas da tabela. Uma vez que n ao foram xados os valores da
unidade de tempo, podemos concluir que os resultados da tabela s ao, para valores sucientemente grandes
de n, aproximadamente proporcionais aos tempos de execuc ao. Neste caso, os resultados 1 e 2, n e 5n, bem
como n
2
e 5n
2
+ 5n + 2 s ao na realidade iguais, pois diferem apenas na constante de proporcionalidade.
Este fato e indicado atrav es de uma notac ao conveniente de acordo com a seguinte denic ao:
Dizemos que g(n) = O(f(n)) se existirem constantes c
0
e n
0
tais que g(n) < c
0
f(n) para todo
n > n
0
.
Esta denic ao traduz a id eia de que a func ao g, a partir de uma constante n
0
, e menor do que f multiplicada
por uma constante de proporcionalidade c
0
. Por exemplo:
c = O(1) para qualquer constante c
2 = O(1)
5n + 2 = O(n)
5n
2
+ 5n + 2 = O(n
2
)
n
k
= O(n
k+1
), k 0
(A ultima igualdade ilustra o fato de que, pela denic ao, a func ao g pode ter crescimento muito mais lento
do que f.)
Devido a estas considerac oes, as nossas an alises tender ao, emgeral, a ser apenas aproximadas, indicando
o comportamento em termos da func ao O. Deve-se tomar cuidado, entretanto, quanto ` a escolha correta das
operac oes a serem contadas.
A ttulo de exemplo faremos uma an alise de um procedimento mais completo indicado no Prog. 1.1. O
procedimento Ordena e um exemplo de algoritmo de ordenac ao por selec ao; este assunto ser a coberto de
maneira mais profunda no Cap. 13.
Numa an alise mais supercial, contaremos apenas os comandos de atribuic ao explcitos. N ao e difcil
perceber que a repetic ao controlada pela vari avel k e executada ni vezes, para cada valor de i. Dentro desta
1.2. TIPOS PRIMITIVOS DE DADOS 3
Programa 1.1 Procedimento Ordena
type vetor = array[1..nMax];
procedure Ordena(var v: vetor; n: integer);
var i,k,t: integer;
begin
for i:=1 to n1 do
begin
j := i;
for k:=j+1 to n do
if v[k]<v[j] then j := k;
t := v[i]; v[i] := v[j]; v[j] := t
end
end;
repetic ao, no pior caso, e executado sempre um comando de atribuic ao. Assim, o n umero de atribuic oes
numa execuc ao do corpo da repetic ao mais externa controlada pela vari avel i pode ser avaliado emni +4,
para os valores i = 1, 2, . . . , n 1. O total ser a dado ent ao pela somat oria:
n1

i=1
(n i + 4) =
n
2
2
+
7n
2
4
ou seja, o n umero de atribuic oes e da ordem de O(n
2
)(veja tamb em o Exerccio 4).
A tabela seguinte indica a import ancia deste tipo de an alise. Deve-se notar que algoritmos que t em
comportamento exponencial, isto e, O(2
n
), s ao in uteis sob o ponto de vista pr atico.
n log
2
n nlog
2
n n
2
n
3
2
n
1 0 0 1 1 2
2 1 2 4 8 4
4 2 8 16 64 16
8 3 24 64 512 256
16 4 64 256 4096 65536
32 5 160 1024 32768 4.294.967.296
1.2 Tipos primitivos de dados
Explicar: bits, bytes, notac ao hexadecimal, caracteres, inteiros, reais, booleanos, etc.
4 CAP

ITULO 1. INTRODUC

AO
1.3 Execuc ao de programas
Nesta sec ao apresentaremos alguns exemplos de layout da pilha de execuc ao de programas. Nestes exemplos
supusemos que um inteiro ocupa dois bytes, um caractere um byte e um endereco de vari avel ou um apon-
tador, quatro bytes. Na realidade, em todos eles foram omitidos alguns pormenores que n ao s ao relevantes
para esta discuss ao.
Programa 1.2 Exemplo de programa
program Exemplo1;
var
i: integer; c: char; v: array[1..5] of char;
procedure g(x: integer; var y: integer);
begin
y := x
end;
procedure f (var z: integer);
var y: integer; b: char;
begin
y := 17; g(y,z)
end;
begin
f (i)
end.
Figura 1.1 Registros de ativac ao para o Prog. 1.2
registro de ativaao
~
registro de ativaao
~
registro de ativaao
~
v c z y b x y
. . .
17 17
de f de g do programa
i
Neste primeiro exemplo, representamos os registros de ativac ao na da pilha durante a execuc ao do
1.3. EXECUC

AO DE PROGRAMAS 5
procedimento g.
Programa 1.3 Exemplo de programa com alocac ao de mem oria din amica
program Exemplo2;
type
Cadeia = array[1..5] of char; ApCadeia = Cadeia;
Reg = record nome: Cadeia; idade: integer end;
ApReg = Reg;
var apc: ApCadeia; apr: ApReg; api: integer;
procedure Aloca(var c: ApCadeia; var r: ApReg);
begin
new(api); api := 10; new(c); new(r);
end;
begin
Aloca(apc,apr); dispose(apc);
dispose(apr); dispose(api)
end.
Figura 1.2 Registros de ativac ao e heap para o Prog. 1.3
. . .
c r
. . .
apc apr api
10
Neste exemplo, a pilha indica o estado das vari aveis no m da execuc ao do procedimeto Aloca.
6 CAP

ITULO 1. INTRODUC

AO
Programa 1.4 Exemplo de programa recursivo
program Exemplo3;
var m: integer;
function fat(n: integer): integer;
begin
if n=0
then fat := 1
else fat := nfat(n1)
end;
begin
m := fat(4)
end;
Figura 1.3 Registros de ativac ao para o Prog. 1.4
m
. . .
n n n n n fat fat fat fat fat
4 3 2 1 0
Neste caso, est a indicado o instante em que h a o n umero m aximo de registros de ativac ao na pilha
(n = 0); fat indica uma pseudo-vari avel para guardar o resultado da func ao.
1.4 Tipos abstratos de dados
Usar um exemplo para explicar: n umero complexos?
1.5 Exerccios
1. An alise de algoritmos envolve, com freq u encia, o c alculo de somat orias de s eries. Prove por induc ao
os seguintes resultados:

i=1
i = n(n + 1)/2, n 1
1.5. EXERC

ICIOS 7

i=1
i
2
= n(n + 1)(2n + 1)/6, n 1

i=0
x
i
= (x
n+1
1)/(x 1), x = 1, n 1
2. Justique os resultados obtidos para a an alise detalhada dos tr es exemplos de trechos de programa na
Sec ao 1.1 (p ag. 2).
3. Determine quantas vezes e executado o comando de atribuic ao x := x + 1 no trecho de programa
abaixo, em func ao de n:
for i:=1 to n do
for j:=1 to i do
for k:=1 to j do
x := x+1
4. Faca uma an alise mais detalhada da eci encia do procedimento Ordena apresentado no Prog. 1.1.
8 CAP

ITULO 1. INTRODUC

AO
Captulo 2
Estruturas Seq uenciais
Este Captulo ser a dedicado ` a implementac ao seq uencial de estruturas, ou seja, ` aquela em que componentes
ocupam posic oes consecutivas de mem oria, possibilitando o c alculo direto dos seus enderecos.
2.1 Representac ao linearizada
Consideremos a declarac ao a: array[1..10] of integer. Supondo que cada inteiro ocupa dois bytes, obt em-
se a seguinte representac ao na mem oria:
. . . . . .
1 2 3 4 5 6 7 8 9 10

Se denotarmos por o endereco do primeiro byte do vetor, e claro que o endereco do i- esimo elemento pode
ser obtido por:
ender(a[i]) = + 2(i 1)
No caso geral de declarac ao b: array[p..u] of T vale a f ormula
ender(b[i]) = +|T|(i p)
onde |T| denota o tamanho do objeto do tipo T em bytes. Esta f ormula pode ser reescrita como
ender(b[i]) = +|T|i
onde = |T|p tem um valor constante, uma vez tenha sido alocado o espaco para o vetor b. Desta
maneira, percebe-se que o c alculo do endereco de um elemento do vetor envolve uma multiplicac ao e uma
soma.
O caso de vetores multidimensionais (ou matrizes) e semelhante. Em particular em PASCAL, bem como
algumas outras linguagens, a declarac ao c: array[p1..u1, p2..u2] of T e equivalente a c: array[p1..u1]
of array[p2..u2] of T. Desta maneira, utilizando o mesmo raciocnio acima, chega-se ` a f ormula
ender(c[i1, i2]) = +|T|(u2 p2 + 1)(i1 p1) +|T|(i2 p2)
9
10 CAP

ITULO 2. ESTRUTURAS SEQ



UENCIAIS
que tamb em pode ser reescrita como
ender(c[i1, i2]) = +t
1
i1 +t
2
i2
com
= |T|((u2 p2 + 1)p1 +p2)
t
1
= |T|(u2 p2 + 1)
t
2
= |T|
Conclui-se, desta maneira, que o c alculo do endereco envolve, neste caso, duas multiplicac oes e duas somas.
F ormulas semelhantes podemser desenvolvidas para os casos de dimens oes maiores veja o Exerccio 2.
2.2 Formas especiais
Existem aplicac oes em que aparecem matrizes que t em formas especiais. Um exemplo s ao as matrizes
triangulares, inferiores ou superiores. Dizemos que uma matriz e triangular inferior se ela e quadrada e
todos os seus elementos acima da diagonal principal s ao nulos, como no exemplo seguinte:

10 0 0 0 0 0
8 20 0 0 0 0
0 5 7 0 0 0
25 3 1 0 0 0
5 10 8 4 10 0
10 8 3 1 9 25

Uma maneira natural seria representar estas matrizes como exibido acima, com todos os elementos,
utilizando, neste caso, a declarac ao a: array[1..6, 1..6] of integer. Esta representac ao acarreta, entretanto,
umdesperdcio de (n1)n/2 elementos, onde n e a ordemda matriz. Al emdisto, algoritmos que manipulam
este tipo de matriz ter ao que processar tamb em os elementos nulos.
Uma alternativa e linearizar a matriz a e represent a-la por meio de um vetor ra, de n(n+1)/2 elementos
n ao necessariamente nulos. No caso do exemplo s ao 21 elementos: ra: array[1..21] of integer. Ser a
estabelecida ent ao uma correspond encia entre os elementos da matriz a e da sua representac ao linearizada
ra, que pode ser tanto por linha como por coluna. No caso de representac ao por linha, teremos:
a[1, 1] a[2, 1] a[2, 2] . . . a[6, 1] . . . a[6, 6]

ra[1] ra[2] ra[3] . . . ra[16] . . . ra[21]
O c alculo dos ndices correspondentes e bastante simples. Os trechos de programa abaixo comparam o
uso das duas implementac oes:
2.3. EXERC

ICIOS 11
var
a: array [1..6,1..6] of integer;
s,i,j: integer;
begin
...
a[4,3] := 75;
...
s := a[i,j]
...
end
var
ra: array [1..21] of integer;
s,i,j: integer;
function IndiceTriangular(i,j: integer): integer;
begin
if i<j
then IndiceTriangular := 0
else IndiceTriangular := (i1)i div 2 + j
end;
begin
...
ra[IndiceTriang(4,3)] := 75;
...
if ij
then s := ra[IndiceTriangular(i,j)]
else s := 0
...
end
O teste de ndices antes de chamar a func ao pode ser evitado, conforme mostra o Exerccio 3 no m deste
captulo.
Existem outros casos especiais de matrizes que podem ser tratados de maneira an aloga, como matrizes
sim etricas, diagonais e de banda (veja os Exerccios 6 a 8). Veremos tamb em, na Sec ao 3.5, uma maneira
bem diferente de implementar matrizes quando a grande maioria dos seus elementos e nula, sem que haja
uma regra que indique quais s ao esses elementos (matrizes esparsas).
2.3 Exerccios
1. Considere a seguinte declarac ao em PASCAL:
c: array[p1..u1, p2..u2] of T;
Explique porque, nesta linguagem, os elementos da matriz s ao obrigatoriamente alocados por linha,
os seja na seguinte ordem:
c[p1, p2] c[p1, p2 + 1] c[p1, p2 + 2] . . . c[p1, u2]
12 CAP

ITULO 2. ESTRUTURAS SEQ



UENCIAIS
c[p1 + 1, p2] c[p1 + 1, p2 + 1] c[p1 + 1, p2 + 2] . . . c[p1, u2]
. . . . . . . . . . . . . . .
c[u1, p2] c[u1, p2 + 1] c[u1, p2 + 2] . . . c[u1, u2]
2. Considere a seguinte forma de declarac ao em PASCAL de matriz n-dimensional:
d: array[p1..u1, p2..u2, ..., pn..un] of T
Estabeleca uma f ormula geral para calcular o endereco do elemento d[i1, i2, . . . , in]. Quantas
operac oes de soma e multiplicac ao s ao necess arias neste caso?
3. A implementac ao de matrizes triangulares sugerida na p ag. 11 exige um teste antes de cada chamada
da func ao IndiceTriangular. Mostre como modicar a representac ao para que o teste possa ser es-
condido dentro da pr opria func ao. Sugest ao: acrescente mais uma posic ao especial ao vetor de
representac ao ra, e preencha-o com um valor constante.
4. Escreva um procedimento que aceita duas matrizes triangulares inferiores e produz a sua soma,
tamb em triangular. O que acontece no caso da operac ao produto?
5. Sugira uma maneira eciente de implementar simultaneamente duas matrizes triangulares de mesma
ordem. Sugest ao: Coloque-as numa mesma matriz retangular de tamanho conveniente.
6. Uma matriz quadrada a e dita sim etrica se para todos os valores dos ndices tem-se a[i, j] =a[j, i].
Sugira uma maneira mais eciente de implement a-la do que a comum.
7. Uma matriz quadrada a e dita diagonal se para todos os valores distintos de i e j, tem-se a[i, j] = 0.
Sugira uma maneira mais eciente de implement a-la do que a comum.
8. Dizemos que uma matriz quadrada a e de banda (p, q) se a[i, j] = 0 para todos os valores de i e j
tais que i j > p ou j i > q. Note que uma matriz diagonal tem a banda (0, 0); uma matriz comum
tem a banda (n 1, n 1).
(a) esboce uma matriz quadrada 8 8, de banda (4, 3);
(b) sugira uma maneira mais eciente de implementar matrizes de banda do que as comuns, usando
a linearizac ao.
Captulo 3
Estruturas ligadas
Introduziremos neste Captulo as principais t ecnicas de construc ao de estruturas ligadas. Apresentaremos
tamb em dois exemplos tpicos de utilizac ao.
3.1 Listas ligadas simples
Uma lista ligada simples apontada por uma vari avel de programa p pode ser representada esquematicamente
por:
. . .
p
As declarac oes tpicas para estabelecer os tipos necess arios s ao:
type
ApRegLista = RegLista;
RegLista = record
info: T;
prox: ApRegLista
end;
Lista = ApRegLista;
onde T e o tipo da informac ao que se deseja guardar nos elementos da lista. Note que utilizamos dois
nomes Lista e ApRegLista para dois tipos aparentemente iguais. A intenc ao e frisar a diferenca entre o
primeiro, que e um tipo abstrato que est a sendo implementado, e o segundo que e um tipo auxiliar utilizado
na implementac ao. Neste caso particular (e muitos outros), estes tipos s ao equivalentes.
As operac oes b asicas de inserc ao e remoc ao de n os gen ericos na lista podem ser esquematizadas como
indicado a seguir:
13
14 CAP

ITULO 3. ESTRUTURAS LIGADAS


. . . . . .
p
Os procedimentos correspondentes podem ser vistos no Prog. 3.1.
Programa 3.1 Rotinas para listas ligadas simples
procedure InsereLista(p: Lista; x: T);
var q: ApRegLista;
begin
new(q);
with q do
begin info := x; prox := p.prox end;
p.prox := q
end;
procedure RemoveLista(p: Lista);
var q: ApRegLista;
begin
q := p.prox;
p.prox := q.prox;
dispose(q)
end;
A convenc ao dos procedimentos e que o par ametro p deve apontar para o n o que precede o n o a ser inserido
ou removido. Note-se, entretanto, que os procedimentos n ao funcionam para o caso em que deseja-se fazer
a operac ao no incio da lista. Este problema sugere a introduc ao de um primeiro n o ctcio na lista, deno-
minado n o-cabeca. O campo de informac ao deste n o n ao ser a utilizado para guardar os elementos da lista;
em algumas aplicac oes poder a ser usado com outra nalidade como veremos mais adiante. Uma lista com
n o-cabeca apontada por uma vari avel p pode ser representada esquematicamente como:
. . .
p
No caso de lista vazia, haver a apenas o n o cabeca:
p
Desta maneira, os procedimentos indicados funcionam mesmo quando se trata do primeiro n o da lista
neste caso o par ametro p deve apontar para o n o-cabeca.
3.2. LISTAS CIRCULARES 15
3.2 Listas circulares
Em algumas aplicac oes e conveniente utilizar listas circulares como esbocado a seguir:
. . .
p
As operac oes de inserc ao e de remoc ao podem ser programadas como indicado no Prog. 3.2
Programa 3.2 Rotinas para listas ligadas circulares
procedure InsereCircular(var p: Lista; x: T);
var q: ApRegLista;
begin
new(q);
with q do
begin
info := x;
if p=nil
then begin prox := q; p := q end
else begin
prox := p.prox;
p.prox := q
end
end
end;
procedure RemoveCircular(var p: Lista);
var q: ApRegLista;
begin
q := p.prox;
if q=p
then p := nil
else p.prox := q.prox;
dispose(q)
end;
Estes procedimentos funcionam em qualquer caso, adotando-se o valor nil para a lista vazia. Esta convenc ao
n ao e muito coerente pois nil n ao satisfaz a denic ao de lista circular. Este fato est a reetido numa certa
complicac ao aparente nos procedimentos. Uma maneira de simplicar a convenc ao e introduzir, tamb em
neste caso, um n o-cabeca (est a indicada tamb em uma lista circular vazia):
16 CAP

ITULO 3. ESTRUTURAS LIGADAS


p
. . .
p
p
Uma vez que esta lista nunca ca de fato vazia, podem ser usados os mesmos procedimentos de inserc ao e
remoc ao indicados na sec ao anterior no Prog. 3.1.
Uma vantagem adicional de haver n o-cabeca e a simplicac ao de alguns algoritmos. Por exemplo,
um procedimento de busca numa lista circular poderia utilizar o campo de informac ao do n o-cabeca como
sentinela conforme demonstrado no Prog. 3.3. Supusemos neste caso que o par ametro p aponta para o n o-
cabeca e que o procedimento devolve o apontador para o primeiro n o que cont em o dado x; caso ele n ao
exista, devolve nil. Note que o uso de sentinela evita testes de m de lista dentro da repetic ao.
Programa 3.3 Busca com sentinela numa lista circular
function BuscaCircular(p: Lista; x: T): ApRegLista;
var q: ApRegLista;
begin
p.info := x; q := p;
repeat
q := q.prox
until q.info=x;
if q=p
then BuscaCircular := nil
else BuscaCircular := q
end;
3.3 Listas duplamente ligadas
As listas ligadas, tanto simples como circulares, apresentam alguns problemas. Por exemplo, dado o apon-
tador para um n o, e difcil remov e-lo da lista; no caso da lista simples, n ao se conhece o seu predecessor, no
caso circular ele pode ser encontrado mas ao custo proporcional ao n umero de n os na lista (veja, entretanto,
o Exerccio 1). Uma alternativa e a utilizac ao de listas duplamente ligadas. Tamb em neste caso podemos
3.4. EXEMPLO 1: MANIPULAC

AO DE POLIN

OMIOS 17
tornar as listas circulares e incluir um n o-cabeca, como ilustrado na gura seguinte:
p
. . .
. . .
p
As declarac oes tpicas para implementar estas listas seriam:
type
ApRegListaDupla = RegListaDupla;
RegListaDupla = record
info: T;
esq,dir: ApRegListaDupla
end;
ListaDupla = ApRegListaDupla;
As operac oes de inserc ao e de remoc ao nestas listas s ao ligeiramente mais complicadas, mas permitem,
por exemplo, a remoc ao do pr oprio n o passado como argumento, como indicado no Prog 3.4.
3.4 Exemplo 1: manipulac ao de polin omios
O problema de manipulac ao de polin omios e um bom exemplo de problema em que e interessante utilizar
as t ecnicas ligadas apresentadas nas sec oes anteriores. Um polin omio de grau n 0 pode ser denotado por:
P(x) = a
n
x
n
+a
n1
x
n1
+. . . +a
1
x
1
+a
0
x
0
onde a
n
= 0, exceto possivelmente no caso n = 0.
Uma primeira alternativa natural para representar polin omios de grau m aximo grauMax seria atrav es de
um vetor do tipo Polinomio conforme as declarac oes:
18 CAP

ITULO 3. ESTRUTURAS LIGADAS


Programa 3.4 Rotinas para listas circulares duplamente ligadas
procedure InsereDuplaDireita(p: ListaDupla; x: T);
var q: ApRegListaDupla;
begin
new(q);
with q do
begin
dir := p.dir; esq := p;
p.dir.esq := q; p.dir := q;
info := x;
end;
end;
procedure RemoveDupla(p: ListaDupla);
begin
p.esq.dir := p.dir;
p.dir.esq := p.esq;
dispose(p)
end;
type
Termo = record
coef : real;
expo: integer
end;
Polinomio = array [0..grauMax] of Termo;
Com esta representac ao, a implementac ao de operac oes como soma, produto e outros sobre polin omios
e bastante simples. Um primeiro problema desta representac ao e que ela exige um limite a priori para o
grau m aximo do polin omio. Isto se deve ao fato de que algumas linguagens de programac ao, como PAS-
CAL, n ao permitem que vetores tenham seus limites calculados dinamicamente durante a execuc ao. Um
outro problema e a possvel ineci encia caso o grau do polin omio seja alto, mas poucos dos seus termos
sejam n ao nulos. Neste caso e mais conveniente utilizar a representac ao ligada. Adotaremos listas circu-
lares com n o-cabeca, a m de utilizar a t ecnica de sentinelas. A gura a seguir representa os polin omios:
P
1
(x) = 5x
20
3x
5
+ 7 e P
2
(x) = 0.
p1
p2
1 5 20 3 5 7 0
1
Supusemos, nesta implementac ao, que cada n o representa um termo com coeciente n ao nulo. Os
termos est ao em ordem decrescente dos expoentes; o n o-cabeca tem expoente 1 que ser a conveniente para
implementar as operac oes que manipulam os polin omios. As declarac oes para esta estrutura seriam:
3.5. EXEMPLO 2: MATRIZES ESPARSAS 19
type
ApTermo = Termo;
Termo = record
coef : real;
expo: integer;
prox: ApTermo;
end;
Polinomio = ApTermo;
A ttulo de exemplo, mostraremos a construc ao da rotina que produz a soma de dois polin omios. Ela
percorrer a simultaneamente as duas listas que representam os polin omios dados, somando os termos com
expoentes iguais e copiando aqueles que n ao t emcorrespondente no outro. Agura a seguir indica a situac ao
gen erica encontrada durante o ciclo repetitivo principal da func ao:
p
q
r
...
...
pp
qq
rr
...
...
...
Nesta gura, as vari aveis pp e qq cont em apontadores para os pr oximos termos dos polin omios dados p
e q cujos expoentes ser ao comparados; rr aponta para ultimo termo inserido no resultado r. A rotina est a
apresentada no Prog. 3.5. Ela precisa ser completada com procedimentos convenientes: CriaPolinomioNulo,
InsereTermo e AvancaTermo veja o Exerccio 2. Note-se a utilizac ao de sentinela como o ultimo termo de
cada polin omio, evitando um tratamento especial para o m de cada uma das listas.
3.5 Exemplo 2: matrizes esparsas
Um outro exemplo cl assico de utilizac ao de t ecnicas ligadas vistas nas sec oes anteriores deste captulo e a
representac ao de matrizes esparsas. Dizemos que uma matriz e esparsa se apenas uma pequena frac ao dos
seus elementos e diferente de zero, sem que haja uma regra simples para determinar os elementos possi-
velmente n ao nulos. Este tipo de matrizes e comum em aplicac oes num ericas onde a frac ao de elementos
n ao nulos pode ser da ordem de 1 a 5%. Nestes casos, uma representac ao que evite a inclus ao de elementos
nulos pode economizar espaco e tempo de c alculo, pois os elementos nulos n ao ter ao que ser processados.
Uma maneira de implementar matrizes esparsas foi sugerida por Knuth [?], e esta apresentac ao est a
baseada nela. Consideremos o seguinte exemplo de matriz:
20 CAP

ITULO 3. ESTRUTURAS LIGADAS


Programa 3.5 Func ao de soma de polin omios
procedure SomaPolinomios(p,q: Polinomio; var r: Polinomio);
var pp, qq, rr: ApTermo; ep, eq: integer; cr: real;
begin
CriaPolinomioNulo(r);
pp := p.prox; qq := q.prox; rr := r;
repeat
ep := pp.expo; eq := qq.expo;
if ep>eq
then begin
InsereTermo(pp.coef ,ep,rr);
AvancaTermo(rr); AvancaTermo(pp);
end
else if ep<eq
then begin
InsereTermo(qq.coef ,eq,rr);
AvancaTermo(rr); AvancaTermo(qq)
end
else if ep=1
then begin
cr := pp.coef +qq.coef ;
if cr=0.0
then begin InsereTermo(cr,ep,rr); AvancaTermo(rr) end;
AvancaTermo(pp); AvancaTermo(qq)
end
until (ep=1) and (eq=1);
rr.prox := r
end;

50 0 0 0
10 0 20 0
0 0 0 0
30 0 60 5

A sua representac ao poderia ser aquela indicada na Fig. 3.1.


Note-se que nesta representac ao cada n o indica um termo n ao nulo da matriz e pertence a duas listas:
uma correspondente ` a sua linha (apontadores horizontais) e outra ` a sua coluna (apontadores verticais). Cada
lista e organizada como uma lista ligada circular com n o cabeca, com os termos em ordem de colunas (nas
listas das linhas) ou em ordem de linhas (nas listas das colunas). Os valores de sentinelas para os campos
das linhas ou colunas s ao 1 (sup oe-se que os ndices da matriz s ao de 1 a n). Os pr oprios n os-cabeca das
3.5. EXEMPLO 2: MATRIZES ESPARSAS 21
Figura 3.1 Representac ao de uma matriz esparsa
1 1 1 1 1 1
1
1
1
1 3
1 1
2 2
1 4 4 3 4 4
3
2
1
4
3
2
1
1
4
50
10 20
30 60 5
linhas e das colunas constituem listas ligadas circulares, com um n o-cabeca comum; um apontador para este
n o representar a a matriz inteira.
Note-se que esta e uma representac ao geral, sim etrica em relac ao ` as linhas e ` as colunas. Ela poderia ser
simplicada para uma aplicac ao dada, utilizando por exemplo apenas as listas das linhas. Note-se tamb em
que a matriz n ao precisa ser quadrada.
As seguintes declarac oes podem ser utilizadas para implementar esta representac ao:
type
ApRegEsparsa = RegEsparsa;
RegEsparsa = record
linha, coluna: integer;
valor: real;
direita, abaixo: ApRegEsparsa
end;
Matriz = ApRegEsparsa;
22 CAP

ITULO 3. ESTRUTURAS LIGADAS


Supondo que tenhamos uma matriz quadrada de ordem n, com r elementos n ao nulos, a representac ao
utilizar a 2n + r + 1 n os ao inv es de n
2
posic oes de n umero reais.

E claro que cada n o ocupar a muito mais
bytes do que um real, mas poder a haver uma economia apreci avel de mem oria se o valor de r for realmente
muito menor que n
2
. Analogamente, para certas operac oes com matrizes poder a haver economia de tempo,
pois os elementos nulos n ao ser ao processados explicitamente.
A ttulo de exemplo, o Prog. 3.6 mostra as rotinas b asicas de atribuic ao e de recuperac ao de um valor
de uma matriz esparsa. Note que para completar estas rotinas falta elaborar os procedimentos InsereMatriz
e RemoveMatriz. Estes procedimentos s ao semelhantes ` aqueles indicados no Prog. 3.1 para listas ligadas,
mas agora a operac ao e realizada em duas listas, sendo fornecidos os predecessores do n o em cada lista.
Veja tamb em Exerccios 4 a 7.
3.6 Exerccios
1. Explique o funcionamento do procedimento RemoveLista:
procedure RemoveLista(p: Lista);
var q: ApRegLista;
begin
q := p.prox;
p := q;
dispose(q)
end;
Quais s ao as condic oes em que este procedimento pode ser utilizado?
2. Complete a declarac ao do procedimento SomaPolinomios do Prog. 3.5 com os procedimentos auxili-
ares.
3. Escreva os procedimentos que implementam as operac oes de subtrac ao, multiplicac ao e divis ao de
polin omios, an alogos ao procedimento de soma indicado no Prog. 3.5.
4. Escreva as rotinas que faltam no Prog. 3.6.
5. Note que na representac ao de matrizes esparsas indicada na Fig. 3.1 est ao includos tamb em os n os-
cabeca das linhas e das colunas vazias, como por exemplo a linha 3. Estes n os poderiamser eliminados
` as custas de alguma complicac ao adicional nos procedimentos que manipulam as matrizes. Refaca as
rotinas indicadas no Prog. 3.6 para vericar este fato.
6. Supondo a representac ao de matrizes esparsas ilustrada na Fig. 3.1, escreva as seguintes rotinas:
procedure InicializaMatriz(var a: Matriz; m,n: integer);
Este procedimento cria uma nova matriz a, com m linhas e n colunas, com todos os elementos
iguais a zero.
procedure LiberaMatriz(var a: Matriz);
Libera toda a mem oria din amica utilizada pela matriz a.
3.6. EXERC

ICIOS 23
procedure SomaMatrizes(var a,b,c: Matriz);
Soma as matrizes a e b, deixando o resultado em c. Sup oe que as matrizes s ao compatveis
quanto ao n umero de linhas e de colunas.
procedure MultiplicaMatrizes(var a,b,c: Matriz);
Multiplica as matrizes a e b, deixando o resultado em c. Sup oe que as matrizes s ao compatveis
para esta operac ao.
7. Escreva um programa que testa as rotinas desenvolvidas no exerccio anterior. Sugest ao: Estabeleca
uma convenc ao para a entrada de dados e escreva as rotinas de entrada e sada convenientes.
24 CAP

ITULO 3. ESTRUTURAS LIGADAS


Programa 3.6 Recuperac ao de valor e atribuic ao em matriz esparsa
function ValorMatriz(var a: Matriz; i,j: integer): real;
var p: ApRegEsparsa; k: integer;
begin
p := a;
for k:=1 to i do p := p.abaixo;
repeat
p := p.direita
until (p.colunaj) or (p.coluna=1);
if j=p.coluna
then ValorMatriz := 0.0
else ValorMatriz := p.valor
end;
procedure AtribuiMatriz(var a: Matriz; i,j: integer; x: real);
var p,q,pp,qq: ApRegEsparsa; k: integer;
begin
p := a; q := a;
for k:=1 to i do p := p.abaixo;
for k:=1 to j do q := q.direita;
repeat
pp := p; p := p.direita
until (p.colunaj) or (p.coluna=1);
repeat
qq := q; q := q.abaixo
until (q.linhai) or (q.linha=1);
if p.coluna=j
then if x=0.0
then p.valor := x
else RemoveMatriz(a,pp,qq)
else if x=0.0 then InsereMatriz(a,i,j,x)
end; { AtribuiMatriz }
Captulo 4
Estruturas Lineares
Exploraremos neste Captulo o conceito abstrato de listas, ou seja seq u encias ordenadas de valores e suas
operac oes. Veremos tamb em algumas estruturas mais restritas, como pilhas e las, de fundamental im-
port ancia em Computac ao.
4.1 Estruturas lineares
Muitas aplicac oes envolvem representac ao e manipulac ao de seq u encias ordenadas de objetos
x
1
, x
2
, . . . , x
n
.
Conforme visto nos captulos anteriores, podemos adotar duas representac oes naturais para estas colec oes:
seq uencial (vetores) ou ligada. A escolha depender a das caractersticas dos objetos e das operac oes ` as quais
dever ao ser submetidas as seq u encias. Entre as v arias operac oes possveis sobre seq u encias, podemos citar:
selecionar e modicar o k- esimo elemento;
inserir um novo elemento entre as posic oes k e k + 1;
remover o k- esimo elemento;
concatenar duas seq u encias;
desdobrar uma seq u encia;
copiar uma seq u encia;
determinar o tamanho de uma seq u encia;
buscar um elemento que satisfaz uma propriedade;
ordenar uma seq u encia;
aplicar um procedimento a todos os elementos de uma seq u encia;
. . .
25
26 CAP

ITULO 4. ESTRUTURAS LINEARES

E f acil perceber, por exemplo, que a operac ao de inserc ao ou de remoc ao numa seq u encia e mais compli-
cada no caso de representac ao seq uencial; por outro lado, com esta representac ao, e mais simples e eciente
a selec ao do k- esimo elemento da seq u encia. Conclumos que, em qualquer aplicac ao, devemos estudar,
em primeiro lugar, as operac oes que ser ao realizadas sobre os objetos. Conforme veremos nas sec oes se-
guintes, muitas vezes poderemos adotar representac oes alternativas, sendo que quase sempre haver a um
compromisso entre a eci encia, mem oria utilizada, generalidade, facilidade de implementac ao, etc.
As sec oes seguintes ser ao dedicadas a listas especiais em que e possvel executar apenas algumas das
operac oes indicadas.
4.2 Pilhas
Consideremos o seguinte problema: dada uma seq u encia constituda de caracteres (, ), [ e ], de-
cidir se estes par enteses est ao corretamente balanceados. N ao deniremos de maneira exata o que e uma
seq u encia balanceada de par enteses, mas daremos alguns exemplos (veja, entretanto, o Exercicio 1):
Correto Incorreto
(
() )
[()] [)
[]()[()[]] ()()[
((([[[]]]))) )(
(O smbolo denota a seq u encia vazia.)
Uma primeira id eia para resolver o problema seria supor que a seq u encia e representada como um vetor
de n caracteres, e que o procedimento percorre o vetor apagando dois caracteres consecutivos que se
balanceiam. Caso a seq u encia seja balanceada, o resultado nal deve ser a cadeia vazia. N ao e difcil
vericar que o n umero de operac oes para esta soluc ao seria, no pior caso, da ordem de O(n
2
). Uma outra
id eia e utilizar uma estrutura de dados especial, denominada pilha.
1
Ser a um caso particular de lista linear,
em que as operac oes de inserc ao e de remoc ao podem ser feitas somente numa unica extremidade da lista.
No caso do nosso problema, o procedimento dever a percorrer a seq u encia de caracteres dada da esquerda
para a direita. Os caracteres (e [ ser ao inseridos na pilha. No caso dos caracteres )e ], ser a vericado
se o caractere que est a na extremidade da pilha e do mesmo tipo que o que est a sendo processado. No caso
positivo, ele ser a removido e o procedimento continua. No caso negativo, a seq u encia n ao era balanceada.
No m, a seq u encia ser a considerada correta se n ao h a mais smbolos a processar e a pilha est a vazia.
Ilustramos a seguir os passos do procedimento para a seq u encia ([([][()])]):
1
Esta pilha e semelhante ` a pilha de execuc ao vista na Sec ao 1.3.
4.2. PILHAS 27
Pilha Resto da seq u encia
Vazia ([([][()])])
( [([][()])])
([ ([][()])])
([( [][()])])
([([ ][()])])
([( [()])])
([([ ()])])
([([( )])])
([([ ])])
([( )])
([ ])
( )
Vazia
De uma maneira geral, diremos que a pilha e uma estrutura linear cujas extremidades ser ao denominadas
fundo e topo. As operac oes de inserc ao (empilhamento) e remoc ao (desempilhamento) podem ser realizadas
somente pelo topo da pilha. A gura seguinte d a uma id eia esquem atica da estrutura:
.
.
.
Desempilha Empilha
topo
fundo
Como em muitos outros contextos, podemos implementar uma pilha utilizando tanto a representac ao
seq uencial (um vetor) quanto a ligada (uma lista). A escolha depender a muito da aplicac ao. Indicamos nos
Progs. 4.1 e 4.2 as declarac oes que implementam as duas opc oes. Adotaremos o ponto de vista de um tipo
abstrato de dados, ou seja, um programa poder a utilizar qualquer uma das implementac oes contanto que as
operac oes sobre a pilha sejam realizadas sempre atrav es dos procedimentos e func oes indicados. Sup oe-se
que existe uma rotina TrataErro a ser executada quando acontece um imprevisto. Note-se tamb em que foi
utilizada sistematicamente a passagem por vari avel para par ametros do tipo Pilha, para evitar, no caso da
implementac ao seq uencial, a c opia do vetor inteiro.
28 CAP

ITULO 4. ESTRUTURAS LINEARES


Programa 4.1 Implementac ao ligada de pilhas
type
ApRegPilha = RegPilha;
RegPilha = record
info: T;
prox: ApRegPilha
end;
Pilha = ApRegPilha;
procedure InicializaPilha(var p: Pilha);
begin
p := nil
end;
function PilhaVazia(var p: Pilha): boolean;
begin
PilhaVazia := p=nil
end;
procedure LiberaPilha(var p: Pilha);
var q: ApRegPilha;
begin
while p=nil do
begin
q := p; p := p.prox; dispose(q)
end
end;
procedure Empilha(var p: Pilha; x: T);
var q: ApRegPilha;
begin
new(q);
with q do
begin
info := x; prox := p; p := q
end
end;
procedure Desempilha(var p: Pilha; var x: T);
var q: ApRegPilha;
begin
if p=nil then TrataErro;
q := p;
with q do
begin x := info; p := prox end
dispose(q)
end;
4.2. PILHAS 29
Programa 4.2 Implementac ao seq uencial de pilhas
type
Pilha = record
topo: 0..TamMax;
elemen: array [1..TamMax] of T
end;
procedure InicializaPilha(var p: Pilha);
begin
p.topo := 0
end;
function PilhaVazia(var p: Pilha): boolean;
begin
PilhaVazia := p.topo=0
end;
procedure LiberaPilha(var p: Pilha);
begin
{ nada }
end;
procedure Empilha(var p: Pilha; x: T);
begin
with p do
if topo=TamMax
then TrataErro
else begin
topo := topo+1;
elemen[topo] := x
end
end;
procedure Desempilha(var p: Pilha; var x: T);
begin
with p do
if topo= 0
then TrataErro
else begin
x := elemen[topo];
topo := topo1
end
end;
A ttulo de exemplo, mostramos no Prog. 4.3 a implementac ao da func ao que determina se uma cadeia
de caracteres representa uma seq u encia balanceada de par enteses, conforme exposto no incio desta sec ao.
Suporemos que a cadeia e representada por um vetor de caracteres e que a informac ao contida nos elementos
da pilha e do tipo char. Adotaremos tamb em a convenc ao de que a cadeia termina com o caractere especial
#. Note-se que a soluc ao n ao depende da opc ao utilizada para implementar a pilha, que foi programada
seguindo a id eia de tipo abstrato de dados. (Veja tamb em o Exerccio 5.6.)
30 CAP

ITULO 4. ESTRUTURAS LINEARES


Programa 4.3 Soluc ao do problema de balanceamento de par enteses
type
Cadeia = array [1..ComprMax] of char;
...
function Balanceada(var c: Cadeia): boolean;
var
p: Pilha; t: char; i: 0..ComprMax;
resultado, continua: boolean;
begin
InicializaPilha(p); i := 1;
resultado := false; continua := true;
while continua do
begin
case c[i] of

: begin
resultado := PilhaVazia(p);
continua := false
end;

: Empilha(p,c[i]);

: if PilhaVazia
then continua := false
else begin
Desempilha(p,t);
if t=

then continua := false


end;

: if PilhaVazia
then continua := false
else begin
Desempilha(p,t);
if t=

then continua := false


end;
end;
i := i+1
end
LiberaPilha(p);
Balanceada := resultado
end;
4.3. EXEMPLO DE APLICAC

AO: MANIPULAC

AO DE EXPRESS

OES 31
4.3 Exemplo de aplicac ao: manipulac ao de express oes
Express oes aparecem em linguagens de programac ao como PASCAL, ou ent ao em sistemas que realizam
manipulac ao simb olica.

E comum nestes casos adotar-se representrac oes alternativas para express oes, dife-
rentes daquelas usadas normalmente. Duas alternativas bastante comuns s ao a notac ao p os-xa e a notac ao
pr e-xa.
2
Simplicaremos a nossa discuss ao supondo que todos os operadores usados nas express oes s ao di adicos,
ou seja, requerem dois operandos. Em notac ao comum, chamada tamb em de notac ao inxa, o operador ca
entre os dois operandos. Como os pr oprios nomes indicam, em notac ao p os-xa o operador segue os dois
operandos enquanto que em notac ao pr e-xa o operador precede os dois operandos. Consideremos alguns
exemplos das tr es notac oes:
inxa p os-xa pr e-xa
a a a
a +b ab+ +ab
a +b c abc + +a bc
(a +b) c ab +c +abc
Deve-se notar que as notac oes pr e-xa e p os-xa n ao necessitam de par enteses. A pr opria forma da
express ao indica a ordem das operac oes como ilustrado pelos exemplos. Em notac ao inxa, utilizamos, por
convenc ao, as prioridades dos operadores e a sua associatividade ` a esquerda ou ` a direita. Quando desejamos
um resultado que e contr ario a estas convenc oes, utilizamos os par enteses.
Um problema de interesse obvio e o de transformac ao entre estas notac oes. Consideremos o caso de
transformac ao da notac ao inxa para a p os-xa, e tomemos um exemplo um pouco mais complexo:
a b
*
c d
^
*
f /
+ g h
*
e
a +c d
^ f
g
*
h
/ * b *
e
onde a b denota a
b
. Nota-se que os nomes das vari aveis s ao copiados da entrada inxa para a sada
p os-xa na mesma ordem. Entretanto, os operadores parecem esperar a chegada de um outro operador,
para que seja tomada a decis ao qual o operador seguinte que vai para a sada. N ao e difcil perceber que
esta decis ao est a baseada nas prioridades dos operadores e que os operadores que s ao lembrados seguem
uma disciplina de pilha, esperando at e que apareca na entrada um de prioridade menor ou igual. Podemos
imaginar, portanto, um algoritmo utilizando uma pilha auxiliar que faz a transformac ao. Os passos deste
algoritmo para o exemplo mostrado est ao indicados a seguir:
2
Estas notac oes s ao chamadas tamb em de notac ao polonesa e notac ao polonesa reversa, em homenagem ao matem atico polon es
Jan ukasiewicz que as introduziu no incio deste s eculo.
32 CAP

ITULO 4. ESTRUTURAS LINEARES


Sada Pilha Entrada
a b +c d e/f g h
a b +c d e/f g h
a b +c d e/f g h
ab +c d e/f g h
ab +c d e/f g h
ab + c d e/f g h
ab c + d e/f g h
ab c + d e/f g h
ab cd + e/f g h
ab cd + e/f g h
ab cde + /f g h
ab cde + /f g h
ab cde + /f g h
ab cde +/ f g h
ab cde f +/ g h
ab cde f/ + g h
ab cde f/+ g h
ab cde f/+ g h
ab cde f/ +g h
ab cde f/ +g h
ab cde f/ +gh
ab cde f/ +gh
ab cde f/ +gh
Pode-se perceber que, numa implementac ao completa, o algoritmo teria que prever os casos iniciais (pilha
vazia) e nais (entrada vazia).
A generalizac ao do algoritmo para express oes que t em par enteses e relativamente simples e, na rea-
lidade, semelhante ao tratamento das express oes balanceadas da Sec ao 4.2. Um abre-par entese dever a ser
empilhado e tratado como o fundo de uma pilha menor, at e que seja encontrado o fecha-par entese correspon-
dente; todos os operadores acima do abre-par entese, dever ao ser transferidos ent ao para a sada. Um esboco
do procedimento que transforma express oes inxas em p os-xas est a indicado no Prog. 4.4. O funciona-
mento correto do procedimento depende da denic ao conveniente de uma func ao Prioridade que indica a
relac ao entre o smbolo de entrada e o smbolo que est a no topo da pilha. Note-se que esta relac ao deve
incluir o smbolo ( quando na pilha (veja tamb em o Exerccio 2). O procedimento deve ser completado
com algumas rotinas obvias.
As outras transformac oes s ao um pouco mais complicadas e tamb em ser ao deixadas para exerccios.
4.3. EXEMPLO DE APLICAC

AO: MANIPULAC

AO DE EXPRESS

OES 33
Programa 4.4 Transformac ao da notac ao inxa para p os-xa
type
Cadeia = array [1..ComprMax] of char;
...
procedure InPos(var expr: Cadeia);
var
p: Pilha;
pe: 0..ComprMax;
corr,aux: char;
m: boolean;
begin
InicializaPilha(p);
Empilha(p,

);
pe := 1;
repeat
corr := expr[pe]; inc(pe);
case corr of

..

:
Sai(corr);

:
repeat
Desempilha(p,aux);
if aux=

then Sai(aux)
until aux=

:
begin
m := false;
repeat
Desempilha(p,aux);
if Prioridade(corr,aux)
then begin
Empilha(p,aux);
Empilha(p,corr);
m := true
end
else Sai(aux)
until m
end
end {case}
until corr=

;
LiberaPilha(p)
end; {InPos}
34 CAP

ITULO 4. ESTRUTURAS LINEARES


4.4 Filas
Uma la e uma estrutura linear restrita em que todas as inserc oes s ao realizadas numa extremidade (m) e
todas as remoc oes na outra extremidade (frente). Esquematicamente podemos podemos visualizar uma la
como:
...
fim
...
frente
... remove insere
Como no caso de pilhas, temos as duas alternativas naturais de implementac ao: seq uencial e ligada,
sendo que a decis ao depender a do contexto de utilizac ao. No caso da implementac ao ligada, e conveniente
utilizar uma lista circular com n o-cabeca, como esbocado a seguir:
. . .
fim frente
Neste caso, e interessante que a vari avel que indicar a a la aponte para o seu ultimo n o. Desta maneira,
com um apontador, tanto a frente como o m da la tornam-se acessveis de maneira eciente. O Prog. 4.5
mostra a implementac ao desta opc ao, sob a forma de um tipo abstrato de dados.
No caso da implementac ao seq uencial, h a o problema inerente de previs ao a priori do n umero m aximo
de elementos que poder a haver na la. Fora esta restric ao, uma soluc ao natural e a adoc ao de um vetor
circular, como indicado no esboco:
frente
fim
...
...
...
n1 0
1
2
3
Por convenc ao, o ndice frente aponta para a posic ao que precede o primeiro elemento da la, enquanto que o
ndice m aponta para o ultimo elemento. Com isto, algumas express oes a serem usadas nos procedimentos
car ao mais simples. Conseq uentemente, poderemos adotar para inicializar uma la os valores:
frente = m = 0
4.5. EXERC

ICIOS 35
Entretanto, a condic ao para detetar que n ao h a mais espaco na la e:
frente = m
ou seja, n ao podemos distinguir entre uma la cheia e uma la vazia! A soluc ao mais simples para este
problema e sacricar uma posic ao do vetor e usar como condic ao de la cheia (veja tamb em o Exerccio 4):
frente = (m + 1) mod n
Com estas convenc oes, podemos reprogramar o tipo abstrato de dados Fila como indicado no Prog. 4.6.
A estrutura de la aparece em muitas aplicac oes. Em particular, veremos um exemplo na Sec ao 6.3
aplicado ao percurso em largura de arvores bin arias.
4.5 Exerccios
1. Dena de maneira precisa o conceito de seq u encia balanceada de per enteses. Sugest ao: Use denic oes
indutivas (isto e, recursivas).
2. Implemente o algoritmo de transformac ao da notac ao inxa para p os-xa descrito na Sec ao 4.3, in-
cluindo express oes com operadores di adicos e par enteses, bem como o tratamento de erros. Uma
sugest ao para a implementac ao da func ao Prioridade e a construc ao de uma tabela que associa a cada
smbolo considerado um n umero inteiro, conforme o smbolo esteja na entrada ou no topo da pilha.
A comparac ao entre estes n umeros indicar a a prioridade em cada caso. Um exemplo desta tabela para
os smbolos considerados seria:
Smbolo Pilha Entrada
3 4
, / 2 2
+, 1 1
( 0 4
Foi adotada nesta tabela a convenc ao de dar prioridade ao smbolo da pilha quando os n umeros s ao
iguais (associac ao ` a esquerda). Note tamb em a maneira de tratar o par entese ( para que ele seja
enquadrado no caso geral de operadores; o par entese ) e tratado de maneira especial como indicado
no Prog. 4.4.
3. A notac ao p os-xa pode ser estendida para operadores mon adicos (de um operando), entretanto eles
introduzem ambig uidade. Por exemplo, as express oes inxas distintas a (b) e
(a b) seriam traduzidas para a mesma express ao p os-xa ab . A m de evitar este pro-
blema, os operadores devem utilizar smbolos distintos na traduc ao. Adotando-se o smbolo para o
operador un ario , teramos:
a (b) ab
(a b) ab
36 CAP

ITULO 4. ESTRUTURAS LINEARES


Complete a implementac ao do exerccio anterior para incluir os operadores mon adicos e +,
usando esta representac ao.
4. A implementac ao seq uencial de las proposta neste captulo sacrica uma posic ao do vetor para dis-
tinguir entre uma la cheia e uma la vazia. Uma outra soluc ao seria incluir no registro que representa
a la uma vari avel booleana que indicasse se a la est a cheia ou n ao. Reescreva os procedimentos do
Prog. 4.6 de acordo com esta sugest ao.
5. Em algumas aplicac oes e interessante utilizar o conceito de la dupla. Nesta estrutura, as inserc oes e
remoc oes podemser feitas emqualquer uma das duas extremidades da seq u encia. Proponha implementac oes
ligada e seq uencial para esta estrutura e escreva as rotinas b asicas para manipul a-la, an alogas ` as dos
Progs. 4.5 e 4.6.
4.5. EXERC

ICIOS 37
Programa 4.5 Implementac ao ligada de las
type
ApRegFila = RegFila;
RegFila = record
info: T;
prox: ApRegFila
end;
Fila = ApRegFila;
procedure InicializaFila(var p: Fila);
begin
new(p); p.prox := p
end;
function FilaVazia(var p: Fila): boolean;
begin
FilaVazia := p=p.prox
end;
procedure LiberaFila(var p: Fila);
var q,r: ApRegFila;
begin
q := p.prox;
while q=p do
begin
r := q.prox; dispose(q); q :=r
end;
dispose(p)
end;
procedure InsereFila(var p: Fila; x: T);
var q: ApRegFila;
begin
new(q);
with q do
begin
info := x; prox := p.prox;
p.prox := q; p := q
end
end;
procedure RemoveFila(var p: Fila; var x: T);
var q,r: ApRegFila;
begin
q := p.prox;
if p=q then TrataErro;
r := q.prox; x := r.info;
q.prox := r.prox;
if r=p then p:= q;
dispose(r)
end;
38 CAP

ITULO 4. ESTRUTURAS LINEARES


Programa 4.6 Implementac ao seq uencial de las
type
Fila = record
frente, m: 0..TamMax;
elemen: array [0..TamMax1] of T
end;
procedure InicializaFila(var p: Fila);
begin
with p do
begin frente := 0; m := 0 end
end;
function FilaVazia(var p: Fila): boolean;
begin
FilaVazia := p.frente=p.m
end;
procedure LiberaFila(var p: Fila);
var q,r: ApRegFila;
begin
{ nada }
end;
procedure InsereFila(var p: Fila; x: T);
begin
with p do
begin
if frente=((m+1) mod TamMax)
then TrataErro;
m := (m+1) mod TamMax;
elemen[m] := x
end;
procedure RemoveFila(var p: Fila; var x: T);
begin
if FilaVazia(p) then TrataErro;
with p do
begin
frente := (frente+1) mod TamMax;
x := elemen[frente]
end
end;
Captulo 5
Recurs ao
O objetivo deste Captulo e discutir a recurs ao, um mecanismo muito poderoso de denic ao e programac ao,
aplic avel em muitas situac oes distintas como tratamento de arvores (veja Cap. 6), aplicac oes simb olicas,
implementac ao de linguagens de programac ao, intelig encia articial e outros.
Na primeira sec ao deste captulo veremos alguns exemplos de recurs ao e discutiremos quando ela deve
ser utilizada. Na sec ao seguinte veremos como a recurs ao explcita pode ser substituda por uma pilha do
tipo visto na Sec. 4.2. Finalmente, na ultima sec ao introduziremos um exemplo mais elaborado de aplicac ao
da recurs ao.
5.1 Recurs ao e repetic ao
Dizemos que uma rotina e recursiva se a sua denic ao envolve uma chamada a ela mesma. Note-se que,
neste sentido, o termo recurs ao e equivalente ao termo induc ao utilizado por matem aticos. Um exemplo
cl assico e muito simples de denic ao indutiva e a func ao fatorial que pode ser caracterizada por:
fat(n) =

1 se n = 0
n fat(n 1) se n > 0
Obviamente, esta denic ao indutiva pode ser transformada numa declarac ao recursiva em PASCAL como no
Prog. 5.1. Por outro lado, e muito f acil escrever uma vers ao n ao recursiva da mesma func ao, como indicado
no mesmo programa. Uma an alise das duas vers oes mostra que o n umero de operac oes executadas e, em
ambos os casos, da ordem de O(n). Entretanto, na vers ao iterativa s ao evitadas as chamadas recursivas e a
conseq uente criac ao de registros de ativac ao, conforme visto na Sec ao 1.3. Desta maneira, a constante de
proporcionalidade certamente ser a menor para esta vers ao.
Um outro exemplo cl assico e o c alculo da s erie de Fibonacci. Esta s erie pode ser denida por:
bo(0) = 0
bo(1) = 1
bo(n) = bo(n 1) + bo(n 2) se n > 1
Novamente, a transformac ao desta denic ao numprograma recursivo e trivial conforme indicado no Prog. 5.2.
Por outro lado, e bastante simples escrever uma vers ao n ao recursiva da func ao, indicada no mesmo pro-
grama. Analisemos a eci encia das duas formulac oes, calculando o n umero de operac oes de soma S(n)
39
40 CAP

ITULO 5. RECURS

AO
Programa 5.1 C alculo da func ao fatorial
function fat(n: integer): integer;
begin
if n=0
then fat := 1
else fat := nfat(n1)
end;
function fat(n: integer): integer;
var i,s: integer;
begin
s := 1;
for i:=1 to n do s := si;
fat := s
end;
realizadas. Para a vers ao recursiva, podemos concluir:
S(n) =

0 se n 1
S(n 1) + S(n 2) + 1 se n > 1
A partir desta formulac ao, pode-se provar por induc ao nita (veja o Exerccio 1) que
S(n) = bo(n + 1) 1
Por outro lado, pode-se mostrar que bo(i) ((1 +

5)/2)
i
/

5. Assim, para valores grandes de n, temos


S(n) 1, 6
n
/1, 4. Por exemplo, para calcular bo(100) seriam necess arias mais de 10
20
somas!

E simples
vericar, entretranto, que para a vers ao iterativa o n umero de somas e apenas n. Obviamente, neste caso n ao
faz sentido utilizar a vers ao recursiva.
Programa 5.2 C alculo da s erie de Fibonacci
function bo(n: integer): integer;
begin
if n1
then bo := n
else bo := bo(n1)+bo(n2)
end;
function bo(n: integer): integer;
var f1,f2,f3,k : integer;
begin
f1 := 0; f2 := 1;
for k:=1 to n do
begin
f3 := f1+f2; f1 := f2; f2 := f3
end;
bo := f1
end;
Umoutro exemplo interessante e cl assico de problema que temuma soluc ao simples utilizando formulac ao
recursiva e o de torres de Hanoi. Suponha que temos tr es hastes, denominadas A, B e C. Na haste A h a 64
discos de tamanhos distintos, com furos no centro, em ordem de tamanhos crescentes; as outras hastes est ao
vazias, conforme indicado na Fig. 5.1. O problema consiste em transferir todas os discos da haste A para a
B, utilizando a haste C como auxiliar, seguindo as seguintes regras:
5.1. RECURS

AO E REPETIC

AO 41
Figura 5.1 O problema de torres de Hanoi
.
.
.
.
. .
A B C
somente um disco e movido de cada vez;
um disco maior nunca pode ser colocado em cima de um disco menor.
Pensando de maneira recursiva, n ao e difcil perceber que a soluc ao pode ser obtida conforme indicado no
Prog. 5.3, no qual s ao impressos todos os movimentos. A chamada inicial seria, neste caso, TorresDeHa-
noi(A,B,C,64).
Programa 5.3 Soluc ao do problema de torres de Hanoi
procedure TorresDeHanoi(origem, destino, aux: char; n: integer);
begin
if n>0
then begin
TorresDeHanoi(origem,aux,destino,n1);
writeln(

Mova de

,origem,

para

,destino);
TorresDeHanoi(aux,destino,origem,n1)
end
end;
Os exemplos vistos neste captulo utilizam a recurs ao direta, ou seja, a rotina que est a sendo denida
depende diretamente da sua pr opria denic ao. Em algumas aplicac oes e interessante utilizar a recurs ao
m utua em que duas ou mais rotinas dependem mutuamente uma da outra. As func oes f e g s ao um exemplo
muito simples deste conceito:
f(n) =

0 se n = 0
g(n 1) se n > 0
g(n) =

1 se n = 0
f(n 1) se n > 0
42 CAP

ITULO 5. RECURS

AO
Note-se que, na realidade, f(n) = n mod 2 e g(n) = (n + 1) mod 2. Na ultima sec ao deste captulo
veremos um exemplo mais interessante de recurs ao m utua.
A transformac ao de denic oes mutuamente recursivas em programas e muito simples. No caso de PAS-
CAL, obt em-se para este exemplo o Prog. 5.4. Note-se que a declarac ao forward e exigida pelo compilador.
Programa 5.4 Exemplo de recurs ao m utua
function g(n: integer): forward;
function f (n: integer): integer;
begin
if n=0
then f := 0
else f := g(n1)
end;
function g(n: integer): integer;
begin
if n=0
then g := 1
else g := g(n1)
end;
5.2 Eliminac ao da recurs ao
Nem sempre e possvel, como no caso de func oes de c alculo de fatoriais e de n umeros de Fibonacci na
sec ao anterior, eliminar a formulac ao recursiva da soluc ao de um problema. Entretanto, existem situac oes
nas quais e conveniente eliminar o uso da recurs ao e substitu-la pela utilizac ao de uma pilha explcita. As
vers oes de rotinas obtidas s ao, em geral, mais complexas mas costumam ser mais ecientes, no que diz
respeito ao coeciente de proporcionalidade, por evitarem v arias operac oes como chamadas e retornos de
rotinas, criac ao de registros de ativac ao, etc.
Consideremos o esboco de procedimento recursivo tpico apresentado no Prog. 5.5. A sua traduc ao para
um procedimento sem recurs ao mas com uma pilha explcita est a indicada no Prog. 5.6.
Basicamente, a vers ao transformada do procedimento simula a execuc ao do procedimento original. An-
tes de simular uma chamada recursiva, os valores das vari aveis locais (incluindo os par ametros) s ao salvos
na pilha, juntamente com uma indicac ao de qual das chamadas ser a simulada. A seguir s ao calculados os
valores dos par ametros para a nova chamada e o ciclo de simulac ao e repetido. No retorno de uma chamada
simulada, s ao restaurados os valores das vari aveis locais e executadas as ac oes pendentes daquela chamada.
O c alculo de novos valores dos par ametros deve ser feito com cuidado pois eles podem depender dos valores
anteriores; para isto s ao usadas as vari aveis tempor arias t1, t2, . . . .
Deve-se notar que este esquema de traduc ao e bastante geral, mas alguns cuidados precisam ser tomados
5.2. ELIMINAC

AO DA RECURS

AO 43
na presenca de par ametros passados por vari avel. O esquema n ao leva em considerac ao nenhuma proprie-
dade do algoritmo que est a sendo transformado nem da estrutura dos seus dados. Traduc oes mais simples e
mais ecientes podem ser conseguidas em casos especcos como exemplicado por algoritmos de percurso
de arvores bin arias na Sec ao 6.3.
Programa 5.5 Esboco de um procedimento recursivo
procedure Exemplo(x1,x2, ...: ...);
var y1, y2, ...: ...;
begin
Ci;
if E(...)
then C
else begin
C1;
Exemplo(e11,e12,...);
C2;
Exemplo(e21,e22,...);
C3;
...
Cm;
Exemplo(em1,em2,...);
Cf
end
end;
44 CAP

ITULO 5. RECURS

AO
Programa 5.6 Esboco da transformac ao do procedimento recursivo do Prog. 5.5
type Chamadas = (chamada1, chamada2,chamada3,...);
procedure Exemplo(x1,x2, ...: ...);
type Acoes = (entrada,retorno,saida);
var y1, y2, ...: ...;
f : Pilha; ch: Chamadas; acao: Acoes; t1, t2: ...;
begin
InicializaPilha(f ); acao := entrada;
repeat
case acao of
entrada: begin
Ci;
if E(...)
then begin C; acao := retorno end
else begin
C1;
Empilha(f ,x1,...,y1,...,chamada1);
t1 := e11; t2 := e12; ...
x1 := t1; x2 := t2; ...
end
end;
retorno: if PilhaVazia(f )
then acao := saida
else begin
Desempilha(f ,x1,...,y1,...,ch);
case ch of
chamada1: begin
C2;
Empilha(f ,x1,...,y1,...,chamada2);
t1 := e21; t22 := e22; ...
x1 := t1; x2 := t2; ...
acao := entrada
end;
chamada2: begin
C3;
Empilha(f ,x1,...,y1,...,chamada3);
t1 := e31; t2 := e32; ...
x1 := t1; x2 := t2; ...
acao := entrada
end;
...
chamadam: Cf
end { case }
end
end { case }
until acao=saida
end;
5.3. EXEMPLO: AN

ALISE SINT

ATICA 45
5.3 Exemplo: an alise sint atica
Vimos na Sec ao 4.3 um exemplo interessante de manipulac ao de express oes ao desenvolver um programa
que transforma express oes em notac ao inxa para a notac ao p os-xa, utilizando uma pilha de operadores.
Conforme estudamos neste captulo, existe uma relac ao muito pr oxima entre a utilizac ao de pilha e a re-
curs ao; na realidade, a pilha e uma maneira de implementar a recurs ao.

E natural, portanto, que o programa
de transformac ao visto possa ser expresso em termos recursivos, tornando-o mais f acil de compreender,
apesar de eventualmente um pouco menos eciente.
Consideremos inicialmente as express oes inxas que podem ser construdas com varaveis representadas
por letras min usculas, os operadores di adicos +, , , / e os par enteses ( e ) (omitimos, por
enquanto, o operador de exponenciac ao ). N ao e difcil notar que uma express ao e sempre tem a forma
e = t
1
t
2
t
n
, n 1
onde os t
i
representamos termos da express ao e, e o smbolo umdos operadores + ou . An alogamente,
um termo t pode ser descrito como
t = f
1
f
2
f
n
, n 1
onde os f
i
representam os fatores do termo t, e representa um dos operadores ou /. Finalmente,
podemos descrever um fator f como sendo ou uma letra ou uma express ao entre par enteses:
f = x ou f = ( e )
onde x denota qualquer letra. (Fica subentendido, apesar de n ao estar implcito nesta notac ao, que nos dois
casos os operadores est ao associados ` a esquerda.)
Deve-se notar que utilizamos denic oes mutuamente recursivas para denir o conjunto de express oes.
Esta forma de descrev e-las leva naturalmente a um conjunto de rotinas recursivas para process a-las com
alguma nalidade. No contexto de teoria de linguagens formais e de teoria de compilac ao, este tipo de
descric ao recebe nome de gram atica, e a an alise de express oes descritas por uma gram atica e denominada
an alise sint atica.
Uma aplicac ao possvel desta id eia e a implementac ao da transformac ao de express oes inxas para p os-
xas atrav es de tr es rotinas mutuamente recursivas, como indicado no Prog. 5.7. Um ponto importante
a destacar e que cada um dos tr es procedimentos Expressao, Termo e Fator e respons avel por processar
a parte da cadeia de smbolos que corresponde ` a respectiva construc ao; al em disto, cada chamada de um
destes procedimentos avanca a vari avel pe at e o caractere que segue a construc ao processada. A detec ao de
erros n ao e completa e ser a deixada para o Exerccio 5. Deve-se observar tamb em a maneira natural como
estes procedimentos seguem a descric ao recursiva das express oes indicadas acima. Um outro ponto a notar e
o instante em que os operadores s ao transferidos para a sada, produzindo o efeito de associac ao ` a esquerda
dos quatro operadores.
Completemos agora o nosso programa com o operador de exponenciac ao . Podemos modicar a
denic ao de fator atrav es de
f = p
1
p
2
p
n
, n 1
p = x ou p = ( e )
onde p denota os elementos prim arios de um fator.
46 CAP

ITULO 5. RECURS

AO
Programa 5.7 Transformac ao inxa para p os-xa (vers ao incompleta)
type
Cadeia = array [1..ComprMax] of char;
...
procedure InPos(var e: Cadeia);
var corr: char; pe: 0..ComprMax;
procedure Expressao; forward;
procedure Termo; forward;
procedure Fator;
begin
corr := e[pe];
case corr of

..

: begin
Sai(corr);
inc(pe)
end;

: begin
inc(pe);
Expressao;
if e[pe]=

then inc(pe)
end
else Erro
end
end; {Fator}
procedure Termo;
var op: char; m: boolean;
begin
Fator;
m := false;
repeat
corr := e[pe];
if (corr=

) or (corr=

)
then begin
op := corr;
inc(pe);
Fator;
Sai(op)
end
else m := true
until m
end; {Termo}
procedure Expressao;
var op: char; m: boolean;
begin
Termo;
m := false;
repeat
corr := e[pe];
if (corr=

) or (corr=

)
then begin
op := corr;
inc(pe);
Termo;
Sai(op)
end
else m := true
until m
end; {Expressao}
begin
pe := 1;
Expressao;
if e[pe]=

then Erro
end; {InPos}
5.3. EXEMPLO: AN

ALISE SINT

ATICA 47
Aparentemente, a extens ao do Prog. 5.7 para incluir a exponenciac ao seria muito simples, bastando para
isto mudar o nome do procedimento Fator para Primario, e escrever um novo procedimento Fator, an alogo a
Expressao e Termo. Entretanto, o procedimento Fator escrito desta maneira trataria o operador como se
fosse associado ` a esquerda o que n ao seria correto. Uma an alise mais cuidadosa indica que seria necess ario
utilizar uma pilha local ao pr oprio procedimento para guardar todas as ocorr encias do operador dentro
do fator corrente, e desempilh a-los e copiar para a sada no m da sua execuc ao. Neste caso particular, a
pilha n ao seria realmente necess aria, pois bastaria anotar o n umero de ocorr encias de , j a que temos um
unico operador neste nvel de preced encia.
Esta soluc ao, apesar de satisfat oria neste caso particular, n ao seria conveniente em geral, se houvesse
uma variedade maior de operadores. Anal, estamos utilizando a recurs ao justamente para evitar o uso de
uma pilha explcita! Uma outra maneira de resolver o problema e modicar a denic ao de fator:
f = p ou f = p f
Note-se que agora a denic ao de f e diretamente recursiva, e indica explicitamente que o operador deve
ser associado ` a direita. Segundo esta denic ao, podemos escrever uma nova vers ao do procedimento Fator
indicada no Prog. 5.8. Note-se que o procedimento Fator n ao pode decidir imediatamente qual das duas
alternativas, p ou p f deve ser escolhida. Entretanto, as duas alternativas t em o mesmo incio p o que
permite que a decis ao seja postergada at e que seja processada a parte comum.
Programa 5.8 Procedimeto Fator
procedure Fator;
begin
Primario;
if e[pe]=

then begin
inc(pe);
Fator;
Sai(

)
end
end; {Fator}
Uma id eia que pode surgir naturalmente neste momento e a transformac ao an aloga das descric oes das
express oes e dos termos para:
e = t ou e = e t
t = f ou t = t f
Observe-se como foi feita a denic ao para indicar que neste caso os operadores s ao associados ` a esquerda.
Entretanto, a transformac ao direta destas denic oes em procedimentos, an aloga ao caso de Fator, n ao parece
ser possvel. Por exemplo, as duas alternativas para express oes, t e e t, t em partes iniciais diferentes e
n ao est a claro como tomar a decis ao. Se o procedimento Expressao chamasse inicialmente o procedimento
Termo, n ao estaria claro como proceder com outros termos se existissem; se ele chamasse inicialmente a si
mesmo, entraria numa repetic ao innita!
48 CAP

ITULO 5. RECURS

AO
Esta diculdade e devida ao fato das denic oes de express oes e de termos conterem recurs ao esquerda,
isto e, o conceito que est a sendo denido aparece imediatamente no incio da denic ao. No caso do fator,
temos a recurs ao direita, isto e, o conceito aparece no m da denic ao. O m etodo de an alise sint atica
apresentado nesta sec ao pertence ` a categoria de m etodos descendentes que n ao s ao aplic aveis em casos
de recurs ao esquerda, sem que haja uma manipulac ao adicional das denic oes levando a formas como a
indicada inicialmente nesta sec ao. Deve-se mencionar que existem outras categorias de an alise, mais gerais,
que n ao apresentam essas limitac oes.
5.4 Exerccios
1. Prove, por induc ao nita, que o n umero de somas S(n) realizado pela vers ao recursiva da func ao bo
do Prog. 5.2 e dado por:
S(n) = bo(n + 1) 1
2. Mostre que
(a) o n umero de movimentos impressos pelo procedimento TorresDeHanoi indicado no Prog. 5.3 e
2
n
1;
(b) este e o n umero mnimo de movimentos para resolver o problema.
3. Aplique as id eias da Sec ao 5.2 para eliminar a recurs ao do procedimento TorresDeHanoi exibido no
Prog. 5.3.
4. Generalize a id eia de eliminac ao da recurs ao aplicando-a ao caso de recurs ao m utua como indicado
no exemplo das func oes f e g da p ag. 41. Sugest ao: Utilize uma unica pilha, mas inclua no c odigo
de retorno a informac ao sobre a origem da chamada.
5. Complete o Prog. 5.7 de maneira a incluir todos os operadores di adicos e mon adicos e a detetar todas
as condic oes de erro.
6. Considere a seguinte denic ao de todas as seq u encias de par enteses balanceados (veja tamb em a
Sec ao 4.2):
b =
b = ( b ) b
b = [ b ] b
onde denota a seq u encia vazia, e cada linha indica uma alternativa para a seq u encia. Escreva um
programa que usa recurs ao para reconhecer as cadeias que correspondem a esta denic ao.
7. Considere a seguinte denic ao de todas as seq u encias de smbolos que denotamexpress oes emnotac ao
pr e-xa:
5.4. EXERC

ICIOS 49
p = x
p = &p
p = p
p = +p p
p = p p
p = p p
p = / p p
p = p p
onde x denota uma letra min uscula. Escreva um programa que usa recurs ao para transformar as
express oes pr e-xas para p os-xas.
8. Refaca o exerccio anterior para a transformac ao de express oes pr e-xas para in-xas. Sugest ao:

E
mais f acil produzir express oes inxas compar enteses para cada operador, mesmo que sejamsup eruos.
Por exemplo, +a
*
bc produziria (a + (b c)).
9. Refaca o exerccio anterior eliminando os par enteses sup eruos. Sugest ao: Cada rotina recursiva
deve receber como argumento uma informac ao sobre o operador que est a sendo processado.
50 CAP

ITULO 5. RECURS

AO
Captulo 6

Arvores bin arias


Neste captulo, bem como no pr oximo, estudaremos arvores, uma estrutura de dados que aparece com
freq u encia em muitas aplicac oes. Intuitivamente, uma arvore representa uma organizac ao da informac ao
em que os dados est ao numa relac ao hier arquica. Na realidade, o uso de arvores para representar relac oes
precede de muito o aparecimento de computadores. Exemplos mais conhecidos s ao as arvores geneal ogicas
1
que indicam os antepassados de um indivduo. Assim a Fig. 6.1 indica a arvore geneal ogica de um c ao de
raca de propriedade de um dos autores. Esta arvore poderia ser estendida (quase!) indenidamente com a
inclus ao de mais gerac oes de antepassados, mas em geral n ao o faremos por falta de informac ao suciente,
ou por falta de interesse, ou por falta de espaco!
Note-se que, pela pr opria natureza da informac ao representada na Fig. 6.1, para cada indivduo h a dois
antepassados imediatos. Note-se, tamb em, que alguns indivduos est ao repetidos, reetindo um fato comum
em arvores geneal ogicas. Como veremos mais adiante, se insistssemos em manter uma unica c opia do
nome de cada indivduo, com v arias linhas apontando para esta c opia, a estrutura de dados deixaria de ser
propriamente uma arvore. No caso desta gura, s ao as ocorr encias dos nomes dos indivduos, e n ao os
indivduos, que constituem a arvore.
A Fig. 6.2 apresenta um outro exemplo de arvore, desta vez relacionada com assuntos ling usticos: a ar-
vore de alguns idiomas que descendemde uma hipot etica lngua indo-europ eia. Neste caso, cada lngua pode
ter um n umero vari avel e, em princpio ilimitado, de descendentes diretos. Devido a limitac oes de espaco,
bem como a diferencas de opini ao entre os ling uistas, a informac ao contida na arvore est a incompleta e
inexata.
Existem muitos outros exemplos de uso de arvores, como a organizac ao hier arquica de uma empresa,
a classicac ao biol ogica das esp ecies, e assim por diante. Nas sec oes que seguem, examinaremos arvores
bin arias. O Captulo 7 ser a dedicado a arvores gerais, como a da Fig. 6.2.
1
Em ingl es utiliza-se o termo pedigree.
51
52 CAP

ITULO 6.

ARVORES BIN

ARIAS
Figura 6.1

Arvore geneal ogica
R. J. B. Sean
Lakeview Lois
R. J. B. Sean
Carina de
Wood Ladge
Ator dos
Seis Irm aos
Arisca dos
Seis Irm aos
Johnson
Fancy Boots
Lady Weberly
R. J. B. Hill
Billy
R. J. B.
Helvetia
Scotland
dos Seis Irm aos
Matarazzos
Beauty
Jesse James
Carina de
Wood Ladge
Sugarteds
Bonnie

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
`
`
`
`
`
`
`
`
`
`

`
`
`
`
`
`
`
`
`

53
Figura 6.2

Arvore de descendentes
Indo-Europeu
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
/
/
/
/
/
/
/
/
/
/
/
`
`
`
`
`
`
`
`
`
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
Grego
cl assico
Germ anico
Indo-Iraniano
It alico
Eslavo

`
`
`
`

`
`
`
`

`
`
`
`
`
Grego
moderno
Germ anico
Setentrional
Germ anico
Ocidental
S anscrito
Persa
Latim
Polon es
Russo
Checo

.
.
.
.

`
`
`
`
`
Sueco
Noruegu es
Ingl es
Alem ao
Holand es
Hindi
Portugu es
Castelhano
Franc es
Italiano
54 CAP

ITULO 6.

ARVORES BIN

ARIAS
6.1 Denic oes, terminologia e propriedades
Uma das variantes mais importantes de arvores s ao as arvores bin arias, das quais a Fig. 6.1 e um exemplo.
De maneira mais precisa, adotaremos a seguinte denic ao:
Uma arvore bin aria T e um conjunto nito de objetos denominados n os (ou v ertices), tais que
ou (a) T e vazio,
ou (b) T consiste de um n o distinto, chamado raiz de T, e de duas arvores bin arias disjuntas T
e
e T
d
, chamadas sub arvores esquerda e direita de T (ou da raiz de T), respectivamente.
Note-se que a denic ao de arvores bin arias e recursiva.
2
A Fig. 6.3 mostra um outro exemplo de arvore bin aria, em que os n os foram rotulados com letras. Nas
aplicac oes, cada n o ser a rotulado com alguma informac ao relevante ao problema em quest ao.
Figura 6.3 Exemplo de arvore bin aria
A
B
D E
C
F
H G
Existem algumas convenc oes e terminologia que t em sido adotadas quase universalmente com relac ao
` as arvores, se bem que nem sempre de maneira muito coerente.
3
Neste texto, indicaremos geralmente as
arvores com as suas razes no topo da gura, e com as sub arvores crescendo para baixo. Como e natural,
as sub arvores esquerda e direita aparecem representadas do lado esquerdo e direito da raiz. Deve-se notar
que as duas arvores bin arias da Fig. 6.4 s ao distintas (veja, entretanto, as denic oes do Captulo 7).
O grau de um n o de uma arvore bin aria e denido como sendo o n umero de sub arvores n ao vazias deste
n o (portanto zero, um ou dois). Assim, os n os A, F e H da Fig. 6.3 t em graus 2, 1 e 0, respectivamente.
Os n os de grau igual a zero s ao chamados de n os terminais ou folhas da arvore. Os outros n os s ao os n os
internos ou n os n ao-terminais. O conjunto de folhas da arvore bin aria da Fig. 6.3 e {D, G, H}.
Ao descrever arvores bin arias utilizam-se com freq u encia termos inspirados por arvores que representam
relac oes de parentesco. Assim, o n o que e a raiz de uma arvore e chamado de pai
4
dos n os que s ao as razes
das suas sub arvores; na Fig. 6.3, A e o pai de B e C; E e o pai de G. Inversamente, falamos em n os que s ao
2
Alguns autores preferem uma denic ao ligeiramente diferente que n ao admite arvores bin arias vazias.
3
O conceito de arvore adotado em Computac ao e distinto mas relacionado com o conceito adotado em Teoria dos Grafos.
4
Como e praxe em portugu es, as formas masculinas como pai ou irm ao s ao utilizadas como traduc oes dos termos neutros
ingleses parent ou sibling, sem nenhuma prefer encia por um dos sexos.
6.1. DEFINIC

OES, TERMINOLOGIA E PROPRIEDADES 55
Figura 6.4

Arvores bin arias distintas
A
B
A
B
lhos de um outro n o; ainda na Fig. 6.3, B e C s ao os lhos de A; G e o unico lho de E. Os lhos de um
mesmo n o s ao chamados de irm aos; assim, B e C s ao irm aos, como o s ao D e E.
As relac oes de pai e lho s ao estendidas de maneira natural para antepassado e descendente. Todos
os n os da arvore da Fig. 6.3 (inclusive A) s ao considerados descendentes de A, e A e o antepassado de
todos eles (inclusive de si mesmo). B e um dos antepassados de B e de G; H e um descendente de C.
Obviamente, poderamos denir, se fosse conveniente, noc oes como primo, tio, e assim por diante.
O nvel de um n o numa arvore bin aria e um n umero natural obtido aplicando-se a seguinte denic ao
recursiva:
(a) a raiz da arvore bin aria tem o nvel 1;
(b) se um n o tem o nvel n, ent ao os seus lhos t em o nvel n + 1.
A altura (ou a profundidade) de uma arvore bin aria e o nvel m aximo atribudo a um n o da arvore. Na
Fig. 6.3, os n os A, C, E e H t em os nveis 1, 2, 3 e 4, respectivamente; a altura da arvore e 4. A altura de
uma arvore bin aria vazia e igual a zero.
5
Existemv arias propriedades quantitativas de arvores bin arias que s ao importantes para as suas aplicac oes.
Citaremos apenas algumas, deixando as suas demonstrac oes para os exerccios. Quase todas as demonstrac oes
s ao bastante simples, utilizando em geral a induc ao matem atica.
1. Uma arvore bin aria com n n os utiliza n 1 apontadores n ao nulos (utilizando a representac ao como
a da Fig. 6.3).
2. O n umero m aximo de n os de uma arvore bin aria de altura h e 2
h
1.
3. As alturas m axima e mnima de uma arvore bin aria de n n os s ao dadas por n e log
2
(n+1), respec-
tivamente.
6
4. Sejamn
0
e n
2
os n umeros de n os com zero e dois lhos, respectivamente, numa arvore bin aria. Ent ao
n
0
= n
2
+ 1.
5. O n umero b
n
de arvores bin arias distintas com n n os e dado por b
n
=
1
n+1

2n
n

. Pode-se mostrar
que, para valores crescentes de n, o valor aproximado e dado por b
n
= 4
n
/n

n.
7
5
Alguns autores associam ` a raiz o nvel zero, e consideram a altura de uma arvore bin aria vazia como sendo indenida.
6
A func ao r indica o teto de r, isto e, o mnimo inteiro maior ou igual a r.
7
Uma demonstrac ao desta propriedade pode ser encontrada, por exemplo, em Knuth [?].
56 CAP

ITULO 6.

ARVORES BIN

ARIAS
6.2 Implementac ao de arvores bin arias
A pr opria maneira de representar as arvores bin arias da Fig. 6.3 sugere uma implementac ao atrav es de
uma estrutura ligada utilizando apontadores. Dependendo da aplicac ao, podemos incluir ou n ao certas
informac oes nesta representac ao. A Fig. 6.5 mostra a mesma arvore da Fig. 6.3, representada utilizando-se
apontadores e tornando f acil a recuperac ao das informac oes lho esquerdo e lho direito para cada n o. O
tipo de n o utilizado poderia ser indicado num programa atrav es das declarac oes:
type
ApReg = Reg;
Reg = record
info: M;
esq, dir: ApReg
end;
ArvBin = ApReg;
onde M e algum tipo que corresponde ` a informac ao a ser contida em cada n o. Suporemos tamb em, na
maior parte das aplicac oes, que e conhecido o apontador ` a raiz da arvore bin aria atrav es do qual pode-se ter
acesso ` a arvore inteira. Este apontador poder a estar contido, por exemplo, numa vari avel do programa, ou
no campo apontador de um outro n o.
Figura 6.5 Representac ao de arvores bin arias com campos esq e dir
A
B C
D E F
G H
Esta representac ao permite realizar com facilidade as operac oes de inserc ao ou remoc ao de n os, contanto
que elas sejam bem denidas. No caso da inserc ao poderamos utilizar, por exemplo, um procedimento
como indicado no Prog. 6.1 onde foi convencionada uma inserc ao do novo n o como lho esquerdo do n o
apontado por p; a sub arvore esquerda de p tornou-se a sub arvore esquerda do novo n o. Outros procedimentos
poderiam ser denidos de maneira semelhante.
Conforme a aplicac ao, poder ao ser utilizadas representac oes ligadas diferentes. A Fig. 6.6 mostra ainda
a mesma arvore da Fig. 6.3, mas contendo apenas o apontador para a representac ao do n o pai. Note-se que
um algoritmo que utilizasse esta representac ao teria necessidade de obter a informac ao sobre a localizac ao
de v arios n os da arvore (ao menos de todas as folhas); um apontador para a raiz n ao seria suciente neste
6.2. IMPLEMENTAC

AO DE

ARVORES BIN

ARIAS 57
Programa 6.1 Procedimento de inserc ao ` a esquerda
procedure InsereEsq(p: ArvBin; x: M);
var q: ApReg;
begin
new(q);
with q do
begin info := x; esq := p.esq; dir := nil end;
p.esq := q
end;
caso. Al em disto, dado um n o qualquer, n ao seria possvel decidir se ele e o lho esquerdo ou direito do seu
pai. Caso esta informac ao fosse exigida pela aplicac ao, seria necess ario colocar, por exemplo, uma marca
adicional em cada n o.
Figura 6.6

Arvore bin aria com o campo pai.
B
G
D E F
H
C
A
Em certos casos, podem ser utilizadas representac oes mais ecientes para arvores bin arias. Dizemos
que uma arvore bin aria de altura h e completa
8
se ela contiver 2
h
1 n os (ou seja, o n umero m aximo de n os
veja a Propriedade 2 da Sec ao 6.1). A Fig. 6.7 mostra uma arvore completa de altura 4.

E f acil vericar
que podemos associar a cada n o x de uma arvore bin aria completa um ndice f(x) tal que:
(a) se x e raiz, ent ao f(x) = 1;
(b) se x
e
e x
d
s ao os lhos esquerdo e direito de x, ent ao f(x
e
) = 2f(x) e f(x
d
) = 2f(x) +1;
(c) se x n ao e raiz, e x
p
e o pai de x, ent ao f(x
p
) = f(x)/2.
9
Nestas condic oes, podemos representar a arvore da Fig. 6.7 por um vetor de n os, como indicado abaixo:
8
Em ingl es full binary tree.
9
A func ao r indica o piso de r, isto e, o m aximo inteiro menor ou igual a r.
58 CAP

ITULO 6.

ARVORES BIN

ARIAS
Figura 6.7

Arvore bin aria completa de altura 4
A
D E G H
C F
B I
J
K L
M
N O
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A B I C F J M D E G H K L N O

E obvio que, nesta representac ao, dado o ndice de um n o qualquer, e simples e eciente achar os
seus lhos e o seu pai, se existirem. Al em disto, com a eliminac ao dos apontadores pode haver economia
consider avel do espaco utilizado para armazenar a arvore. Esta representac ao pode ser estendida de maneira
obvia para arvores quase completas que s ao aquelas semelhantes ` as completas, em que est a faltando um
certo n umero de n os no nal da ordem indicada pelo ndice f(x) denido acima. A Fig. 6.8 mostra um
exemplo.
Existem v arias aplicac oes em que arvores completas e quase completas com esta representac ao seq uen-
cial podem ser utilizadas. Outras maneiras de representar arvores bin arias ser ao vistas nas sec oes seguintes
e nos exerccios.
Figura 6.8

Arvore bin aria quase completa de altura 4
A
D E G H
C F
B I
J
K
M
6.3. PERCURSO DE

ARVORES BIN

ARIAS 59
6.3 Percurso de arvores bin arias
V arias aplicac oes de arvores bin arias exigem o exame sistem atico das informac oes contidas em todos os n os
da arvore. Dizemos que tais aplicac oes realizam um percurso
10
(ou uma travessia) da arvore, e que cada n o
recebe uma ou mais visitas. A ordem em que os n os devem ser percorridos depende da aplicac ao. Existem,
entretanto, duas classes de percursos que aparecem com mais freq u encia, e que ser ao estudadas de maneira
mais detalhada.
Uma classe de percursos de arvores bin arias e constituda por percursos em profundidade, que seguem
a pr opria denic ao recursiva destas arvores. Tr es desses percursos poderiam ser chamados de can onicos, e
est ao denidos a seguir, para o caso de arvores bin arias n ao vazias:
Pr e-ordem:
Visitar a raiz
Percorrer a sub arvore esquerda em pr e-ordem
Percorrer a sub arvore direita em pr e-ordem
P os-ordem:
Percorrer a sub arvore esquerda em p os-ordem
Percorrer a sub arvore direita em p os-ordem
Visitar a raiz
Inordem (ou ordem sim etrica):
Percorrer a sub arvore esquerda em inordem
Visitar a raiz
Percorrer a sub arvore direita em inordem
No caso da arvore da Fig. 6.3 obteramos as seguintes ordens de percurso:
Pr e-ordem: A,B,D,E,G,C,F,H
P os-ordem: D,G,E,B,H,F,C,A
Inordem: D,B,G,E,A,F,H,C
Estas denic oes podem ser traduzidas diretamente em procedimentos recursivos que implementam os
percursos. Supondo a implementac ao de arvores da Sec ao 6.2 com os campos esq e dir, podemos utilizar o
procedimento apresentado no Prog. 6.2 para realizar o percurso em pr e-ordem, utilizando recurs ao.
Os outros percursos emprofundidade podemutilizar procedimentos an alogos, trocando-se simplesmente
a posic ao do comando de visita ao n o p.

E f acil vericar que os procedimentos realizam um n umero de
operac oes proporcional ao tamanho da arvore apontada por p (isto e, ao n umero de n os). A mem oria uti-
lizada e proporcional ao n umero m aximo de chamadas recursivas atingido em algum instante da execuc ao.
Este n umero e igual ` a altura da arvore, sendo no m aximo igual ao seu n umero de n os. Mais adiante estu-
daremos maneiras mais ecientes de implementar estes percursos, diminuindo possivelmente os fatores de
proporcionalidade mas sem afetar o comportamnento descrito.
Dizemos que o percurso de uma arvore bin aria e realizado em largura (ou em nvel) se os seus n os s ao
visitados em ordem dos seus nveis, isto e, em primeiro lugar o nvel 1 (a raiz), depois o nvel 2, depois o
10
Em ingl es traversal.
60 CAP

ITULO 6.

ARVORES BIN

ARIAS
Programa 6.2 Procedimento de percurso recursivo em pr e-ordem
procedure PreOrdem(p: ArvBin);
begin
if p= nil then
with p do
begin
Visita(p);
PreOrdem(esq);
PreOrdem(dir)
end
end;
nvel 3, e assim por diante. Dentro de cada nvel, a ordem costuma ser da esquerda para a direita, quando
representada como na Fig. 6.3. Assim, para aquela arvore, o percurso em largura produziria a seguinte
ordem das visitas aos n os: A,B,C,D,E,F,G,H.
Uma maneira simples de implementar o algoritmo de percurso em largura e utilizar uma la como de-
nida na Sec ao 4.4, para lembrar, em ordem certa, os n os que ainda n ao foram processados (inicialmente,
a raiz). No procedimento do Prog. 6.3 sup oe-se que os elementos da la s ao do tipo ApReg, e que todos os
procedimentos auxiliares foram denidos convenientemente.
Programa 6.3 Procedimento de percurso em largura utilizando uma la
procedure PercursoEmLargura(p: ArvBin);
var f : Fila; q: ApReg;
begin
InicializaFila(f );
InsereFila(f ,p);
repeat
Remove(f ,q);
if q=nil then with q do
begin
Visita(q);
InsereFila(f ,esq);
InsereFila(f ,dir)
end
until FilaVazia(f )
end;

E f acil vericar que o tempo de execuc ao do procedimento PercursoEmLargura e basicamente propor-


cional ao n umero de n os existentes na arvore.

E interessante notar tamb em que, no caso de arvores bin arias
6.3. PERCURSO DE

ARVORES BIN

ARIAS 61
completas ou quase completas, com sua representac ao seq uencial da sec ao anterior, o algoritmo de percurso
em largura reduz-se a uma simples enumerac ao seq uencial dos elementos do vetor que representa a arvore!
Os percursos em profundidade denidos nesta sec ao sugerem algumas outras representac oes lineares de
arvores que podem ser muito uteis em algumas aplicac oes, como por exemplo a representac ao de arvores
em arquivos. Note-se que, dado o resultado de um dos percursos da arvore, n ao e possvel reconstru-la sem
alguma informac ao adicional. Pode-se mostrar, entretanto (veja os Exerccios 5 e 6), que esta reconstruc ao
e possvel se forem conhecidos os resultados de se percorrer a arvore em pr e-ordem e inordem (ou em p os-
ordem e inordem). Podemos descrever, assim, uma arvore bin aria fornecendo duas ordens de percurso. Uma
outra maneira de descrever uma arvore consiste em fornecer apenas uma das ordens de percurso com alguma
informac ao adicional. Por exemplo, podemos indicar, para cada n o, quais s ao as suas sub arvores n ao vazias.
Adotando a notac ao X
ij
, com valores de i (ou j) iguais a zero se a sub arvore esquerda (ou direita) for vazia,
e iguais a um caso contr ario, obt em-se para a arvore da Fig. 6.3, no caso da pr e-ordem, a representac ao:
A
11
B
11
D
00
E
10
G
00
C
10
F
01
H
00
Ao inv es de utilizar os ndices, podemos usar uma descric ao parent etica, na qual (no caso da inordem,
por exemplo) cada n o e descrito por um abre-par entese, a descric ao da sua sub arvore esquerda, o r otulo
do n o, a descric ao da sub arvore direita, e por um fecha-par entese; uma arvore vazia ca descrita por ().
Novamente, no caso do mesmo exemplo de arvore bin aria, obteramos a descric ao:
(((()D())B((()G())E()))A((()F(()H()))C()))
Este tipo de descric ao parent etica pode ser obtido facilmente com percurso em profundidade da arvore.
Os procedimentos de percurso em profundidade descritos acima s ao muito obvios e bastante ecientes,
pelo menos em princpio, pois os seus tempos de execuc ao e a mem oria utilizada no pior caso s ao essen-
cialmente proporcionais ao tamanho da arvore. Mesmo assim, podem-se aproveitar as particularidades dos
procedimentos e a estrutura de dados utilizada para introduzir v arias melhorias, ` as vezes de maneira muito
engenhosa.
Em primeiro lugar, poderamos aplicar aos procedimentos de percurso em profundidade as t ecnicas
vistas na Sec ao 5.2 para eliminar o uso da recurs ao, substituindo-a por uma pilha explcita. Mesmo se a
transformac ao for aplicada sem levar em considerac ao as caractersticas de cada procedimento, poder a haver
uma economia apreci avel no tempo de execuc ao e na mem oria m axima utilizada. O tempo seria economi-
zado diminuindo-se o n umero de operac oes necess arias para processar cada n o, que na formulac ao anterior
inclua chamadas recursivas do procedimento, que podem ser operac oes relativamente caras em algumas
implementac oes. As chamadas das rotinas que manipulam a pilha explcita poderiam ser implementadas de
maneira mais eciente, ou simplesmente substitudas por comandos correspondentes.
11
Al em disso, con-
forme foi visto na Sec ao 1.3, para cada chamada recursiva, o sistema cria na sua pilha uma nova area de
dados locais para um procedimento, que e o seu registro de ativac ao. Esta area e normalmente muito maior
do que o espaco que ser a utilizado para cada n o, com uma pilha explcita. Como resultado, teramos ainda
procedimentos com tempo e espaco lineares, mas com coecientes de proporcionalidade signicativamente
menores. Como exemplo deste tipo de transformac ao, mostramos no Prog. 6.4 o percurso em pr e-ordem.
Supusemos neste caso que os elementos da pilha s ao especicados pelas declarac oes abaixo. A adaptac ao
deste procedimento para a inordem e a p os-ordem e muito simples (veja o Exerccio 16).
11
Esta substituic ao e denominada ` as vezes expans ao em linha.
62 CAP

ITULO 6.

ARVORES BIN

ARIAS
type
Chamadas = (chamada1, chamada2);
ElemPilha = record
info: ApReg;
chamada: Chamadas
end;
Programa 6.4 Pr e-ordem com pilha explcita obtida por transformac ao
procedure PreOrdem(p: ArvBin);
type
Acoes = (entrada,retorno,saida);
var
f : Pilha; q: ApReg; ch: Chamadas;
acao: Acoes;
begin
InicializaPilha(f ); acao := entrada;
repeat
case acao of
entrada: if p=nil
then begin
Visita(p); Empilha(f ,p,chamada1);
p := p.esq
end
else acao := retorno;
retorno: if PilhaVazia(f )
then acao := saida
else begin
Desempilha(f ,p,ch);
case ch of
chamada1: begin
Empilha(f ,p,chamada2);
p := p.dir;
acao := entrada
end;
chamada2: { nada }
end
end
until acao=saida
end;
A vers ao do procedimento mostrada no Prog. 6.4 foi obtida de maneira quase mec anica, sem levar em
considerac ao a natureza do procedimento recursivo em quest ao nem a estrutura que ele est a manipulando.

E
6.3. PERCURSO DE

ARVORES BIN

ARIAS 63
interessante notar que no caso da pr e-ordempodemos obter uma outra vers ao muito simples do procedimento
atrav es de uma pequena transformac ao do procedimento PercursoEmLargura: basta substituir a la por uma
pilha, e inverter a ordem de inserc ao dos elementos, como indicado no Prog. 6.5.
Programa 6.5 Pr e-ordem com pilha explcita an aloga ao percurso em largura
procedure PreOrdem(p: ArvBin);
var f : Pilha;
begin
InicializaPilha(f );
Empilha(f ,p);
repeat
Desempilha(f ,p);
if p=nil then with p do
begin
Visita(p);
Empilha(f ,dir)
Empilha(f ,esq);
end
until PilhaVazia(f )
end;
Uma an alise destas vers oes mostra que h a muitos empilhamentos seguidos imediatamente de desempi-
lhamentos, al em do empilhamento de apontadores nulos. A vers ao do Prog. 6.6, um pouco mais elaborada,
elimina esta ineci encia.
No caso dos outros percursos em profundidade, tamb em podemos aproveitar as suas peculiaridades para
diminuir mais ainda os coecientes de proporcionalidade. Por exemplo, no caso da p os-ordem e necess ario
distinguir quando o algoritmo est a voltando depois de percorrer a sub arvore esquerda ou direita do n o
corrente. Esta distinc ao pode ser feita comparando-se o apontador a uma destas sub arvores com o apontador
ao ultimo n o visitado, como mostrado no Prog. 6.7.
64 CAP

ITULO 6.

ARVORES BIN

ARIAS
Programa 6.6 Pr e-ordem mais eciente com pilha explcita
procedure PreOrdem(p: ArvBin);
var f : Pilha; m: boolean;
begin
InicializaPilha(f ); m := false;
repeat
if p=nil
then with p do
begin
Visita(p);
if dir=nil then Empilha(f ,dir);
p := esq
end
else if PilhaVazia(f )
then m := true
else Desempilha(f ,p)
until m
end;
6.3. PERCURSO DE

ARVORES BIN

ARIAS 65
Programa 6.7 P os-ordem com pilha explcita
procedure PosOrdem(p: ArvBin);
var f : Pilha; ultimo: ApReg; sobe: boolean;
begin
InicializaPilha(f );
repeat
while p=nil do
begin
Empilha(f ,p); p := p.esq
end;
sobe := true; ultimo := nil;
while sobe and (not PilhaVazia(f )) do
begin
Desempilha(f ,p);
if p.dir=ultimo
then begin
Empilha(f ,p); p := p.dir; sobe := false
end
else begin
Visita(p); ultimo := p
end
end
until PilhaVazia(f )
end;
Uma outra id eia interessante pode ser aplicada para reduzir o espaco utilizado por algoritmos de percurso
em profundidade. Ao inv es de manter a pilha como uma estrutura de dados separada, pode-se embuti-la
dentro da pr opria arvore, a um custo que em certos casos pode ser desprezvel. O algoritmo do Prog. 6.8,
conhecido com o nome de Deutsch, Schorr e Waite (veja por exemplo Knuth [?]), implementa esta id eia
ao inverter os apontadores que est ao no caminho desde a raiz da arvore at e o n o corrente. O m etodo exige,
entretanto, a exist encia nos n os de um campo adicional para distinguir entre as possibilidades de invers ao
do apontador esquerdo ou direito. Esta marca e implementada possivelmente aproveitando-se algum espaco
n ao utilizado do pr oprio n o (um bit e suciente). O Exerccio 18 sugere uma outra soluc ao em que as marcas
formam uma pilha externa ` a arvore, mas ocupam um espaco bem menor do que a pilha de apontadores. Na
vers ao do Prog. 6.8 indicamos de maneira obvia onde devem ser colocados os comandos de visita para a
obtenc ao dos tr es percursos em profundidade. Os tipos foram redenidos para incluir o campo marca.
Deve-se notar como, durante o percurso, a vari avel t aponta para uma lista ligada de n os que constituem
a pilha (as ligac oes entre os elementos da lista usam os campos esq ou dir conforme a marca); a vari avel p
aponta sempre para o n o corrente.
Uma observac ao importante sobre o algoritmo de Deutsch, Schorr e Waite e que ele modica temporari-
amente a estrutura de dados percorrida, mas deixa-a nalmente intacta, exceto possivelmente pelos campos
de marca. Este fato pode tornar impratic avel o uso do algoritmo em certas situac oes, como por exemplo
66 CAP

ITULO 6.

ARVORES BIN

ARIAS
numa base de dados compartilhada por v arios processos concorrentes. Por outro lado, caso seja possvel
incluir as marcas nos n os, o algoritmo realiza o percurso utilizando mem oria auxiliar constante (apenas as
vari aveis do programa).
6.3. PERCURSO DE

ARVORES BIN

ARIAS 67
Programa 6.8 Algoritmo de Deutsch, Schorr e Waite
type
Marcas = (MarcaEsq, MarcaDir);
ApReg = Reg;
Reg =
record
info: M;
marca: Marcas;
esq, dir: ApReg
end;
ArvBin = ApReg;
procedure DeutschSchorrWaite(p: ArvBin);
var t,q: ApReg; sobe: boolean;
begin
t := nil;
repeat
while p=nil do with p do { desce a esquerda }
begin
PreVisita(p); marca := MarcaEsq;
q := esq; esq := t;
t :=p; p := q
end;
sobe := true;
while sobe and (t=nil) do with t do
begin
case marca of
MarcaEsq: begin { desce a direita }
InVisita(t); sobe := false;
marca := MarcaDir; q := p; p := dir;
dir := esq; esq := q
end;
MarcaDir: begin { sobe }
PosVisita(t);
q := dir; dir := p;
p := t; t := q
end
end
until t=nil
end;
68 CAP

ITULO 6.

ARVORES BIN

ARIAS
6.4 Exemplo de aplicac ao: arvores de busca

Arvores bin arias t emmuitas aplicac oes, e algumas delas ser ao vistas mais adiante. Nesta sec ao, mostraremos
uma aplicac ao simples que ser a explorada de maneira mais completa no Captulo 8.
Suponhamos que, numa arvore bin aria, os campos de informac ao cont em objetos que podem ser classi-
cados de acordo com alguma ordem total. Como exemplos poderamos tomar n umeros inteiros (ordenados
de maneira obvia) ou cadeias de caracteres (em ordem alfab etica ou lexicogr aca
12
). Dizemos, ent ao, que
a arvore e uma arvore bin aria de busca se em cada n o da arvore vale a propriedade de que, usando a or-
dem especicada, o valor contido no seu campo de informac ao segue todos os valores contidos nos n os da
sub arvore esquerda e precede todos os valores contidos nos n os da sub arvore direita.
AFig. 6.9 mostra umexemplo de arvore bin aria de busca que cont emos n umeros inteiros 5, 8, 10, 15, 16, 21, 25, 27;
na Fig. 6.10 temos um exemplo de arvore bin aria que cont em os nomes abreviados dos meses, em ordem
alfab etica.
Figura 6.9

Arvore bin aria de busca contendo n umeros
"!
#
5
"!
#
10
"!
#
15

"!
#
8
&
&
&
&

"!
#
25
"!
#
21
t
t
t
"!
#
27
&
&
&
&
"!
#
16

r
r
r
r
r
r
r
r
r
r

Arvores bin arias de busca podem ser utilizadas para manter de maneira eciente tabelas de elementos.

E
muito simples, por exemplo, a vericac ao da presenca ou n ao de um elemento na tabela. O Prog. 6.9 mostra
o exemplo de um procedimento que verica se um elemento x est a contido na arvore de busca apontada por
p, e caso contr ario o insere; o valor nal da vari avel pertence indica se o elemento j a pertencia ` a arvore.
Supusemos neste exemplo a implementac ao da Sec ao 6.2. Utilizamos neste caso a formulac ao recursiva que
torna a elaborac ao mais simples. O uso da recurs ao, neste caso, n ao e estritamente necess ario, pois a busca
pode ser realizada com uma simples malha repetitiva (veja o Exerccio 23).
Deve-se notar que o n umero de operac oes executado pelo procedimento BuscaInsere e proporcional, no
pior caso, ` a profundidade da arvore. De acordo com as propriedades da Sec ao 6.1, a profundidade de uma
arvore bin aria com n n os est a entre log
2
(n + 1) e n. Dizemos que uma arvore bin aria est a balanceada
12
Ordem lexicogr aca e uma generalizac ao da ordem alfab etica que inclui tamb em outros caracteres que n ao letras.
6.4. EXEMPLO DE APLICAC

AO:

ARVORES DE BUSCA 69
Figura 6.10

Arvore bin aria de busca contendo nomes dos meses
"!
#
abr
"!
#
dez
"!
#
ago

t
t
t
"!
#
jan
"!
#
fev
&
&
&
&

"!
#
jun
"!
#
mar
"!
#
mai

t
t
t
"!
#
out
"!
#
set

"!
#
nov
&
&
&
&

"!
#
jul

r
r
r
r
r
r
r
r
r
r
se ela tem profundidade mnima, ou seja log
2
(n + 1). Na pr atica, procura-se manter as arvores de busca
balanceadas de tal maneira que suas profundidades sejam pr oximas da mnima (veja Sec ao 8.1). Pode-se
mostrar tamb em que arvores de busca obtidas por inserc ao em ordem aleat oria t em profundidades m edias
bastante pr oximas desta profundidade mnima.
A remoc ao de um elemento de uma arvore bin aria de busca e ligeiramente mais complicada. Caso o
elemento esteja num n o que e uma folha da arvore, basta substitu-lo por uma sub arvore vazia; no caso de
um n o com apenas uma sub arvore vazia, a remoc ao ainda e simples, substituindo-se o apontador a este n o
por um apontador ` a sua unica sub arvore. Finalmente, quando o elemento a ser removido est a num n o de
grau dois e, portanto, com duas sub arvores n ao vazias, podemos substituir o valor a ser removido pelo maior
valor que o precede (ou o menor valor que o segue) e remover o outro n o.

E f acil vericar que este outro n o
tem o grau zero ou um, recaindo-se no caso anterior (veja tamb em o Exerccio 24).
70 CAP

ITULO 6.

ARVORES BIN

ARIAS
Programa 6.9 Busca e inserc ao numa arvore bin aria de busca
procedure BuscaInsere(var p: ArvBin; x: T; var pertence: boolean);
begin
if p=nil
then begin
pertence := false; new(p);
with p do
begin
esq := nil; dir := nil; info := x
end
end
else with p do
if x=info
then pertence := true
else if x<info
then BuscaInsere(esq,x,pertence)
else BuscaInsere(dir,x,pertence)
end;
6.5. EXERCICIOS 71
6.5 Exercicios
1. Demonstre as Propriedades 1 a 4 da Sec ao 6.1 (p ag. 55).
2. Dizemos que uma arvore e estritamente bin aria se todos os seus n os t em graus 0 ou 2. Qual e a relac ao
entre o n umero total n de n os de uma arvore bin aria estrita e os n umeros n
0
e n
2
(veja a Propriedade
4 da Sec ao 6.1).
3. Caracterize as arvores bin arias para as quais a pr e-ordeme a inordemproduzemos mesmos resultados.
4. Caracterize as arvores bin arias para as quais a pr e-ordeme o percurso emlargura produzemos mesmos
resultados.
5. Mostre que nenhuma das tr es ordens de percurso em profundidade determina sozinha a arvore bi-
n aria da qual ela resulta. Mostre que a pr e-ordem junto com a p os-ordem tamb em n ao e suciente.
Sugest ao: Exiba contra-exemplos para cada caso.
6. Mostre que a pr e-ordem e a inordem (ou a p os-ordem e a inordem) s ao sucientes para determinar
uma arvore bin aria. Sugest ao: Descreva os algoritmos de reconstruc ao, mostrando que em cada
passo h a somente uma escolha.
7. Dada uma arvore bin aria T, dene-se o n umero de Strahler S(T) por:
se T e vazia ent ao S(T) = 0;
se T n ao e vazia, e T
e
e T
d
s ao as duas sub arvores de T, ent ao:
S(T) =

max{S(T
e
), S(T
d
)} se S(T
e
) = S(T
d
)
S(T
e
) + 1 caso contr ario
(a) Escreva um procedimento que calcula os n umeros de Strahler para todas as sub arvores de uma
arvore bin aria, armazenando-os nas suas respectivas razes.
(b) Enumere as arvores bin arias com o n umero mnimo de n os, tal que o seu n umero de Strahler e 3?
(c) Escreva um procedimento de percurso em profundidade de arvores bin arias que, utilizando os
n umeros precalculados de Strahler, minimiza a altura m axima da pilha escolhendo conveniente-
mente em cada passo a sub arvore esquerda ou direita para ser percorrida em primeiro lugar.
8. Suponha que e dada uma colec ao de n os para representar de maneira padr ao uma arvore bin aria. Os
campos esq destes n os formam uma lista ligada que representa a pr e-ordem de uma arvore bin aria;
os campos dir formam a lista (dos mesmos n os) que representa a inordem da mesma arvore. As duas
listas s ao dadas por apontadores aos seus primeiros n os. Escreva um procedimento que reconstr oi a
arvore bin aria correspondente, sem gerar n os adicionais.
9. Escreva procedimentos para a obtenc ao de descric oes lineares (veja p ag. 61) de arvores bin arias com
representac ao padr ao, de acordo com os v arios percursos em profundidade.
72 CAP

ITULO 6.

ARVORES BIN

ARIAS
Programa 6.10 Pr e-ordem com pilha explcita
type
ProxTarefa = (FazVisita, FazPercurso);
RegPilha = record info: ApReg; tarefa: ProxTarefa end;
procedure PreOrdem(p: ArvBin);
var f : Pilha; q: ApReg; t: ProxTarefa;
begin
InicializaPilha(f ); Empilha(f ,p,FazPercurso);
repeat
Desempilha(f ,q,t);
case t of
FazVisita: Visita(q);
FazPercurso: if q= nil
begin
Empilha(f ,dir,FazPercurso);
Empilha(f ,esq,FazPercurso);
Empilha(f ,q,FazVisita)
end
end
until PilhaVazia(f )
end;
10. Escreva procedimentos para reconstruir arvores bin arias a partir das suas descric oes lineares (veja
p agina 61).
11. Escreva procedimentos para realizar os tr es percursos em profundidade de arvores bin arias comple-
tas e quase completas, representadas seq uencialmente. N ao use recurs ao nem estruturas de dados
auxiliares.
12. Note que o procedimento PreOrdem do Prog. 6.2 executa chamadas recursivas mesmo para as sub ar-
vores vazias. Reescreva o procedimento para evitar estas chamadas. Discuta a economia de tempo e
espaco obtida.
13. Uma outra maneira elegante de realizar o percurso em pr e-ordem est a indicada no Prog. 6.10, onde
est a includa a declarac ao do tipo RegPilha da informac ao que deve estar guardada na pilha. Escreva
procedimentos an alogos para realizar os outros dois percursos em profundidade.
14. O que se pode armar sobre o tamanho m aximo alcancado pela la do procedimento PercursoEmLar-
gura do Prog. 6.3?
15. Reescreva o procedimento PercursoEmLargura do Prog. 6.3 de maneira a eliminar a inserc ao de
apontadores nulos na la.
16. Escreva procedimentos para inordem e p os-ordem, an alogos ao procedimento PreOrdem do Prog. 6.4.
6.5. EXERCICIOS 73
Programa 6.11 Algoritmo de Lindstrom e Dwyer
procedure LindstromDwyer(p: ArvBin);
var vazia.q,t: ApReg;
begin
new(vazia); t := vazia;
repeat
if p=nil
then begin q := p; p := t; t := q end
else begin
Visita(p);
q := t; t := p; p := p.esq;
t.esq := t.dir; t.dir := q
end
until p=vazia;
dispose(vazia)
end;
17. Escreva um procedimento para inordem an alogo ao procedimento PreOrdem do Prog. 6.6.
18. Implemente o algoritmo de Deutsch, Schorr e Waite do Prog. 6.8, utilizando em lugar das marcas
em cada n o, uma pilha externa de marcas que indica os campos invertidos no caminho da raiz ao n o
corrente.
19. Considere o procedimento do Prog. 6.11, proposto por Lindstrom [?] e Dwyer [?], para percorrer
arvores bin arias utilizando a representac ao ligada comum. Explique o resultado do percurso realizado
pelo procedimento.

E possvel fazer com que o procedimento realize um dos tr es percursos can onicos
em profundidade?
20. Considere uma representac ao de arvores bin arias proposta por Sikl ossy em [?] em que o campo esq
de cada n o n cont em o resultado da express ao
pai(n) filho esq(n)
e analogamente para o campo dir. Nestas express oes, pai(n), filho esq(n) e filho dir(n) deno-
tam os enderecos dos respectivos n os, e denota a operac ao de ou-exclusivo entre os dgitos na
representac ao bin aria do endereco. Quando algum dos n os n ao existe, utiliza-se o valor nulo. Note-se
que, para quaisquer valores x e y, valemxyx = y e xyy = x. Suponha tamb em que cada n o
cont em um campo de marca que indica se este n o e o lho esquerdo ou direito do seu pai. (Suponha
que o n o raiz e o lho esquerdo do seu pai, que n ao existe). Escreva os procedimentos de percursos
can onicos em profundidade de arvores representadas desta maneira. Os procedimentos n ao devem
modicar a arvore durante o percurso, nem utilizar estruturas de dados auxiliares cujo tamanho possa
depender da pr opria arvore.
74 CAP

ITULO 6.

ARVORES BIN

ARIAS
21. Ache exemplos de ordens em que poderiam ter sido inseridos os elementos nas arvores bin arias de
busca das Figs. 6.9 e 6.10. Existe alguma maneira sistem atica de achar estas ordens?
22. O exerccio anterior apresenta v arias soluc oes; ache uma caracterizac ao de todas elas.
23. Reescreva o procedimento do Prog. 6.9 sem usar recurs ao nem pilha.
24. Escreva um procedimento que remove um elemento dado de uma arvore bin aria de busca; ap os a
remoc ao a arvore deve manter a propriedade de ser de busca.
25. O conceito de arvores bin arias pode ser generalizado
13
para m ultiplas sub arvores, adotando-se a
denic ao: dado um inteiro positivo n, uma arvore n- aria T e um conjunto nito de objetos (n os
ou v ertices) tais que:
ou (a) T e vazio,
ou (b) T consiste de um n o distinto, chamado raiz de T, e de n arvores n- arias disjuntas
T
1
, T
2
, . . . , T
n
, chamadas primeira, segunda, . . ., n- esima sub arvores de T (ou da raiz
de T), respectivamente.
Note que uma representac ao padr ao de arvores n- arias poderia utilizar n os declarados por:
type
ApReg = Reg;
Reg = record
info: M;
lhos: array[1..n] of ApReg
end;
ArvNaria = ApReg;
Estenda, sempre que possvel as noc oes e os algoritmos estudados neste captulo para o caso de arvo-
res n- arias.
13
Um outro tipo de generalizac ao ser a visto no captulo seguinte.
Captulo 7

Arvores gerais
O captulo anterior foi dedicado a um estudo bastante completo de arvores bin arias, uma estrutura que apa-
rece com freq u encia nas aplicac oes. Entretanto existem situac oes nas quais uma arvore bin aria n ao constitui
uma descric ao natural das relac oes entre os objetos a serem manipulados; um exemplo desta situac ao apa-
rece na Fig. 6.2 referente ` a famlia de lnguas indo-europ eias. Cada n o desta gura poderia ter um n umero
vari avel e, emprincpio, ilimitado de descendentes diretos. Outros exemplos s ao as arvores dos descendentes
de um indivduo, da organizac ao hier arquica de uma empresa e da classicac ao biol ogica de esp ecies.
Nas sec oes deste captulo estudaremos as denic oes, propriedades, representac oes ecientes e os al-
goritmos aplic aveis a essas arvores gerais,
1
fazendo refer encias freq uentes aos conceitos correspondentes
relativos ` as arvores bin arias.
7.1 Denic oes e terminologia
Uma arvore geral (ou simplesmente uma arvore) T e um conjunto nito e n ao vazio de objetos (n os ou
v ertices), tais que T consiste de um n o distinto, chamado de raiz de T, e de m 0 arvores disjuntas
T
1
, T
2
, . . . , T
m
, chamadas sub arvores de T (ou da raiz de T).
Note-se que esta denic ao n ao admite o conceito de arvore vazia; por outro lado, um n o pode n ao
ter sub arvores (m = 0). Est a implcita nesta denic ao uma ordem das sub arvores T
1
, T
2
, . . . , T
m
; alguns
autores preferem usar neste caso o termo arvores ordenadas.

E interessante, neste contexto, introduzir mais um conceito: uma oresta (ou uma arboresc encia) e uma
seq u encia nita de arvores. Dada uma oresta F, podemos escrever, portanto, F = (T
1
, T
2
, . . . , T
m
) onde
m 0 e cada T
i
representa uma arvore da oresta F. Deve-se notar que a denic ao de orestas tamb em e
recursiva, pois uma arvore pode ser vista como a sua raiz juntamente com a oresta das suas sub arvores. A
Fig. 7.1 mostra um exemplo de arvore; retirando-se a raiz A, obt em-se uma oresta de quatro arvores, com
as razes B, C, D e E.
Os conceitos de grau, folha, n o interno, pai, lho, irm ao, antepassado, descendente, nvel e altura
denidos na Sec ao 6.1 podem ser adaptados de maneira natural ` as arvores gerais e ser ao deixados para
exerccios.
1
Esta generalizac ao deve ser contrastada com as arvores n- arias introduzidas no Exerccio 25 do Cap. 6.
75
76 CAP

ITULO 7.

ARVORES GERAIS
Figura 7.1 Exemplo de arvore
A
C D
H
E
F G
B
L
I J K
7.2 Representac ao de arvores
Por analogia com arvores bin arias, poderamos representar arvores gerais por meio de n os que inclussem
vetores de apontadores, prevendo algum n umero m aximo grauMax de lhos:
type
ApReg = Reg;
Reg = record
info: M;
grau: 0..grauMax;
lhos: array[1..grauMax] of ApReg
end;
Arvore = ApReg;
onde o campo grau indica o n umero de lhos realmente existentes. Esta representac ao teria dois incon-
venientes. Em primeiro lugar, e necess ario prever um limite m aximo para o grau de cada n o, o que pode
ser difcil em algumas aplicac oes. Em segundo lugar, pode haver um grande desperdcio de mem oria se o
grau de cada n o for, em geral, muito menor do que esse m aximo. Em alguns sistemas (inclusive algumas
implementac oes de PASCAL), e possvel obter-se o efeito de uma declarac ao como
type
ApReg = Reg;
Reg = record
info: M;
grau: 0..grauMax;
lhos: array[] of ApReg
end;
Arvore = ApReg;
onde o n umero de componentes do vetor lhos e indicado quando e alocada uma vari avel din amica do
tipo Reg. Com esta facilidade cariam resolvidos os dois problemas citados. Entretanto, tornam-se mais
7.2. REPRESENTAC

AO DE

ARVORES 77
Figura 7.2 Uma oresta com tr es arvores
D
B
E F G
A
J
K L M
H I
C
N O P
Q
Figura 7.3 Representac ao bin aria de uma oresta com tr es arvores
D
B
E F G
A
J
K L M
H I
C
N O P
Q
complicadas as operac oes sobre arvores que possivelmente modicam o grau de um n o, como a inserc ao e
a remoc ao.
Uma outra alternativa para representar arvores gerais e a utilizac ao de arvores bin arias para representar
orestas de arvores. Considere a oresta de tr es arvores indicada na Fig. 7.2. Suponha agora que cada
n o da foresta e ligado por uma aresta horizontal ao seu irm ao seguinte, quando existir, e por uma aresta
descendente ao seu primeiro lho, tamb em quando este existir. Ao mesmo tempo s ao eliminadas as arestas
originais. O resultado desta operac ao aparece na Fig. 7.3. (Note que as razes A, B e C das tr es arvores s ao
consideradas irm as.)
Se considerarmos as arestas descendentes como sendo as que apontam para lhos esquerdos e as hori-
zontais como as que apontam para lhos direitos, a Fig 7.3 pode ser interpretada como uma arvore bin aria, a
partir da qual pode-se reconstruir facilmente a oresta original (veja o Exerccio 2). A m de enfatizar esta
utilizac ao de arvores bin arias, poderamos utilizar n os declarados por:
78 CAP

ITULO 7.

ARVORES GERAIS
type
ApReg = Reg;
Reg = record
info: M;
irmao, lhos: ApReg
end;
Arvore = ApReg;
A transformac ao indicada neste exemplo pode ser denida de maneira mais precisa, seguindo a pr opria
estrutura recursiva dos objetos envolvidos. Seja F = (T
1
, T
2
, . . . , T
m
) uma oresta com m 0. A arvore
bin aria B(F) que representa F e denida por:
(a) arvore bin aria vazia se F e uma oresta vazia (m = 0);
(b) arvore bin aria cuja raiz cont em a mesma informac ao da raiz de T
1
; cuja sub arvore esquerda
e dada por B((T
11
, T
12
, . . . , T
1m
1
)) onde (T
11
, T
12
, . . . , T
1m
1
) e a oresta das sub arvores
de T
1
; e cuja sub arvore direita e dada por B((T
2
, . . . , T
m
)).
Pode-se denir de maneira an aloga uma transformac ao inversa que associa a cada arvore bin aria T uma
oresta F(T) por ela representada (veja o Exerccio 2).
A representac ao bin aria assim denida resolve os problemas das outras representac oes sugeridas no
incio desta sec ao. Como veremos na sec ao seguinte, existe tamb em uma correspond encia natural entre
percursos de orestas e os percursos em profundidade de arvores bin arias. Note-se tamb em que uma arvore
geral pode ser tratada como uma oresta unit aria, ou seja constituda de uma unica arvore.
Deve-se notar, tamb em, que a representac ao de orestas por meio de arvores bin arias pode ser interpre-
tada como uma lista de listas, semelhante ` as listas generalizadas a serem vistas no Cap. 9.
7.3 Percursos de orestas
Analogamente ` as arvores bin arias, v arias aplicac oes de arvores gerais e de orestas exigem um exame
sistem atico do conte udo de todos os n os. Costuma-se denir, portanto, algumas ordens de percurso naturais.
Seja F = (T
1
, T
2
, . . . , T
m
) uma oresta n ao vazia, onde F
1
= (T
11
, T
12
, . . . , T
1m
1
) e a oresta das sub ar-
vores de T
1
; teremos ent ao:
Pr e-ordem de orestas:
Visitar a raiz de T
1
Percorrer a oresta F
1
em pr e-ordem de orestas
Percorrer a oresta (T
2
, . . . , T
m
) em pr e-ordem de orestas
P os-ordem de orestas:
Percorrer a oresta F
1
em p os-ordem de orestas
Percorrer a oresta (T
2
, . . . , T
m
) em p os-ordem de orestas
Visitar a raiz de T
1
7.4. EXERC

ICIOS 79
Inordem de orestas:
Percorrer a oresta F
1
em inordem de orestas
Visitar a raiz de T
1
Percorrer a oresta (T
2
, . . . , T
m
) em inordem de orestas
No caso da Fig. 7.2 obteramos os seguintes resultados:
Pr e-ordem: A,D,J,E,K,L,F,G,M,B,C,H,I,N,O,Q,P
P os-ordem: J,L,K,M,G,F,E,D,Q,P,O,N,I,H,C,B,A
Inordem: J,D,K,L,E,F,M,G,A,B,H,N,Q,O,P,I,C
Deve-se notar que os mesmos resultados seriam obtidos aplicando-se os percursos correspondentes para
arvores bin arias ` a arvore da Fig. 7.3 que representa a oresta da Fig. 7.2. Esta e uma propriedade geral que
resulta das denic oes das transformac oes B e F (veja o Exerccio 7).
Uma outra observac ao importante refere-se ` a interpretac ao intuitiva dos percursos de orestas. Em pr e-
ordem, a raiz de uma arvore geral e visitada imediatamente antes da visita a todos os seus descendentes;
em inordem de orestas, uma raiz e visitada imediatamente ap os a visita a todos os seus descendentes;
nalmente em p os-ordem de orestas, n ao h a uma interpretac ao t ao natural. Deve-se notar, portanto, que
a pr e-ordem de orestas tem uma interpretac ao intuitiva semelhante ` a pr e-ordem de arvores bin arias, en-
quanto que a inordem de orestas tem uma interpretac ao semelhante ` a p os-ordem de arvores bin arias! Este
fato leva alguns autores a chamarem a inordem de orestas de p os-ordem, e a n ao denirem a terceira ordem
de percurso.
Aimplementac ao dos percursos depende da representac ao utilizada para orestas. No caso da representac ao
bin aria, podemos utilizar todos os variantes estudados na Sec ao 6.3. No caso de outras representac oes, a
implementac ao e bastante obvia e ser a deixada para exerccio.
O percurso em largura de orestas e de arvores gerais pode ser denido de maneira semelhante ` as
arvores bin arias. A sua implementac ao ser a deixada para exerccios.
7.4 Exerccios
1. Redena os conceitos denidos na Sec ao 6.1 relativos a arvores bin arias para as arvores gerais.
2. Dena a transformac ao F(T) mencionada na Sec ao 7.2.
3. Mostre que F(B(F)) = F e B(F(T)) = T para qualquer oresta F e qualquer arvore bin aria T.
4. Transforme para representac ao bin aria a arvore geral da Fig 6.2 referente ` as lnguas indo-europ eias.
5. Por que, no caso de arvores gerais, foi conveniente introduzir-se o conceito de oresta?
6. Suponha que T e uma arvore bin aria completa de altura h. O que se pode armar sobre a forma geral
da oresta F(T)?
7. Demonstre que os tr es percursos em profundidade denidos para orestas s ao equivalentes aos per-
cursos correspondentes de arvores bin arias quando aplicados ` as suas representac oes bin arias.
80 CAP

ITULO 7.

ARVORES GERAIS
8. Escreva os procedimentos de percurso em profundidade para arvores gerais representadas por n os
declarados na p agina 76.
9. Escreva os procedimentos de percurso em largura de arvores gerais representadas por n os declarados
na p agina 76.
10. Escreva os procedimentos de percurso em largura de orestas com representac ao bin aria.
11. Proponha uma representac ao de orestas utilizando o conceito de listas generalizadas a ser visto no
Cap. 9.
Captulo 8

Arvores de busca
O objetivo deste Captulo e o estudo de aplicac oes de arvores no armazenamento e recuperac ao eciente
de informac ao. Na primeira sec ao veremos como podemos manipular arvores de busca bin arias, de modo a
garantir um comportamento logartmico. Na sec ao seguinte, veremos como estruturar informac ao no caso
de utilizac ao de dispositivos de mem oria de massa, tipicamente discos rgidos. Finalmente, veremos o uso
de arvores bin arias quase completas para resolver um problema de prioridades.
8.1

Arvores de altura balanceada
J a vimos na Sec ao 6.4 que arvores bin arias podem ser usadas para guardar e recuperar informac oes, com
n umero de operac oes proporcional ` a altura da arvore, ou seja variando aproximadamente, entre log
2
n e n.
Veremos nesta sec ao, como esta manipulac ao pode ser realizada de maneira a garantir a altura da ordem de
O(log
2
n).
1
Figura 8.1 Exemplos de arvores AVL
0
0 0
0

+
+ 0
0
Dizemos que uma arvore bin aria de busca e de altura balanceada ou do tipo AVL
2
se para todos os seus
n os vale a propriedade de que a diferenca de alturas entre as sub arvores esquerda e direita e no m aximo 1,
1
Escreveremos com frq u encia O(log n), pois log
2
n = log
2
b log
b
n = O(log
b
n) para qualquer base b > 1.
2
Dos nomes dos seus inventores: G. M. Adelson-Velski e E. M. Landis.
81
82 CAP

ITULO 8.

ARVORES DE BUSCA
Figura 8.2

Arvores de Fibonacci

F
4

0 0

F
3
0
0

0
F
2
F
1

F
h2
F
h
F
h1
0
F
0
nil
em valor absoluto. A diferenca entre as alturas direita e esquerda e chamada fator de balanceamento. Nos
exemplos da Fig. 8.1, os smbolos ,0 e + denotam os fatores 1, 0 e +1.
A m de calcular a altura m axima de uma arvore AVL, consideremos a famlia de arvores F
h
com
n umero mnimo de n os N(h), xada a altura h. Sem perda de generalidade, suporemos que a sub arvore
esquerda e sempre a mais alta. Esta famlia de arvores, chamadas de arvores de Fibonacci, est a exibida na
Fig. 8.2.

E f acil concluir que o n umero de n os de uma arvore de Fibonacci de altura h e dado por:
N(h) = N(h 1) +N(h 2) + 1, h 2
de onde resulta N(h) = f
h+2
1, onde f
i
e o i- esimo n umero de Fibonacci. Lembrando que f
i

((1 +

(5))/2)
i
/

(5), demonstra-se que uma arvore de Fibonacci com n n os tem a altura aproximada de
1, 44 log
2
(n + 2), que e o pior caso para arvores AVL.
Explicaremos a seguir o algoritmo de busca e inserc ao numa arvore AVL, de maneira a preservar esta
propriedade. Suporemos um algoritmo recursivo que p ara t ao logo a altura da arvore n ao muda, ap os a
inserc ao:
Caso 1: Inserc ao em arvore vazia
0
h = 0 h = 1
nil
8.1.

ARVORES DE ALTURA BALANCEADA 83
A altura nal aumenta.
Caso 2: Inserc ao do lado mais baixo
0
h h
+
A altura nal permanece inalterada (o processo de inserc ao p ara).
Caso 3: Inserc ao quando as duas alturas s ao iguais
h
h+1
0
A altura nal aumenta.
Caso 4: Inserc ao do lado mais alto
h

Deixa de ser AVL. H a dois subcasos:


(4a): Caminho LL (esquerdo, esquerdo) rotac ao simples

A
B
B
A h
T
3
T
3
0
0 0
h
h2 h2
h2
h1
h2 h2
T
1
T
2
T
1
T
2
A altura nal permanece inalterada (o processo de inserc ao p ara).
84 CAP

ITULO 8.

ARVORES DE BUSCA
(4b): Caminho LR (esquerdo, direito) rotac ao dupla
C
B
0
C
X Y

A
T
3
h3
h2
h h
0
h2
h2
3
T
h2
T
21
T
22
T
22
T
21
h3
h3
h2
X Y
0
/0
0/+
T
1
T
1
A B
O n o inserido pode ser X ou Y. Quando h=2, as arvores T
1
e T
3
s ao vazias, e o n o inserido e o
pr oprio n o C; neste caso as arvores T
21
e T
22
s ao vazias.
A altura nal permanece inalterada (o processo de inserc ao p ara)
Existem tamb em os casos sim etricos 2, 3 e 4 quando a inserc ao e realizada do lado direito da raiz. O
Prog. 8.1 mostra o esboco da rotina recursiva.

E simples vericar que o n umero de operac oes necess arias para inserir um valor numa arvore AVL e
proporcional ` a sua altura. De acordo com o que vimos, o valor da altura n ao passa de aproximadamente
1, 44 log
2
n, o que garante a eci encia do algoritmo.
O algoritmo de remoc ao de um valor, preservando-se as propriedades de arvores AVL, e um pouco mais
complexo e comp oe-se de duas partes. Em primeiro lugar, a remoc ao de um n o arbitr ario e substituda pela
remoc ao de uma folha. Para tanto, existem tr es casos possveis:
1. o n o tem grau zero e, portanto, j a e uma folha;
2. o n o tem grau um pela propriedade AVL, a sua unica sub arvore e necessariamente constituda por
uma folha, cujo valor e copiado para o n o pai; o n o a ser eliminado e a folha da sub arvore;
3. o n o tem grau dois o seu valor e substitdo pelo maior valor contido na sua sub arvore esquerda (ou
o menor valor contido na sua sub arvore direita); o n o que continha o menor (ou maior) valor copiado
tem necessariamente grau zero ou um, recaindo num dos casos anteriores.
A segunda parte do algoritmo consiste, portanto, na remoc ao de uma folha. O processo e semelhante
` a inserc ao e ilustrado a seguir de maneira an aloga. Sup oe-se, em cada caso, que o algoritmo retorna da
remoc ao de um n o numa sub arvore esquerda, com diminuic ao de altura, e e analisado o efeito para a raiz
corrente. Se houver novamente diminuic ao de altura, o algoritmo continua retornando pelo caminho de
descida; caso contr ario, o algoritmo p ara.
Caso 1: Remoc ao de uma folha
0
h = 1 h = 0
nil
A altura diminui (o processo continua).
8.1.

ARVORES DE ALTURA BALANCEADA 85
Caso 2: Alturas iguais
0
h+1 h+1
+
A altura permanece inalterada (o processo p ara).
Caso 3: Remoc ao do lado mais alto
h+1 h+2
0
A altura diminui (o processo continua).
Caso 4: Remoc ao do lado mais baixo
h
h+2
+
H a tr es subcasos, dependendo do fator de balanceamento do lho direito da raiz:
86 CAP

ITULO 8.

ARVORES DE BUSCA
Programa 8.1 Esboco da rotina de busca e inserc ao em arvore AVL
procedure BuscaInsere(var p: ArvAVL; k: TipoChave;
inf : TipoInfo; var h: boolean; var q: Arvore);
{ O par ametro h indica se a altura p da arvore cresceu;
q apontar a para o n o que cont em a chave k.}
var p1,p2: ArvAVL;
begin
if p=nil then {N ao achou}
begin
new(p); h := true;
with p do
begin
bal := zero; chave := k; info := inf ;
esq := nil; dir := nil
end
end
else
if k<p.chave then {Desce ` a esquerda}
begin BuscaInsere(p.esq,k,inf ,h,q);
if h then {Sub arvore esquerda cou mais alta}
case p.bal do
mais: begin p.bal := zero; h := false end;
zero: p.bal := menos;
menos: {Rebalancear}
begin
p1 := p.esq;
if p1.bal=menos then {Rotac ao simples LL}
begin ... end
else {Rotac ao dupla LR}
begin ... end;
p.bal := zero; h := false
end
end {case}
end
else if k>p.chave then {Desce ` a direita}
begin {An alogo ao caso de descer ` a esquerda} end
else h := false {Achou!}
end;
8.1.

ARVORES DE ALTURA BALANCEADA 87
(4a): Fator 0 (rotac ao simples RR)
T
1
A
+
T
1
T
2
h
A
+
T
3
T
3
B
B
0
h1
h
h+2
h
h+2

h
2
T
h1
A altura permanece inalterada (o processo p ara).
(4b): Fator + (rotac ao simples RR)
T
3
T
3
B
T
1
T
2
h1
T
2
h1
h1
h
h+2
h
A
+
+
h+1 A
0
B
0
A altura diminui (o processo continua).
(4c): Fator - (rotac ao dupla RL)
T
1
T
2
T
3
T
4
A
+
B

C
?
h1
T
1
T
2
T
3
T
4
C
A B
h1
h+1
0
0/+ /0
h1
h+2
h1
A altura diminui (o processo continua).
88 CAP

ITULO 8.

ARVORES DE BUSCA
8.2

Arvores de tipo B
Vimos na sec ao anterior que e possvel utilizar arvores bin arias para armazenar e recuperar informac ao,
garantindo que o tempo de execuc ao das rotinas ser a da ordem O(log
2
n). Entretanto, quando se trata de
dados arquivados em dispositivos de mem oria externa, como discos rgidos, mesmo este desempenho n ao
e satisfat orio. A Fig. 8.3 indica, esquematicamente, o funcionamento de um disco magn etico e ajuda a
entender a disparidade entre tempos de acesso.
O tempo total de um acesso ao disco e constitudo pela soma de tr es parcelas:
tempo de busca
3
S
tempo de lat encia L
tempo de transfer encia de dados T
Os tempos S e L variam aleatoriamente, conforme a localizac ao dos dados no disco e a posic ao do
mecanismo de acesso no incio da operac ao; T depende basicamente da quantidade de dados a serem
transferidos. A soma destas tr es parcelas costuma ser ordens de grandeza maior do que os tempos de acesso
` a mem oria principal.
Por outro lado, note-se, por exemplo, que altura mnima de uma arvore bin aria que cont em 1.024 n os
e 10; para uma arvore com 1 milh ao de n os, esta altura ser a de 20. O n umero de acessos ` a estrutura
nos algoritmos de busca e inserc ao e proporcional a esta altura. Este n umero de acessos e aceit avel para
estruturas residentes na mem oria principal, mas torna-se proibitivo para mem orias externas. Nestes casos,
o tempo de execuc ao de algoritmos e dominado pelo tempo de acesso, assim a preocupac ao principal e
diminuir o n umero deles. Uma soluc ao obvia para este problema e diminuir a altura da arvore, aumentando
signicativamente o grau dos seus n os. Al em disto, deve-se garantir que a altura n ao crescer a al em de
um certo limite. Uma das estruturas mais utilizadas neste caso s ao as arvores do tipo B (ou arvores B),
semelhantes ` as arvore n- arias denidas no Cap. 6.
T e uma arvore B de ordem b 2 se
1. todas as folhas de T t em o mesmo nvel;
2. cada n o interno tem um n umero vari avel r de registros e r + 1 de lhos, onde

b/2 r b se n o = raiz
1 r b se n o = raiz
3. cada folha tem um n umero vari avel r de registros obedecendo ` a mesma restric ao do item
anterior;
4. os campos de informac ao contidos nos registros obedecem ` a propriedade de arvores de
busca.
3
Em ingl es seek.
8.2.

ARVORES DE TIPO B 89
Figura 8.3 Funcionamento esquem atico de discos magn eticos
1
0
2
3
4
5
mecanismo de acesso
trilha mais
externa
trilha mais
interna
superfcies

S
L
90 CAP

ITULO 8.

ARVORES DE BUSCA
Figura 8.4 Exemplo de arvore B de ordem 3
125
83
35 51 85 20
50 17
48 5 3 80 120
203
150 205
A Fig. 8.4 apresenta um exemplo de arvore B de ordem 3.
4
Note que, neste caso, cada n o da arvore
cont em de 1 a 3 registros de dados. Na pr atica, as ordens s ao muito maiores, sendo tipicamente 255 ou 511.
A tabela seguinte indica os n umeros mnimos e m aximos de registros de dados que podem estar contidos
em nveis 1 a 4 de uma arvore B de ordem 255.
mnimo m aximo
nvel n os registros n os registros
1 1 1 1 1 255
2 2 2 127 256 256 255
3 2 128 2 128 127 256
2
256
2
255
4 2 128
2
2 128
2
127 256
3
256
3
255
Total 33.027 4.194.303 16.843.009 4.294.967.295
Os n umeros desta tabela mostram que, numa arvore de ordem 255, de altura 4, podemos guardar entre
4 10
6
e 4 10
9
registros de dados. Isto certamente cobre a maior parte de aplicac oes. Note-se que para
uma arvore de altura 5, o mnimo seria da ordem de 5 10
7
. Conclui-se que o n umero de acessos para
encontrar um dado numa arvore B tpica n ao passa, na pr atica, de 4. Se supusermos que a raiz reside sempre
na mem oria principal, este n umero reduz-se a 3. Note-se que uma arvore bin aria de altura mnima que
contivesse 4 10
6
registros teria a altura aproximada de 22.
A implementac ao de arvores B pode utilizar as t ecnicas j a vistas nos Caps. 6 e 7. Por exemplo, um n o
de uma arvore B de ordem 255 poderia seguir as declarac oes:
const ordem = 255;
type
ApReg = Reg;
Reg = record
numregs: 0..ordem;
lhos: array[0..ordem] of ApReg
info: array[1..ordem] of M;
end;
ArvB = ApReg;
Sup oe-se que os elementos do n o seguem a representac ao natural indicada na Fig. 8.4. Assim, a informac ao
contida em info[1] e maior do que as informac oes contidas na sub arvore lhos[0] e menor do que as con-
tidas na sub arvore lhos[1]. Os campos de informac ao dentro de um n o est ao em ordem crescente. Deve-se
4
Alguns autores utilizam um conceito diferente de ordem.
8.2.

ARVORES DE TIPO B 91
observar que simplicamos a discuss ao supondo que a arvore est a sendo manipulada na mem oria, pois uti-
liza ainda o conceito de apontadores. Numa implementac ao real, com a arvore em disco, utilizaramos os
enderecos no disco, an alogos aos apontadores.
O algoritmo de busca em arvore B e bastante elementar, an alogo ` as arvores de busca do Cap. 6 e n ao
ser a apresentado aqui. Note-se apenas que, feito acesso a um n o, a busca do valor dado no vetor info pode
ser feita utilizando-se a t ecnica de busca bin aria uma vez que os dados est ao ordenados.
O algoritmo de inserc ao e um pouco mais complexo e ser a apresentado atrav es de uma rotina auxiliar
recursiva InsereRecArvB(p,s,x,h) esbocada no Prog. 8.3 e alguns diagramas que esclarecem os v arios casos
que ocorrem neste processo. Os par ametros p e x denotam a arvore e o valor a ser inserido. Ao retornar,
a vari avel h indicar a se houve necessidade de quebra do n o em dois n os; neste caso, a vari avel x conter a o
valor que deve car entre os valores contidos nos novos n os, e a vari avel s apontar a para o n o que deve car
` a direita de x; por construc ao, o n o anterior car a ` a esquerda. O valor devolvido pela func ao ser a falso se o
valor x fornecido j a ocorre na arvore. O Prog. 8.2 indica a chamada inicial da rotina de inserc ao.
Programa 8.2 Rotina de busca e inserc ao em arvoreB
function InsereArvB(var p: ArvB; var x: M): Boolean;
{ Devolve

false

se

x

j a ocorre na arvore

p

. }
var h: Boolean; q,s: ArvB;
begin
InsereArvB := InsereRecArvB(p,s,x,h);
if h
then begin
new(q);
with q do
begin
numregs := 1;
lhos[0] := p; lhos[1] := s;
info[1] := x
end;
p := q
end
end;
92 CAP

ITULO 8.

ARVORES DE BUSCA
Programa 8.3 Esboco da rotina auxiliar de busca e inserc ao em arvoreB
function InsereRecArvB(var p,s: ArvB; var x: M; var h: Boolean): Boolean;
var i: 0..ordem;
begin
if p=nil
then begin
h := true;
s := nil;
InsereRecArvB := true
end
else with p do
begin
i := {menor ndice

j

tal que

xinfo[j]

; sen ao,

j=(numregs+1)

};
if (iordem) and (x=info[i])
then begin
h := false;
InsereRecArvB := false
end
else begin
InsereRecArvB := InsereRecArvB(lhos[i1],s,x,h);
if h
then begin
{Insere

x

e

s

na posic ao

i

dos vetores

info

e

lhos

; se necess ario, sup oe que existe uma


posic ao adicional em cada vetor};
inc(numregs);
if numregsordem
then h := false
else begin
{Quebra o n o

p

; a primeira metade
permanece em

p

; o valor do meio e
atribudo a

x

; a segunda metade e
copiada para um novo n o alocado em

s

};
h := true
end
end
end
end
end;
8.2.

ARVORES DE TIPO B 93
Caso 1:

Arvore vazia
h: verdadeiro s : nil
Caso 2: r < b
x
i
x
i+1
x x:
x
i
x
i+1
T
s:
x
i
x
i+1
(chamada recursiva)
1 i i+1 r
... ...
b
1 i i+1 r
... ...
b
x: x
1 i i+1
... ...
r b
T
x
h: verdadeiro
h: falso
94 CAP

ITULO 8.

ARVORES DE BUSCA
Caso 3: r = b
x
i
x
i+1 p:
x
1 i i+1
...
b
...
x:
T
s:
x
i
x
i+1 p:
y
k
T
k
T
b+1
p:
1
...
b k
x
i
x
i+1 p:
(chamada recursiva)
h: verdadeiro
1 i i+1
...
b
...
x:
x
equivale a
1 i i+1
...
b
...
T
x
onde k = b/2 + 1.
(continua)
8.2.

ARVORES DE TIPO B 95
y
k1
1
...
b k
p:
y
k
x:
T
k
T
b+1
s:
1
...
b k
h: verdadeiro
A seguir, o algoritmo de inserc ao e apresentado atrav es de exemplos.
Caso 1: Inserc ao do elemento 81 a folha tem espaco para mais um elemento:
125
83
35 51 85 20
50 17
48 5 3 80 120
203
150 205
125
83
35 51 85 20
50 17
48 5 3 80 120
203
150 205 81

E f acil ver que neste caso haver a, no m aximo, h +1 acessos ao disco (h leituras e 1 gravac ao) onde h
e a altura da arvore.
96 CAP

ITULO 8.

ARVORES DE BUSCA
Caso 2: Inserc ao do elemento 33 Estouro da folha provoca subida da mediana dos b + 1 registros e
divis ao dos restantes em dois n os, com b/2 e b/2 registros, respectivamente:
17
5 3 85 120 51 80 20 33 48
83
125 50
35
125
83
35 51 85 20
50 17
48 5 3 80 120
Neste caso, haver a, no m aximo h leituras e 2h + 1 gravac oes, supondo que h a estouro em todos os
nveis.
Note-se que estas operac oes podem envolver uma movimentac ao razo avel de dados dentro dos n os, mas
elas ser ao realizadas na mem oria principal, assim que em termos de eci encia o fator dominante ser a ainda
o n umero de acessos ao disco que claramente e da ordem O(h), ou seja O(log
b
n).
O algoritmo de remoc ao segue a mesma losoa de manter as propriedades de arvore B. Uma remoc ao
sempre pode ser reduzida ` a remoc ao de um elemento de uma folha; caso ele n ao esteja na folha, ele pode
ser trocado com o primeiro elemento que o segue (ou o ultimo que o precede) na arvore este elemento
estar a numa folha. Por exemplo, se quisermos remover o elemento 83 da Fig. 8.4, poderemos colocar em
seu lugar o elemento 85 (ou 80), caindo assim no caso de remoc ao de uma folha. O algoritmo de remoc ao
ser a apresentado somente atrav es de exemplos.
8.2.

ARVORES DE TIPO B 97
Caso 1: Remoc ao do elemento 51 a folha ainda tem o n umero mnimo b/2 de registros:
125
83
35 51 85 20
50 17
48 5 3 80 120
203
150 205
125
83
35 85 20
50 17
48 5 3 120
203
150 205 80
Neste caso, haver a, h leituras e 1 gravac ao.
Caso 2: Remoc ao do elemento 85 o n umero de elementos cai abaixo do mnimo b/2, mas um dos n os
irm aos tem mais do que o mnimo de elementos, permitindo um empr estimo atrav es do n o pai; no
caso ser ao movidos 80 e 83:
125
83
35 51 85 20
50 17
48 5 3 80
203
150 205
125
35 51 20
50 17
48 5 3
203
150 205 83
80
Neste caso, haver a, no pior caso, h + 2 leituras e 3 gravac oes.
Caso 3: Remoc ao do elemento 150 o n umero de elementos cai abaixo do mnimo b/2 e n ao h a possi-
bilidade de empr estimo; neste caso existe um n o irm ao que tem b/2 registros, e juntando este n o
com a folha em quest ao e incluindo o elemento do n o pai que separa os dois, obt em-se um novo n o
98 CAP

ITULO 8.

ARVORES DE BUSCA
cheio; este processo pode ser propagado at e a raiz:
35 51 20
50 17
48 5 3 80
85 203 205
125
83
125
83
35 51 85 20
50 17
48 5 3 80
203
150 205
Neste caso, haver a, no pior caso, 3h 2 leituras e 2h 1 gravac oes.
Conclui-se que a remoc ao tamb em pode ser realizada com n umero de acessos da ordem O(h).
Deve-se notar, nalmente, que existem variantes de arvores B, como B
+
e B

descritos na literatura
veja, por exemplo, [?].
8.3

Arvores digitais
Conjuntos de cadeias de caracteres podem ser representados por arvores digitais em que as arestas s ao
rotuladas com caracteres consecutivos das cadeias. Por exemplo, o conjunto das palavras inglesas:
a an and are as at be
but by for from had have he
her his i in is it no
not of on or
pode ser representado pela arvore da Fig 8.5. Nesta representac ao, os n os da forma indicam o m de uma
cadeia.
Uma representac ao possvel para arvores digitais e utilizar arvores n- arias de grau do tamanho do alfa-
beto utilizado (por exemplo, 26) com uma marca booleana para indicar um n o :
a b c z y
...
8.3.

ARVORES DIGITAIS 99
Figura 8.5 Exemplo de arvore digital
a
o
i
o
h
n
n
r s
t e
u
y
o r
i
t
e
n
o
f
n
r
d
e
t
r
d t
m
e
b
f
a
s
v s r
Com esta representac ao, o apontador pode ser selecionado utilizando-se o pr oprio caractere como ndice;
desta maneira, o tempo de busca torna-se proporcional ao comprimento da cadeia. H a, entretanto, um grande
desperdcio de mem oria: dos 39 26 = 1014 campos apontadores do exemplo, apenas 38 s ao n ao nulos.
Este desperdcio de mem oria pode ser reduzido em parte utilizando um formato especial para as folhas, sem
o vetor; no caso do exemplo, haveria reduc ao para 19 26 = 494 campos apontadores, dos quais 38 n ao
nulos. Pode-se tamb em modicar a representac ao, com folhas especiais, juntando cadeias quando h a uma
unica possibilidade de continuar na arvore; no caso do exemplo, restariam 12 n os comuns com 312 campos
apontadores, dos quais 31 n ao nulos, como mostra a Fig. 8.6.
Figura 8.6 Representac ao modicada de arvore digital
re
d
s t e y ut or rom
d ve r
is n s t
t
f n r
a
o
i h
n
n
r s
t e
u
y
o r
i
t
e
n
o
f
n
r
d
d t
b
f
a
s
v r

Arvores digitais s ao ecientes na fatorac ao de prexos comuns das cadeias representadas. Em casos
em que h a tamb em muito compartilhamento de suxos comuns, e interessante utilizar-se aut omatos nitos
acclicos minimais. Por exemplo, as 15 formas dos verbos ingleses do, redo e undo seriam representadas
pelo aut omato da Fig. 8.7.
Supondo a utilizac ao de folhas especiais (sem vetores), este aut omato teria 1126 = 286 campos apon-
tadores, dos quais 16 n ao nulos; a arvore digital correspondente teria 26 26 = 676 campos apontadores,
dos quais 37 n ao nulos. Deve-se notar, entretanto, que a construc ao de um aut omato como este e muito mais
complicada e demorada do que de uma arvore digital.
100 CAP

ITULO 8.

ARVORES DE BUSCA
Figura 8.7 Exemplo de aut omato
g
n
d
r e
u
n
d
i
o
e
i
n
d
s
e
8.4 Filas de prioridade
Uma outra aplicac ao de arvores bin arias e exemplicada por las de prioridade usadas para selecionar ou
remover ecientemente o maior (ou o menor) elemento de uma colec ao.
Uma la de prioridade e uma arvore bin aria que tem as seguintes propriedades:
1. a arvore e completa ou quase completa;
2. em cada n o da arvore, o valor da chave e maior do que os valores das chaves dos lhos.
Figura 8.8 Exemplo de la de prioridade
5
45
4
30
6
40
7
38
3
75
1
95
2
88
15 10 23
8 9 10
A Fig. 8.8 mostra um exemplo desta estrutura. Conforme foi visto na Sec ao 6.2, arvores quase comple-
tas podem ser implementadas ecientemenete utilizando vetores; neste caso a la de prioridade costuma ser
chamada de heap. Ela pode ser percorrida facilmente utilizando-se as f ormulas vistas na p ag. 57. No caso
do nosso exemplo, teramos:
1 3 4 5 6 7 8 9 10 2
95 88 75 30 45 40 38 10 15 23
8.4. FILAS DE PRIORIDADE 101
A determinac ao do maior elemento da la e obviamente trivial e muito eciente pois e o elemento que
est a na raiz da arvore, isto e, na primeira posic ao do heap. Vericaremos que as operac oes de inserc ao e
remoc ao de elementos do heap tamb em podem ser realizadas com eci encia, mantendo-se a propriedade da
estrutura. Primeiramente, veremos atrav es de exemplos duas operac oes b asicas de subida e de descida de
elementos na arvore.
Suponhamos que na primeira posic ao disponvel (isto e, 11) do nosso exemplo foi colocado um novo
elemento cujo valor e 90. Este elemento pode ser deslocado, por meio de trocas sucessivas, no sentido da
raiz da arvore, at e encontrar a posic ao em que ser a satisfeita a denic ao de heap. A Fig. 8.9 ilustra os estados
inicial e nal desta operac ao.
Figura 8.9 Operac ao de subida de um elemento no heap
3
75
1
95
2
15 10 23
8 9 10
7
38
6
40
5 4
30
45
88
90
11
3
75
1
95
2
88
15 10 23
8 9 10
7
38
6
40
5
45
4
30
90
11
Analogamente, suponhamos que temos um heap no qual apenas um elemento n ao satisfaz a denic ao
por n ao ser maior do que os elementos contidos nos seus lhos. Podemos deslocar este elemento na direc ao
das folhas at e que ele encontre uma posic ao v alida. Fig. 8.10 ilustra esta operac ao.
A programac ao destas operac oes e simples, adotando-se, por exemplo, as declarac oes:
102 CAP

ITULO 8.

ARVORES DE BUSCA
Figura 8.10 Operac ao de descida de um elemento no heap
3
75
1
95
2
15 10
8 9 10
7
38
6
40
5 4
30
13
88
23
3
75
1
95
2
15 10 23
8 9 10
7
38
6
40
5 4
30
88
13
const nMax = ...;
type
Indice = 0 .. nMax;
Heap = record
vetor: array [1..nMax] of T;
n: Indice { Comprimento corrente }
end;
As rotinas b asicas est ao indicadas no Prog. 8.4.

E f acil vericar que cada uma das rotinas realiza da ordem
de O(log n) operac oes, proporcional ` a altura da arvore.
Utilizando estas rotinas podemos programar as operac oes de construc ao inicial, inserc ao e remoc ao de
um heap, conforme mostra o Prog. 8.5. Note-se que a remoc ao e sempre feita na raiz, devolvendo o elemento
m aximo. No caso de construc ao, indicamos duas vers oes diferentes. Pode-se mostrar que o procedimento
ConstroiHeap realiza O(nlog n) operac oes enquanto que o procedimento OutroConstroiHeap realiza O(n)
operac oes. Veremos na Sec ao 13.3 como estas rotinas podem ser usadas para obter um algoritmo eciente
de ordenac ao.
8.4. FILAS DE PRIORIDADE 103
Programa 8.4 Operac oes b asicas para heap
procedure Sobe(var a: Heap; m: Indice);
var j: Indice; x: T;
begin
with a do
begin
x := vetor[m];
j := m div 2;
while (j1) and (vetor[j]<x) do
begin
vetor[m] := vetor[j];
m := j; j := j div 2
end;
vetor[m] := x
end
end;
procedure Desce(var a: Heap; m: Indice);
var k: Indice; continua: boolean; x: T;
begin
with a do
begin
x := vetor[m]; k := 2m;
continua := true;
while continua and (kn) do
begin
if k<n then
if vetor[k]<vetor[k+1]
then k := k+1;
if x<vetor[k]
then
begin
vetor[m] := vetor[k];
m := k;
k := 2k
end
else continua := false
end;
vetor[m] := x
end
end;
104 CAP

ITULO 8.

ARVORES DE BUSCA
Programa 8.5 Rotinas de manipulac ao de heaps
procedure ConstroiHeap(var a: Heap);
var m: Indice;
begin
with a do
for m:=2 to n do Sobe(a,m)
end;
procedure OutroConstroiHeap(var a: Heap);
var m: Indice;
begin
with a do
for m:=n div 2 downto 1 do Desce(a,m)
end;
procedure InsereHeap(var a: Heap; x: T);
begin
with a do
begin
n := n+1;
vetor[n] := x;
Sobe(a,n)
end
end;
function RemoveHeap(var a: Heap): T;
begin
with a do
begin
RemoveHeap := vetor[1];
vetor[1] := vetor[n];
n := n1; Desce(a,1)
end
end;
8.5. EXERC

ICIOS 105
8.5 Exerccios
1. Demonstre que o n umero de n os de uma arvore de Fibonacci de altura h descrita na Sec ao 8.1 e dado
por N(h) = f
h+2
1.
2. Complete a rotina exibida no Prog. 8.1.
3. Escreva uma func ao que verica se uma arvore dada tem alturas balanceadas. Suponha que a arvore
n ao cont em os fatores de balanceamento. Sugest ao: A func ao deve devolver tamb em a altura da
arvore.
4. Implemente o algoritmo de remoc ao de arvores AVL seguindo a explicac ao da Sec ao 8.1.
5. Podemos generalizar o conceito de arvores de altura balanceada, impondo que o fator de balancea-
mento seja no m aximo k, em valor absoluto, sendo este um valor prexado.
Calcule a altura m axima de uma arvore deste tipo, em func ao de k e do n umero de n os n.
Desenvolva os algoritmos de inserc ao e de remoc ao an alogos aos discutidos para as arvores
AVL.
6. Descreva numa notac ao mais precisa os algoritmos de inserc ao e de remoc ao em arvores B, sem entrar
em muitos pormenores de programac ao.
7. Justique as conclus oes obtidas sobre os n umeros de acesso ao disco para os algoritmos de inserc ao
e de remoc ao em arvores B.
106 CAP

ITULO 8.

ARVORES DE BUSCA
Captulo 9
Listas Gerais
Este captulo cobrir a uma generalizac ao dos conceitos de estruturas lineares vistas no Cap. 4.
9.1 Conceitos e implementac ao
Dizemos que uma lista generalizada e uma seq u encia linear em que cada elemento ou e um atomo, ou e uma
lista generalizada. O conceito de atomo depende da aplicac ao, mas poder a ser um inteiro, um nome, um
registro de informac oes ou outra estrutura qualquer que n ao seja tratada como lista neste contexto. Note-se
que o conceito de lista generalizada foi denido de maneira recursiva.
Utilizaremos, ` as vezes, uma notac ao parent etica para descrever listas generalizadas. Nesta notac ao, cada
lista ter a a forma
(
1
,
2
, . . . ,
n
)
onde
i
denota um atomo ou uma lista generalizada, conforme a denic ao acima. Indicaremos alguns
exemplos destas listas, dando um nome a cada uma:
A: ((4,7),(4,7,(8)))
B: ((1,4),(7,8))
C: (3,B,B)
D: (5,8,D)
E: ()
As listas A, B, C, D e E t em, respectivamente, 2, 2, 3, 3 e 0 elementos.
As listas C e D podem ser expandidas com as denic oes correspondentes:
C: (3,((1,4),(7,8)),((1,4),(7,8)))
D: (5,8,(5,8,(5,8,(...))))
Note-se que a lista D, apesar de ter tr es elementos, inclui um n umero innito de inteiros. Este fato deve-se
obviamente ` a denic ao recursiva desta lista.
Para representar na mem oria as listas generalizadas, podemos usar as v arias t ecnicas vistas no Cap. 3.
Por exemplo, usando as listas ligadas simples, poderamos representar os exemplos acima como indicado
na Fig. 9.1. Neste caso, utilizamos a representac ao compartilhada em que as v arias listas repetidas s ao
representadas uma unica vez como e o caso da lista B. Uma outra opc ao, necess aria em algumas aplicac oes,
107
108 CAP

ITULO 9. LISTAS GERAIS


Figura 9.1 Implementac ao compartilhada de listas
4 7
8 7 4
7 8
1 4
5 8
3 C:
B:
A:
D:
E:
nil
seria expandir as denic oes das listas; neste caso teramos a representac ao da Fig. 9.2. Como e natural, neste
caso, n ao poderemos representar adquadamente a lista D. Note-se que nos dois casos haver a necessidade
de incluir em cada n o da estrutura uma marca que indique se o elemento e um atomo ou uma lista.
A implementac ao destas id eias e a formulac ao de algoritmos que manipulam estas listas resulta natural-
mente da discuss ao acima. Indicamos no Prog. 9.1 a implementac ao de uma func ao que conta os atomos
de uma lista. Esta vers ao n ao funciona para listas que t em alguma circularidade como e o caso da lista D.
Al em disto, a contagem dos atomos e realizada como se a representac ao fosse feita com c opia. Por exemplo,
o resultado seria 9 para a lista C qualquer que fosse a representac ao. O Prog. 9.2 traz uma outra soluc ao que
funciona para qualquer lista e cujo resultado indica exatamente o n umero de atomos usado na representac ao.
Esta vers ao sup oe que todos os campos visitado da estrutura t em inicialmente o valor false; estes campos
t em o seu valor modicado para true durante a execuc ao.
9.1. CONCEITOS E IMPLEMENTAC

AO 109
Figura 9.2 Implementac ao de listas com c opia
4 7
8 7 4
7 8
1 4
7 8
1 4
7 8
1 4
3
E:
nil
C:
B:
A:
D:
...
5
5 8
5 8
8
110 CAP

ITULO 9. LISTAS GERAIS


Programa 9.1 Contagem de atomos de uma lista
type
ApReg = Reg;
ListaGen = ApReg;
Reg = record
prox: ApReg;
case ElementoAtomo: boolean of
true: (atomo: integer);
false: (lista: ListaGen)
end;
function ContaAtomos(p: ListaGen): integer;
var s: integer;
begin
s := 0;
while p=nil do with p do
begin
case ElementoAtomo of
true: s := s+1;
false: s := s+ContaAtomos(lista)
end;
p := prox
end;
ContaAtomos := s
end;
9.1. CONCEITOS E IMPLEMENTAC

AO 111
Programa 9.2 Contagem de atomos de uma lista vers ao mais geral
type
ApReg = Reg;
ListaGen = ApReg;
Reg = record
visitado: boolean;
prox: ApReg;
case ElementoAtomo: boolean of
true: (atomo: integer);
false: (lista: ListaGen)
end;
function ContaAtomos(p: ListaGen): integer;
var s: integer;
begin
s := 0;
while p=nil do with p do
begin
if not visitado then
begin
visitado := true;
case ElementoAtomo of
true: s := s+1;
false: s := s+ContaAtomos(lista)
end
end;
p := prox
end;
ContaAtomos := s
end;
112 CAP

ITULO 9. LISTAS GERAIS


9.2 Exemplo: polin omios em m ultiplas vari aveis
Uma aplicac ao interessante de listas generalizadas e a manipulac ao de polin omios em m ultiplas vari aveis
que estende o exemplo da Sec ao 3.4. Consideremos um exemplo de polin omio em vari aveis x, y e z:
P(x, y, z) = x
10
y
3
z
2
+ 2x
8
y
3
z
2
+ 3x
8
y
2
z
2
+x
4
y
4
z 6x
3
y
4
z + 2yz
Uma primeira id eia de representac ao poderia adotar para cada termo um n o da forma:
coef x y z
Entretanto, esta representac ao e muito inexvel, xando o n umero de vari aveis. Uma segunda representac ao
utiliza as id eias da sec ao anterior. O polin omio em k 1 vari aveis ser a transformado em um polin omio em
uma vari avel, com coecientes que s ao polin omios emk 1 vari aveis, e assim por diante. O nosso exemplo
pode ser reescrito como:
P(x, y, z) = ((x
10
+ 2x
8
)y
3
+ 3x
8
y
2
)z
2
+ ((x
4
6x
3
)y
4
+ 2x
0
y)z
Esta transformac ao sugere as representac oes indicadas na Fig. 9.3. A alternativa (a) utiliza mais mem oria
mas e mais uniforme e, portanto, facilita a programac ao das rotinas de manipulac ao. A implementac ao
destas representac oes poderia utilizar n os do tipo:
type
ApTermo = Termo;
Polinomio = ApTermo;
Termo = record
prox: Polinomio;
case MarcaCabeca: boolean of
true: (variavel: char);
false:
(expoente: integer;
case CoefInteiro: boolean of
true: (CoefInt: integer);
false: (CoefPolin: Polinomio)
)
end;
Utilizando esta representac ao, pode-se elaborar as rotinas usuais de manipulac ao de polin omios: soma,
multiplicac ao, divis ao etc. V arias delas ser ao semelhantes ao caso de polin omios de uma vari avel, mas
utilizar ao recurs ao para operar sobre os coecientes que s ao, por sua vez, polin omios.
9.3. EXERCICIOS 113
Figura 9.3 Representac ao dos polin omios em m ultiplas vari aveis
z 2 1
y
4 1
x 2 0
x 1 4 3
y 3 2
x 3 8
x 1 10 2 8
6
(a)
z 2 1
y
4
x 1 4 3
y 3 2
x 3 8
x 1 10 2 8
1 2
6
(b)
9.3 Exercicios
1. Transforme os programas 9.1 e 9.2 eliminando os comandos while e introduzindo recurs ao dupla.
2. Escreva uma func ao que verica se uma lista generalizada tem compartilhamento ou circularidades
na sua representac ao.
3. Escreva uma func ao que calcula o n umero de n os utilizado na representac ao de uma lista generalizada
e que funciona em qualquer caso.
4. Escreva procedimentos que copiam listas generalizadas representadas como na Sec ao 9.1. Considere
duas vers oes: uma que faz uma c opia exata e outra que ao copiar expande todas as sublistas.
5. Escreva as rotinas de soma e multiplicac ao para polin omios emm ultiplas vari aveis, conforme indicado
na Sec ao 9.2.
114 CAP

ITULO 9. LISTAS GERAIS


Captulo 10
Espalhamento
A t ecnica de espalhamento
1
permite construc ao eciente de tabelas em que deseja-se armazenar informac ao
constituda de chaves, chamadas neste contexto de nomes, e de atributos correspondentes, sem utilizar
estruturas em arvore, mas baseadas na representac ao das pr oprias chaves.
Como em outros casos de implementac ao de tabelas (veja Cap. 8), as operac oes fundamentais s ao a
busca, inserc ao e remoc ao de informac oes.
10.1 Conceitos b asicos
Uma tabela de espalhamento e uma matriz comb 1 linhas e s 1 colunas, como esquematizado a seguir.
Dado um nome x, a linha desta matriz e selecionada calculando-se um ndice f(x), onde f e a func ao de
espalhamento. No caso do exemplo (b = 7 e s = 3) temos f(joao) = 3. As colunas 2 e 3 s ao usadas
quando h a mais de um nome mapeado pela func ao f num mesmo valor. Em muitos casos utilizam-se tabelas
com s = 1, ou seja apenas uma coluna.
1 2 3
0
1
2
f(joao) 3 joao
4
5
6
Suponhamos, a ttulo de exemplo, que a func ao f calcula o ndice baseado na posic ao da primeira letra
do alfabeto no nome, isto e, 0 para a letra a, 1 para b, etc. A tabela seguinte (b = 26 e s = 2) indica o
resultado de inserc ao de v arios nomes (foram ignorados os acentos):
1
Em ingl es hashing ou scattering.
115
116 CAP

ITULO 10. ESPALHAMENTO


1 2
0 antonio atila
1
2 carlos celio
3 douglas
4 ernesto estevao
5

24
25 zoroastro
Dependendo da localizac ao de espacos livres na tabela, podemos continuar inserindo mais nomes, como por
exemplo, diogo que entraria na posic ao [3,2] e francisco que entraria na posic ao [5,1]. Entretanto,
n ao seria possvel inserir eduardo pois as duas posic oes da linha 4 j a est ao ocupadas. Neste caso, temos
uma colis ao.
Por outro lado, e claro que a func ao de espalhamento escolhida para o exemplo e muito ing enua. Mesmo
que o valor de s fosse muito maior, podemos imaginar que linhas da tabela correspondentes ` as letras a ou
m seriam esgotadas muito antes daquelas correspondentes a q ou x.
Podemos concluir que a utilizac ao de tabelas de espalhamento apresenta dois problemas fundamentais:
escolha da func ao de espalhamento
tratamento das colis oes
Estes dois aspectos ser ao discutidos nas sec oes seguintes.
10.2 Func oes de espalhamento
A escolha de uma func ao de espalhamento deve satisfazer a duas propriedades:
eci encia
bom espalhamento
Esta ultima signica que os valores produzidos pela func ao devem ter um comportamento aparentemente
aleat orio, independentemente do valor do nome, diminuindo a probabilidade de haver conitos enquanto
houver espaco razo avel na tabela.
Citaremos, sem muita discuss ao, apenas alguns exemplos de func oes de espalhamento. Na realidade,
os m etodos indicados podem ser combinados, resolvendo alguns problemas de cada um. Outros m etodos
podem ser encontrados na literatura especializada.
1. Divis ao: o nome, tratado como um n umero na base 26, e dividido por um n umero p relativamente
primo f(x) = x mod p. Por exemplo, para p = 51 teramos:
f(carlos) = ( ((((2 26 + 0) 26 + 17) 26 + 11) 26 + 14) 26 + 18 ) mod 51
= 24.069.362 mod 51 = 14
10.3. ENDEREC AMENTO ABERTO 117
ou seja, o nome carlos deveria ser inserido na linha 14 da tabela, se houver espaco. Note-se que
a utilizac ao deste tipo de func ao implica em adotar tamb em o valor p como o n umero de linhas da
tabela. Uma outra observac ao e que o c alculo da func ao pode ser otimizado, utilizando-se aritm etica
modular o que evitaria operac oes com muitos dgitos.
2. Selec ao de algarismos: o nome e tratado como uma seq u encia de algarismos ou de bytes ou de bits,
e uma subseq u encia e selecionada para representar o ndice. Por exemplo, suponhamos que todos os
nomes s ao representados como a seq u encia de dgitos x = d
0
d
1
d
11
em alguma base conveniente;
uma escolha seria f(x) = d
3
d
5
d
9
.
Retomemos o exemplo do nome carlos. A sua representac ao poderia ser 020017111418. Supu-
semos que cada letra e indicada por dois dgitos que indicam a posic ao no alfabeto, ou seja 00 para
a, 01 para b, etc. Teramos ent ao f(carlos) = 074.
Este m etodo deveria ser combinado com outros para resolver o problema de comprimentos vari aveis
dos nomes.
3. Dobramento: novamente, o nome e tratado como uma seq u encia de algarismos ou de bytes ou de
bits, e algumas subseq u encias s ao combinadas por operac oes convenientes para produzir um ndice.
Por exemplo, suponhamos que todos os nomes s ao representados como a seq u encia de dgitos x =
d
0
d
1
d
11
em alguma base conveniente; uma escolha seria f(x) = d
3
d
5
d
9
d
8
d
7
d
10
, onde
denota a operac ao de ou exclusivo bit a bit.
10.3 Enderecamento aberto
Umdos m etodos de tratar o problema de colis oes e o enderecamento aberto. Neste caso, o algoritmo procura
uma outra posic ao disponvel na tabela para guardar o dado, de maneira que ele possa ser recuperado sem
muito problema quando necess ario.
Veremos tr es variantes desta t ecnica. Nos tr es casos, utilizaremos o mesmo exemplo que consis-
tir a da inserc ao dos nomes antonio, carlos, douglas, celio, armando, zoroastro, atila,
alfredo, nesta ordem, ainda utilizando a func ao de espalhamento baseada na primeira letra. A tabela ter a
os par ametros s = 1 e b = 26.
Reespalhamento linear: se houver colis ao, procura-se a pr oxima posic ao consecutiva livre da tabela,
ou seja, s ao utilizados os ndices (f(x) + i) modb, (i = 0, 1, ). A aritm etica modular e utilizada
para tornar a tabela circular, recomecando a busca desde o incio, se necess ario.
Os resultados do exemplo est ao indicados na coluna (a) da Fig. 10.1.
Um dos problema criados por este tipo de tratamento e o aparecimento de aglomerac oes de entradas
em partes da tabela.
Reespalhamento quadr atico: a busca de uma posic ao livre segue a f ormula (f(x) + i
2
) modb, (i =
0, 1, ).
Os resultados do exemplo est ao indicados na coluna (b) da Fig. 10.1.
118 CAP

ITULO 10. ESPALHAMENTO


Reespalhamento duplo: a busca de uma posic ao livre segue a f ormula (f(x) +i g(x)) modb, (i =
0, 1, ), onde g(x) e uma segunda func ao de espalhamento conveniente.
Usando, por exemplo, uma func ao g(x) = (c mod3) + 1, onde c e o c odigo num erico da segunda
letra do nome x, obteramos para o mesmo exemplo a coluna (c) da Fig. 10.1.
Figura 10.1 Resultados das t ecnicas de enderecamento aberto
0 antonio
1 armando
2 carlos
3 douglas
4 celio
5 atila
6 alfredo
7
8
9

25 zoroastro
(a)
0 antonio
1 armando
2 carlos
3 douglas
4 atila
5
6 celio
7
8
9 alfredo

25 zoroastro
(b)
0 antonio
1
2 carlos
3 douglas
4 celio
5
6 armando
7
8 atila
9 alfredo

25 zoroastro
(c)
Note-se que os algoritmos de busca utilizados no caso de tabelas construdas desta maneira t em que
seguir o mesmo c alculo para vericar se um nome pertence ` a tabela. Por exemplo, no caso do espalhamento
quadr atico, se o nome procurado for carolina, o algoritmo calcular a os ndices: 2, 2+1
2
= 3, 2+2
2
= 6
e 2+3
2
= 11, vericando que o nome n ao aparece em nenhuma posic ao, e parando a busca quando aparece
uma posic ao livre.
Um problema importante no caso de utilizac ao de enderecamento aberto e o de remoc ao de entradas da
tabela. Por exemplo, se removermos da tabela (b) da Fig. 10.1 o nome armando, a busca descrita acima
n ao poder a encontrar mais o nome atila. Uma maneira de resolver o problema seria substituir um nome
eliminado por uma marca especial, denominada ` as vezes l apide, que indica que a posic ao est a livre mas
que n ao p ara a busca. Assim, a remoc ao de armando que foi mencionada produziria:
10.4. ENCADEAMENTO 119
0 antonio
1 +++++++
2 carlos
3 douglas
4 atila
5
6 celio
7
8
9 alfredo

25 zoroastro
Finalmente, deve-se mencionar que esta t ecnica pode ser bastante eciente, em m edia, mas depende de
uma boa escolha da func ao de espalhamento e do tamanho da tabela em relac ao ao n umero de entradas ocu-
padas. A an alise precisa desta eci encia e bastante complexa, mas pode-se mostrar que satisfeitas algumas
condic oes, o n umero m edio de comparac oes de nomes numa busca de um elemento que est a na tabela e
(2 )/(2 2), onde denota o fator de carga que e a frac ao de posic oes da tabela ocupadas. Supondo
uma tabela com 1000 posic oes, teramos os seguintes resultados para alguns valores:
100 1,06
200 1,13
300 1,21
400 1,33
500 1,50
600 1,75
700 2,17
800 3,00
900 5,50
950 10,5
Como era de se esperar o n umero m edio de comparac oes comeca a crescer rapidamente quando o fator de
carga comeca a ser apreci avel. Por outro lado, a eci encia e muito boa para fatores de carga razo aveis, at e
60% ou 70%. Note-se que numa arvore bin aria de busca com 500 n os e de altura mnima, o n umero de
comparac oes poderia chegar a 9.
10.4 Encadeamento
Uma outra t ecnica para tratar de colis oes e o encadeamento que consiste em utilizar listas ligadas para
manter numa unica posic ao da tabela todas as entradas que produzem o mesmo valor da func ao de espalha-
mento. Utilizando ainda o mesmo exemplo dos nomes antonio, carlos, douglas, celio, armando,
zoroastro, atila, alfredo, inseridos nesta ordem, ainda utilizando a func ao de espalhamento base-
ada na primeira letra, obteramos a tabela:
120 CAP

ITULO 10. ESPALHAMENTO


0 alfredo atila armando antonio
1
2 celio carlos
3 douglas
4
5

25 zoroastro
Neste caso, as entradas da tabela s ao na realidade apontadores para os primeiros n os de cada lista. A
implementac ao das listas pode utilizar as v arias t ecnicas descritas no Cap. 3.
A eci encia desta implementac ao de encadeamento tamb em depende do tamanho b da tabela e do
n umero de entradas existentes n. Tomando = n/b, pode-se mostrar que o n umero m edio de comparac oes
de nomes numa busca de um elemento que est a na tabela e 1 + /2. Usando o mesmo exemplo da sec ao
anterior, podemos apresentar a seguinte tabela (note que podemos ter > 1):
100 1,05
200 1,10
400 1,20
500 1,25
1000 1,50
2000 2,00
Podemos ver que a degradac ao de eci encia com o crescimento do fator de carga e mais lenta do que no
caso de enderecamento aberto. Al em disto, n ao existe o problema de a tabela car totalmente preenchida.
A remoc ao de entradas pode usar as t ecnicas j a conhecidas em relac ao a listas ligadas.
10.5 Exerccios
Captulo 11
Gerenciamento de Mem oria
Linguagens e sistemas apresentam duas maneiras distintas de tratar os problemas de gerenciamento da
mem oria din amica: explcita e implcita. Um exemplo de gerenciamento explcito e a linguagem PASCAL
em que os pseudo-procedimentos New e Dispose s ao utilizados pelo pr oprio programador para requisitar
e devolver ao sistema blocos de mem oria din amica de tamanho conveniente. O sistema n ao verica se
as vari aveis apontadoras, quando usadas, referem-se a blocos corretamente alocados atrav es de New, nem
se os blocos liberados atrav es de Dispose s ao realmente desnecess arios; toda a responsabilidade cabe ao
programador. Mesmo nestes sistemas, deve existir um mecanismo que permite manter as informac oes sobre
a mem oria j a alocada e aquela disponvel para alocac ao.
Em sistemas com gerenciamento autom atico ou implcito, o programador requisita blocos de mem oria
atrav es de construc oes apropriadas. O sistema e respons avel pela manutenc ao de todas as informac oes e
pela liberac ao de eventuais blocos de mem oria que n ao podem ser mais utilizados pelo programa por serem
inacessveis. Neste ultimo caso, e realizada a tarefa de identicac ao e coleta de blocos de mem oria que j a
foram utilizados mas tornaram-se inacessveis ao programa. Linguagens como LISP e PROLOG utilizam
este tipo de implementac ao. Algumas t ecnicas ser ao vistas nas sec oes seguintes.
11.1 Gerenciamento elementar
Uma exemplo elementar de gerenciamento de mem oria explcito feito pelo pr oprio programador est a in-
dicado no Prog. 11.1. Sup oe-se, para ns deste exemplo, que um programa em PASCAL utiliza n os de
somente um tipo que cont em pelo menos um campo apontador, no caso prox. O programador utiliza os pro-
cedimentos Aloca e Desaloca. O primeiro, chama o pseudo-procedimento New somente quando necess ario.
Ao inv es de desalocar a mem oria atrav es de Dispose,
1
o programador chama o procedimento Desaloca que
coleta os n os a serem descartados numa lista ligada global de n os disponveis, apontada pela vari avel disp.
O valor desta vari avel deve ser inicializado no comeco da execuc ao do programa atrav es do procedimento
InicializaAloca.
Aabordagemdeste exemplo pode ser estendida a n os de v arios tipos diferentes, mas a sua implementac ao
em PASCAL apresenta alguns problemas, como a necessidade de manutenc ao de v arias listas disponveis e
conjuntos de procedimentos, correspondentes a cada tipo. Al em disto, o aproveitamento de mem oria pode
tornar-se ineciente quando h a disponibilidade de n os de um tipo mas n ao de outro.
1
Em alguns sistemas mais antigos, o procedimento Dispose n ao fazia nada!
121
122 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
Veremos, nas sec oes seguintes, algumas maneiras de resolver este tipo de problemas. Asua programac ao
e feita, em geral, fora do sistema de execuc ao da linguagem PASCAL padr ao que n ao n ao permite acesso ao
seu sistema de gerenciamento de mem oria. Mesmo assim, a ttulo de clareza, os algoritmos ser ao apresen-
tados em notac ao mais pr oxima possvel desta linguagem.
Programa 11.1 Gerenciamento elementar de mem oria
type
ApReg = Reg;
Reg = record
...
prox: ApReg;
...
end;
var
disp: ApReg;
procedure InicializaAloca;
begin
disp := nil
end;
procedure Aloca(var p: ApReg);
begin
if disp=nil
then begin p := disp; disp := disp.prox end
else New(p)
end;
procedure Desaloca(p: ApReg);
begin
p.prox := disp; disp := p
end;
11.2 Contagem de refer encias
Uma maneira aparentemente simples de implementar o gerenciamento autom atico de mem oria din amica e
a utilizac ao de contadores de refer encias.
2
Esta t ecnica sup oe que cada bloco din amico possui um campo
adicional no qual e mantido um contador de n umero de apontadores (refer encias) a este bloco. Quando o
bloco e alocado, este campo recebe o valor um. O bloco pode ser desalocado quando o valor do contador
atinge o valor zero.
Neste caso, a implementac ao de operac oes que envolvem vari aveis apontadoras deve ser revista. Consi-
deremos o comando de atribuic ao da forma p := q, onde p e q s ao duas vari aveis apontadoras do mesmo
tipo; suponhamos que as duas foram inicializadas e apontam para dois blocos de mem oria v alidos. Neste
caso, o compilador de PASCAL deveria traduzir este comando para a seguinte seq u encia:
2
Em ingl es reference counts.
11.2. CONTAGEM DE REFER

ENCIAS 123
if q=nil
then q.refs := q.refs+1;
if p=nil then
begin
p.refs := p.refs1;
if p.refs=0
then DesalocaRefs(p)
end;
p :=q
onde DesalocaRefs e uma rotina que trata de desalocar um bloco de mem oria. Se o bloco a ser desalocado
cont em apontadores, os contadores correspondentes tamb em t em que ser atualizados, e podem aparecer
outros blocos para desalocac ao. O Prog. 11.2 mostra como poderia ser implementada esta rotina. Note-se
que ela precisa conhecer, de alguma maneira, quais s ao os campos apontadores existentes dentro de cada
bloco. Para simplicar a exposic ao, suporemos que cada registro apontado tem um vetor de apontadores,
descrito de maneira obvia. Suporemos tamb em que a mem oria liberada e coletada numa lista disponvel
como indicado na sec ao anterior, atrav es do primeiro apontador.
Programa 11.2 Rotina de desalocac ao para contagem de refer encias
type
ApReg = Reg;
Reg =
record
refs: Integer;
...
numAps: Integer;
aponts: array [1..MaxAps] of ApReg;
...
end;
procedure DesalocaRefs(p: ApReg);
var q: ApReg; i: Integer
begin
with p do
for i:=1 to numAps do
begin
q := aponts[i];
if q=nil then
begin
q.refs := q.refs1;
if q.refs=0 then DesalocaRefs(q)
end
end;
p.aponts[1] := disp;
disp := p
end;
Os repetidos testes de apontadores nulos poderiam ser eliminados atrav es de um truque de programac ao,
utilizando-se ao inv es de nil um n o especial com valor do contador muito alto, que nunca atingisse o valor
zero. Mesmo assim, o custo desta t ecnica e relativamente alto, pois transformou uma simples operac ao de
atribuic ao numa seq u encia de operac oes bastante complexas, de durac ao imprevisvel, pois o procedimento
DesalocaRefs e recursivo.
Entretanto, o problema mais grave desta t ecnica reside no fato de n ao ser aplic avel no caso de estruturas
de dados que t em circularidades. Por exemplo, numa lista ligada circular, os contadores de refer encias dos
seus n os nunca atingir ao o valor zero, mesmo que n ao haja vari aveis apontando para algum n o da lista.
124 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
Este fato torna a t ecnica utiliz avel somente em situac oes especiais. Em situac oes em que o problema de
chamadas recursivas n ao e muito freq uente, esta t ecnica tem a vantagem de distribuir o tempo adicional de
gerenciamento de mem oria de maneira mais uniforme ao longo da execuc ao dos programas.
11.3 Coleta de lixo
Uma outra t ecnica de implementac ao de gerenciamento autom atico de mem oria e comumente chamada de
coleta de lixo.
3
Ela sup oe que a mem oria din amica e alocada de acordo comas necessidades do programa at e
que ela seja esgotada. No momento em que esta situac ao ocorre, o sistema executa uma s erie de operac oes
que t em por nalidade identicar todos os blocos de mem oria ainda acessveis ao programa e liberar a
mem oria dos outros blocos.
A coleta de lixo padr ao envolve duas fases principais: marcac ao dos blocos acessveis e compactac ao
ou coleta dos blocos que n ao est ao em uso. Nesta ultima fase, a escolha entre a compactac ao e a coleta
depende de alguns fatores que ser ao comentados mais adiante. Para ns de exposic ao, suporemos que a
mem oria din amica pode ser tratada de duas maneiras diferentes. Na primeira fase, o acesso aos blocos
de mem oria ser a aquele normalmente usado em PASCAL. Na segunda fase, suporemos que a mem oria
din amica e constituda por um vetor MemDin de registros consecutivos. A m de simplicar a exposic ao
inicial, suporemos tamb em que cada registro tem um certo n umero de campos apontadores, conhecidos pelo
programa e representado por um vetor, analogamente ` a forma utilizada na sec ao anterior. Al em disto, cada
registro ter a um campo booleano marca, com valor inicial falso, para indicar se o correspondente bloco de
mem oria j a foi marcado.
A fase de marcac ao corresponde, basicamente, a um simples percurso em pr e-ordem das estruturas de
dados acessveis a partir das vari aveis do programa. O problema de visitas repetidas a um n o devidas a
compartilhamento e circularidades ser a resolvido utilizando-se o pr oprio campo marca, analogamente ` a
t ecnica usada no Prog. 9.2. O procedimento Marcar est a apresentado no Prog. 11.3. Ele deve ser executado
para cada valor apontador armazenado em alguma vari avel do programa.

E bastante f acil vericar que o
n umero total de chamadas do procedimento Marcar ser a igual ao n umero de campos apontadores acessveis
a serem percorridos. A eci encia da fase de marcac ao pode ser melhorada atrav es da eliminac ao da recurs ao
como ilustrado para percursos em pr e-ordem na Sec ao 6.3. Caso seja necess ario minimizar o espaco para a
pilha, pode-se adaptar o algoritmo de Deutsch, Schorr e Waite de Prog. 6.8. Na realidade, este algoritmo foi
desenvolvido originalmente neste contexto.
Terminada a fase de marcac ao, trataremos a mem oria din amica como um vetor conveniente, descrito
anteriormente, a m de recuperar a mem oria que n ao foi marcada. A sua declarac ao poderia ter a forma
var MemDin: array[1..MemDinMax] of Reg;
Uma t ecnica muito simples seria fazer a coleta numa lista disponvel, como j a foi feito nas sec oes
anteriores, atrav es do primeiro campo apontador. Esta alternativa est a apresentada no Prog. 11.4. Utilizamos
neste programa o operador &, que n ao existe em PASCAL, mas e an alogo ao da linguagem C, e devolve o
endereco da vari avel correspondente, isto e, um apontador. Note-se que o procedimento Coleta atribui
novamento valores falsos a todas as marcas, para que, numa pr oxima coleta de lixo, todas elas tenham o
valor esperado.

E simples vericar que esta fase de gerenciamento tem um tempo de execuc ao proporcional
3
Em ingl es garbage collection.
11.3. COLETA DE LIXO 125
Programa 11.3 Algoritmo de marcac ao de uma estrutura
type
ApReg = Reg;
Reg =
record
marca: Boolean;
...
numAps: Integer;
aponts: array[1..MaxAps] of ApReg;
...
end;
procedure Marcar(p: ApReg);
var i: Integer;
begin
if p=nil then
with p do
if not marca then
begin
marca := true;
for i:=1 to numAps do Marcar(aponts[i])
end
end;
ao tamanho total da mem oria din amica, que pode ser muito maior do que o tamanho da mem oria realmente
em uso.
Programa 11.4 Coleta de n os marcados
procedure Coleta;
var i: Integer;
begin
disp := nil
for i:=1 to MemDinMax do
with MemDin[i] do
if marca
then marca := false
else begin
aponts[1] := disp;
disp := &(MemDin[i])
end
end;
Esta t ecnica de coleta funciona bem em caso de registros de tipo uniforme, ou pelo menos, de mesmo
comprimento. Ela pode ser adaptada para registros de tamanho vari avel, contanto que o sistema saiba
identicar os campos apontadores de cada registro. Al em disto, cada registro dever a conter uma indicac ao
relativa ao seu comprimento para viabilizar o percurso seq uencial do procedimento Coleta. Por outro lado, a
coleta de blocos de mem oria de tamanho vari avel traz v arios problemas de gerenciamento a serem discutidos
na Sec ao 11.4.
Uma alternativa conveniente para esta t ecnica de coleta e a compactac ao de mem oria. Ela consiste,
basicamente, em deslocar todos os blocos marcados para o incio (ou o m) da mem oria din amica, deixando
o espaco disponvel sob a forma de um unico bloco. Novamente, a m de simplicar a exposic ao, suporemos
126 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
inicialmente que trata-se de registros de tipo uniforme, como no caso da coleta simples. A extens ao para o
caso de registros de tamanho vari avel ser a deixado para um exerccio (vide Exerccio 1).
Suporemos que, para ns de compactac ao, cada registro possui, al em dos outros campos, um campo
apontador auxiliar que denominaremos destino pois conter a o endreco para o qual o registro dever a ser
movido. A compactac ao ser a implementada em tr es passos. No primeiro passo, ser ao preenchidos os
campos destino de cada registro marcado. No segundo passo, ser ao modicados os campos apontadores de
cada registro para reetir a posic ao nal dos registros correspondentes. Finalmente, no terceiro passo, os
registros ser ao movidos para a sua posic ao nal. O Prog. 11.5 mostra os procedimentos correspondentes aos
tr es passos. Deve-se notar que falta indicar ainda a atualizac ao das vari aveis apontadoras do programa para
o valor indicado pelos campos destino correspondentes. Desta vez, a vari avel disp apontar a para o primeiro
bloco disponvel; outros blocos poder ao ser alocados seq uencialmente. N ao e difcil, novamente, vericar
que a compactac ao tem um tempo de execuc ao proporcional ao tamanho total da mem oria din amica, que
pode ser muito maior do que o tamanho da mem oria realmente em uso.
Programa 11.5 Rotinas de compactac ao
type
ApReg = Reg;
Reg =
record
marca: Boolean;
destino: ApReg;
...
numAps: Integer;
aponts: array[1..MaxAps] of ApReg;
...
end;
var disp: ApReg;
procedure Atualiza;
var i,k: Integer;
begin
for i:=1 to MemDinMax do
with MemDin[i] do
if marca then
for k:=1 to numAps do
aponts[k] := aponts[k].destino;
end;
procedure CalculaDestino;
var i,j: Integer;
begin
j := 1;
for i:=1 to MemDinMax do
with MemDin[i] do
if marca then
begin
destino := &(MemDin[j];)
j := j+1
end;
disp := &(MemDin[j])
end;
procedure Move;
var i: Integer;
begin
for i:=1 to MemDinMax do
with MemDin[i] do
if marca then
begin
marca := false;
destino := MemDin[i];
end
end;
11.4. ALOCAC

AO DE BLOCOS DE MEM

ORIA VARI

AVEIS 127
11.4 Alocac ao de blocos de mem oria vari aveis
Conforme foi visto nas sec oes anteriores, o resultado da coleta de mem oria disponvel pode ser uma lista
ligada de blocos que n ao est ao em uso, ou ent ao um bloco compactado unico de mem oria cujo tamanho e o
m aximo possvel, pois inclui toda a mem oria disponvel naquele momento.
A obtenc ao de uma lista ligada e mais simples e eciente, e e uma soluc ao muito boa no caso de
blocos de tamanho xo.
4
No caso de blocos de tamanho vari avel, pode-se chegar a uma situac ao em que
o total de mem oria disponvel seria suciente para uma dada requisic ao, mas nenhum bloco existente e
sucientemenete grande.
Mesmo que n ao ocorra este caso extremo, pode ser freq uente a situac ao em que o bloco encontrado na
lista disponvel e maior do que necess ario. Se ele for alocado na ntegra, haver a um desperdcio de mem oria.
Se a poltica de alocac ao for a de quebrar o bloco em dois, alocando o tamanho exato e recolocando a
sobra do bloco na lista disponvel, haver a a tend encia de fragmentac ao de mem oria, isto e, formac ao de
blocos muito pequenos com pouca probabilidade de reutilizac ao. Esta tend encia poder a ser especialmente
acentuada se o crit erio de alocac ao for o de melhor candidato,
5
isto e, de procurar o bloco de tamanho
mnimo, mas maior ou igual ao necess ario. Al em disto, a busca deste candidato pode levar um tempo
excessivo.
Na pr atica, observa-se que o crit erio de primeiro candidato,
6
em que procura-se o primeiro bloco da lista
de tamanho maior ou igual ao necess ario, funciona melhor. Para prevenir a proliferac ao de blocos pequenos
ele pode ser complementado com a id eia de n ao quebrar mais blocos que deixariam sobras menores do
que um valor pr e-determinado. Uma outra modicac ao neste esquema consiste em tornar a lista disponvel
circular e iniciar a busca de um novo bloco sempre na posic ao seguinte na lista ` aquela utilizada numa
alocac ao anterior, evitando a acumulac ao de blocos pequenos no incio da lista. Este tipo de estrat egia
recebe o nome de selec ao do pr oximo candidato.
7
Mesmo assim, ele pode acabar com uma lista disponvel
contendo um n umero grande de blocos pequenos.
Este esquema de lista disponvel pode ser melhorado signicativamente juntando-se, sempre que possvel,
blocos contguos que n ao s ao reconhecidos como um unico bloco. Entretanto, a identicac ao de blocos
contguos pode ser bastante ineciente. Uma das t ecnicas propostas para resolver o problema e a de marcas
de fronteira.
8
Neste caso, blocos de mem oria em uso e disponveis s ao representados como indicado na
Fig. 11.1.
Nesta representac ao, os campos tamanho e livre1 ocorrem no incio, e o campo livre2 no m de qualquer
bloco, disponvel ou n ao. Os campos esq e dir ocorrem ap os o campo livre1 somente em blocos que n ao
est ao em uso e s ao usados para formar uma lista duplamente ligada de blocos disponveis. O campo inicio
ocorre no m de bloco disponvel, precedendo imediatamente o campo livre2, e aponta para o incio do
pr oprio bloco. As letras f e t denotam, respectivamente, os valores booleanos false e true. Note que os
valores dos campos livre1 e livre2 s ao sempre iguais. Esta disposic ao dos campos permite que, dado o
endereco (apontador) a um bloco, seja f acil vericar o estado e o incio dos dois blocos contguos.
As operac oes de alocac ao e desalocac ao s ao bastante ecientes. Para alocar um bloco novo, basta
percorrer a lista disponvel ` a procura de um bloco de tamanho suciente. Se a diferenca de tamanhos
for abaixo de um limite pr e-determinado, o bloco e alocado na ntegra. Caso contr ario, a mem oria em
4
Mesmo neste caso pode ser prefervel realizar compactac ao para diminuir a movimentac ao de p aginas da mem oria virtual.
5
Em ingl es best t.
6
Em ingl es rst t.
7
Em ingl es next t.
8
Em ingl es boundary tags.
128 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
Figura 11.1 Blocos em uso e disponvel (marcas de fronteira)
tamanho
livre2
livre1
f
f
tamanho dir
livre2
livre1 esq
inicio
t
t
Em uso Disponvel
excesso constitui um novo bloco que e reinserido na lista disponvel e marcado de maneira apropriada. Na
operac ao de desalocac ao de um bloco, a exist encia das marcas de fronteira permite vericar rapidamente se
um ou ambos dos seus dois blocos contguos tamb em est ao disponveis. Conforme o caso, um ou ambos
s ao juntados ao bloco que est a sendo liberado. A exist encia da lista duplamente ligada permite operac oes
ecientes de inserc ao e remoc ao na lista. Os detalhes de implementac ao ser ao deixados para um exerccio
(vide Exerccio 2).
11.5 Alocac ao controlada
As id eias sugeridas na sec ao anterior s ao, em geral, bastante ecientes, mas n ao garantem a eliminac ao da
fragmentac ao, e podem gastar um tempo excessivo na busca de pr oximo candidato ` a alocac ao. Uma outra
id eia de alocac ao controlada de mem oria e o sistema de blocos conjugados bin arios.
9
Para simplicar a
exposic ao, suporemos que a mem oria e constituda de um certo n umero de blocos de tamanho mnimo,
numerados de 0 a 2
m
1, ou seja, h a 2
m
blocos. Suporemos tamb em que 2, 4, 8, ..., blocos contguos
podem ser combinados em blocos maiores, seguindo a arvore bin aria indicada na Fig. 11.2 (caso de m = 4).
Nesta arvore conceitual, as folhas indicam os blocos de tamanho mnimo e os n os internos correspondem a
blocos obtidos pela junc ao de 2, 4, 8 e 16 blocos mnimos. Os valores de k s ao os nveis da arvore; em cada
nvel, o bloco tem o tamanho 2
k
. Dizemos que dois blocos de mesmo tamanho s ao conjugados se os n os
correspondentes da arvore s ao irm aos.
Verica-se que e f acil reconhecer se dois ndices i e j denotam duas areas conjugadas de tamanho 2
k
.

E
suciente para isto tomar a representac ao bin aria dos n umeros i e j: elas devem diferir apenas no k- esimo
bit, contado da direita para a esquerda, comecando com zero. No exemplo indicado na gura, tomemos
i = 8, j = 10 e k = 1; neste caso, i
[2]
= 1000 e j
[2]
= 1010.
10
As duas representac oes diferem apenas
no bit n umero 1. Conclui-se que os blocos apontados por 8 e 10, de tamanho 2, s ao conjugados, podendo
ser juntados num unico bloco de tamanho 4, fato este conrmado pela gura. Tomemos um outro exemplo,
9
Em ingl es binary buddy system.
10
A notac ao n
[2]
indica aqui a representac ao do n umero n em base 2.
11.5. ALOCAC

AO CONTROLADA 129
com i = 4, j = 8 e k = 2. Neste caso, i
[2]
= 0100 e j
[2]
= 1000, e as duas representac oes diferem em mais
de um bit, n ao correspondendo a blocos conjugados. A gura conrma que os blocos 4 e 8 de tamanho 4
n ao correspondem a irm aos na arvore.
Figura 11.2

Arvore para o sistema de blocos conjugados com m = 4
0 15
0 7
4 7 8 11
4 5 6 7 8 9 2 3
0 3
0 1
8 15
12 15
10 11 12 13 14 15
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
k=0
k=1
k=2
k=3
k=4
A alocac ao e desalocac ao de blocos segue um esquema relativamente simples. Somente podem ser
alocados os blocos que fazem parte da arvore. Os blocos disponveis est ao arranjados em m + 1 listas
duplamente ligadas; a k- esima lista cont em os blocos disponveis de tamanho 2
k
. Os apontadores para os
n os cabeca das listas formam um vetor numerado de 0 a m. Numa operac ao de alocac ao que necessita de
tamanho n, aloca-se um bloco de tamanho k = log
2
n. Se n ao existir um bloco deste tamanho, procura-se
um bloco de tamanho 2
k+1
que e quebrado em dois blocos conjugados de tamanho 2
k
. Caso este tamb em
n ao exista, aplica-se uma operac ao semelhante a um bloco de tamanho 2
k+2
, etc. Para inicializar o sistema,
e formado um unico bloco de tamanho 2
m
.
Numa operac ao de desalocac ao de um bloco de tamanho 2
k
, verica-se se o seu bloco conjugado est a
disponvel; se estiver, os dois blocos s ao juntados, formando um bloco de tamanho 2
k+1
. Caso o bloco con-
jugado deste novo bloco tamb em esteja disponvel, e formado um novo bloco de tamanho 2
k+2
, e o processo
e repetido. O bloco nal e inserido na lista correspondente ao seu tamanho. Para que estes algoritmos pos-
sam ser executados, cada bloco, em uso ou disponvel, dever a conter certas informac oes conforme indicado
na Fig. 11.3. Os detalhes de implementac ao ser ao deixados para um exerccio (vide Exerccio 3). Note-se
que a arvore da Fig. 11.2 e apenas conceitual e n ao existe sicamente na mem oria durante a execuc ao dos
algoritmos.
130 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
Figura 11.3 Blocos em uso e disponvel (sistema conjugado)
k f k esq dir t
Em uso Disponvel
11.6 Exerccios
1. Esboce a implementac ao de compactac ao de mem oria para blocos de tamanho vari avel, conforme
sugerido na Sec ao 11.3.
2. Esboce a implementac ao do esquema de alocac ao e desalocac ao de blocos utilizando marcas de fron-
teira, conforme explicado na Sec ao 11.4.
3. Escreva as rotinas para implementar a alocac ao e a desalocac ao de mem oria utilizando o sistema de
blocos conjugados explicado na Sec ao 11.5.
4. Osistema de blocos conjugados bin arios como explicado na Sec ao 11.5 sup oe que a mem oria din amica
tem tamanho 2
m
para algum m. Sugira como implementar o sistema quando isto n ao acontece. Su-
gest ao: Adote uma maneira diferente de inicializar as listas dos blocos disponveis; lembre que todo
n umero positivo pode ser expresso como uma soma de pot encias distintas de 2.
5. O esquema de blocos conjugados utiliza o fato de que dois blocos contguos de tamanho 2
k
podem ser
juntados num bloco de tamanho 2
k+1
. Uma outra id eia seria utilizar os n umeros de Fibonacci que t em
a propriedade F
n
= F
n1
+F
n2
.
11
Nesta vers ao do esquema, um bloco de nvel n seria obtido pela
junc ao de dois blocos, um de nvel n 1 e outro de nvel n 2. Complete os detalhes deste esquema
e esboce as rotinas correspondentes. A Fig. 11.4 ilustra esta t ecnica para mem oria disponvel de 13
blocos (n = 7).
11
Lembre que F
0
= 0 e F
1
= 1.
11.6. EXERC

ICIOS 131
Figura 11.4

Arvore para blocos conjugados de Fibonacci com F
7
= 13
0 1 2 3 4 5 6 7 8 9 10 11 12
0 2
0 1 3 4 5 6 8 9 11 12
5 7 8 10
8 12 0 4
0 7
0 12
F
F
F
F
F
3
4
5
6
7
2
F = 1
= 2
= 3
= 5
= 8
= 13
132 CAP

ITULO 11. GERENCIAMENTO DE MEM



ORIA
Captulo 12
Processamento de Cadeias e Textos
12.1 Representac ao de cadeias
12.2 Noc oes de compactac ao de cadeias
12.3 Busca de padr oes
12.4 Noc oes de criptograa
12.5 Exerccios
133
134 CAP

ITULO 12. PROCESSAMENTO DE CADEIAS E TEXTOS


Captulo 13
Algoritmos de Ordenac ao
Neste captulo ser ao cobertos v arios algoritmos de ordenac ao. A ordenac ao e um dos problemas funda-
mentais em Computac ao e existem v arios algoritmos para resolv e-lo. Pode-se demonstrar que um algoritmo
baseado apenas em comparac oes de chaves exige da ordem de O(nlog n) operac oes de comparac ao, no pior
caso.
A m de uniformizar e simplicar a apresentac ao, suporemos em todo este captulo que deseja-se orde-
nar um vetor de dados especicado pelo tipo Vetor e utilizaremos o procedimento auxiliar Troca:
const nMax = ...;
type
Indice = 0 .. nMax;
Vetor = record
dados: array [1..nMax] of T;
n: Indice { Comprimento corrente }
end;
procedure Troca(var x, y: T);
var t: T;
begin t := x; x := y; y := t end;
Deve-se observar que cobriremos m etodos de ordenac ao aplic aveis a seq u encias representadas na mem oria
principal (ordenac ao interna). A ordenac ao de arquivos mantidos em dispositivos externos (ordenac ao ex-
terna) requer m etodos especiais. Notaremos quando o m etodo pode ser adaptado para esta aplicac ao.
13.1 Ordenac ao por transposic ao
Algoritmos de ordenac ao por transposic ao baseiam-se em trocas repetidas de elementos que est ao fora
de ordem. O algoritmo muito simples conhecido como bubblesort est a apresentado no Prog. 13.1 veja
tamb em a Sec ao 1.1. J a sabemos que este algoritmo realiza da ordem de O(n
2
) operac oes, ou seja, n ao e
muito adequado, exceto para sequ u encias de poucas dezenas de elementos.
Um outro algoritmo de ordenac ao por transposic ao e conhecido como quicksort. A an alise de sua
eci encia e bastante complexa, mas pode-se demonstrar que, o n umero m edio de operac oes realizadas e da
ordem de O(nlog n) enquanto que no pior caso este n umero e O(n
2
). Apesar disto, e um dos m etodos
135
136 CAP

ITULO 13. ALGORITMOS DE ORDENAC



AO
Programa 13.1 Algoritmo bubblesort
procedure BubbleSort(var v: Vetor);
var i,j: Indice;
begin
with v do
begin
for i:=n downto 2 do
begin
{ Troca vizinhos fora de ordem e deixa, em denitivo, em dados[i] }
{ o m aximo de dados[1..i] }
for j:=1 to i1 do
if dados[j]>dados[j+1] then Troca(dados[j],dados[j+1]);
end
end
end;
muito usados na pr atica, por ter o coeciente de proporcionalidade relativamente pequeno. O algoritmo est a
apresentado no Prog. 13.2.
13.2 Ordenac ao por inserc ao
Os algoritmos por inserc ao sup oem que uma parte da seq u encia de dados j a est a ordenada, e inserem mais
um elemento no lugar apropriado. O Prog 13.3 apresenta um exemplo deste tipo de algoritmo, denominado
inserc ao simples. Pode-se demonstrar que este algoritmo executa da ordem de O(n
2
) de operac oes, sendo
portanto pouco recomend avel sob o ponto de vista pr atico.
13.3 Ordenac ao por selec ao
Os algoritmos por selec ao sup oem que os menores elementos da seq u encia de dados j a est ao ordenados,
buscando a seguir o menor elemento da seq u encia restante para inclu-lo. O Prog 13.4 apresenta um exemplo
deste tipo de algoritmo, denominado selec ao simples. Pode-se demonstrar que este algoritmo executa da
ordem de O(n
2
) de operac oes, sendo tamb em pouco recomend avel sob o ponto de vista pr atico.
Um outro algoritmo por selec ao e conhecido como heapsort veja Prog. 13.5 e utiliza as id eias da
Sec ao 8.4. Demonstra-se que o algoritmo realiza da ordem O(nlog n) operac oes o que o torna um dos
algoritmos otimos para esta aplicac ao.
13.4. ORDENAC

AO POR INTERCALAC

AO 137
Programa 13.2 Algoritmo quicksort
procedure QuickSortAux(var v: Vetor; esq, dir: Indice);
var i,j: Indice; pivot: T;
begin { Sup oe esq dir }
with v do
begin
i := esq; j := dir; pivot := dados[(esq+dir) div 2];
repeat
while dados[i]<pivot do i := i+1;
while dados[j]>pivot do j := j1;
if ij then begin
Troca(dados[i],dados[j]);
i := i+1; j := j1
end
until i>j;
if esq<j then QuickSortAux(v,esq,j);
if dir>i then QuickSortAux(v,i,dir)
end
end;
procedure QuickSort(var v: Vetor);
var i: Indice;
begin
QuickSortAux(v,1,v.n)
end;
13.4 Ordenac ao por intercalac ao
Os algoritmos desta classe fazem a intercalac ao de seq u encias j a ordenadas de comprimentos crescentes.
Demonstra-se que os algoritmos realizam da ordem O(nlog n) operac oes o que os torna algoritmos otimos
para esta aplicac ao. Apresentaremos duas vers oes de ordenac ao por intercalac ao: a iterativa e a recursiva.
Para aplicac oes na mem oria, a primeira e certamente mais adequada. Entretanto, a segunda pode ser refor-
mulada facilmente para ordenac ao de arquivos externos. Os algoritmos est ao apresentados nos Progs. 13.6
e 13.7
13.5 Ordenac ao por distribuic ao
138 CAP

ITULO 13. ALGORITMOS DE ORDENAC



AO
Programa 13.3 Ordenac ao por inserc ao simples
procedure Insercao(var v: Vetor);
var i,j: integer; p: T;
begin
with v do
begin
for i:=1 to n1 do
begin
{ insere dados[i + 1] em dados[1..i] }
p := dados[i+1]; j := i;
while (j1) and (p<dados[j]) do
begin dados[j+1] := dados[j]; j := j1 end;
dados[j+1] := p
end
end
end;
13.6 Exerccios
13.6. EXERC

ICIOS 139
Programa 13.4 Ordenac ao por selec ao simples
procedure Selecao(var v: Vetor);
var i,j, p: integer;
begin
with v do
begin
for i:=1 to n1 do
begin
{ coloca em dados[i] o mnimo de dados[i..n 1] }
p := i;
for j:=i+1 to n do
if dados[j]<dados[p] then p :=j;
Troca(dados[i],dados[p])
end
end
end;
140 CAP

ITULO 13. ALGORITMOS DE ORDENAC



AO
Programa 13.5 Algoritmo heapsort
procedure DesceRaiz(var v: Vetor; raiz,ultimo: Indice);
{ Sup oe que sub arvores da raiz constituem heaps

}
var x: T; i,j: Indice; continua: boolean;
begin
with v do
begin
x := dados[raiz]; continua := true;
j := raiz; i := 2j;
while continua and (iultimo) do
begin
if (i<ultimo) and (dados[i]<dados[i+1])
then i := i+1;
if x<dados[i]
then begin dados[j] := dados[i]; j := i; i := 2i end
else continua := false
end;
dados[j] := x
end
end;
procedure HeapSort(var v: Vetor);
var i: Indice;
begin
with v do
begin
for i:= n div 2 downto 1 do DesceRaiz(v,i,n);
for i:= n downto 2 do
begin Troca(dados[1],dados[i]); DesceRaiz(v,1,i1) end
end
end;
13.6. EXERC

ICIOS 141
Programa 13.6 Ordenac ao iterativa por intercalac ao
procedure IntercalaIteAux(var v,w: Vetor; esq, dir, ld: Indice);
var i,j,k: Indice;
begin
{ Intercala os vetores v.dados[esq..dir 1] e v.dados[dir..ld 1] }
{ em w.dados[esq..ld 1] }
i := esq; j := dir; k := esq;
while (i<dir) and (j<ld) do begin
if v.dados[i]v.dados[j]
then begin w.dados[k] := v.dados[i]; i := i+1 end
else begin w.dados[k] := v.dados[j]; j := j+1 end;
k := k+1
end;
while (i<dir) do
begin w.dados[k] := v.dados[i]; i := i+1; k := k+1 end;
while (j<ld) do
begin w.dados[k] := v.dados[j]; j := j+1; k := k+1 end;
end;
procedure IntercalaIterativo(var v: Vetor);
var d, esq, dir, ld: integer; par: boolean; w: Vetor;
begin
{ Ordena de 2 em 2, de 4 em 4, ..., usando intercalac ao }
with v do begin
d :=1; par := false; w.n := v.n;
while d<n do begin
esq := 1; par := not par;
repeat
dir := esq+d; ld := dir+d;
if dir>n
then begin dir := n+1; ld := n end { direito vazio }
else if ld>(n+1) then ld := n+1;
if par
then IntercalaIteAux(v,w,esq,dir,ld)
else IntercalaIteAux(w,v,esq,dir,ld);
esq := dir+d;
until esq>n;
d := 2d
end;
if par then dados := w.dados;
end
end;
142 CAP

ITULO 13. ALGORITMOS DE ORDENAC



AO
Programa 13.7 Ordenac ao recursiva por intercalac ao
procedure IntercalaRecAux(var u,v,w: Vetor);
var i,j,k: Indice;
begin
{ Intercala os vetores u e v, deixando resultados em w }
with w do begin
i := 1; j := 1; n := u.n+v.n;
for k:=1 to n do begin
if (iu.n) and (jv.n)
then if u.dados[i]v.dados[j]
then begin dados[k] := u.dados[i]; i := i+1 end
else begin dados[k] := v.dados[j]; j := j+1 end
else if iu.n
then begin dados[k] := u.dados[i]; i := i+1 end
else begin dados[k] := v.dados[j]; j := j+1 end
end
end
end;
procedure IntercalaRecursivo(var v: Vetor);
var i: Indice; v1,v2: Vetor;
begin
with v do begin
if n>1 then begin
v1.n := n div 2; v2.n := nv1.n;
for i:=1 to v1.n do v1.dados[i] := dados[i];
for i:=1 to v2.n do v2.dados[i] := dados[i+v1.n];
IntercalaRecursivo(v1); IntercalaRecursivo(v2);
IntercalaRecAux(v1,v2,v)
end;
end
end;
Captulo 14
Programac ao Orientada a Objetos
14.1 Conceitos b asicos
O Prog. 14.1 (com continuac ao em 14.2) traz um exemplo de utilizac ao do paradigma de orientac ao a
objetos, no contexto da linguagemTurboPascal. Oexemplo ilustra, de maneira bastante elementar, conceitos
de heranca e de m etodos virtuais.
14.2 Implementac ao
14.3 Exerccios
143
144 CAP

ITULO 14. PROGRAMAC



AO ORIENTADA A OBJETOS
Programa 14.1 Exemplo de utilizac ao de objetos (continua)
program Figuras;
type
TFigura = class
posx,posy: Real;
function Area: Real; virtual; abstract;
procedure Desenha(escala: Real); virtual; abstract;
end;
TRetangulo = class(TFigura)
larg,alt: Real;
function Area: Real; override;
procedure Desenha(escala: Real); override;
end;
TCirculo = class(TFigura)
raio: Real;
function Area: Real; override;
procedure Desenha(escala: Real); override;
end;
procedure TRetangulo.Desenha(escala: Real);
begin
{Este procedimento est a incompleto}
Writeln(

Desenho de um ret angulo de largura



,larg:5:2,

e altura

,alt:5:2);
Writeln(

Posic ao:

,posx:5:2,

,posy:5:2)
end;
function TRetangulo.Area: Real;
begin
Area := largalt
end;
function TCirculo.Area: Real;
begin
Area := Pisqr(raio)
end;
14.3. EXERC

ICIOS 145
Programa 14.2 Exemplo de utilizac ao de objetos (continuac ao)
procedure TCirculo.Desenha(escala: Real);
begin
{Este procedimento est a incompleto}
Writeln(

Desenho de um crculo de raio



,raio:5:2);
Writeln(

Posic ao:

,posx:5:2,

,posy:5:2)
end;
procedure DesenhaImprimeArea(f : TFigura);
begin
Writeln;
f .Desenha(2.0);
Writeln(

Area:

,f .Area:6:2)
end;
procedure Translacao(f : TFigura; dx,dy: Real);
begin
with f do
begin
posx := posx+dx;
posy := posy+dy
end
end;
var
g1,g2: TFigura;
ret: TRetangulo;
circ: TCirculo;
begin
ret := TRetangulo.Create;
ret.posx := 0.0; ret.posy := 0.0;
ret.larg := 5.0; ret.alt := 10.0;
circ := TCirculo.Create;
circ.posx := 3.0; circ.posy := 10.0;
circ.raio := 5.0;
g1 := ret;
g2 :=circ;
Translacao(ret,2.0,3.0);
Translacao(g2,3.0,1.0);
DesenhaImprimeArea(g1);
DesenhaImprimeArea(g2)
end.

You might also like