10.3.	Técnicas de Gerência de Arquivos Utilizando Árvores
•	Árvores podem também ser ser utilizadas para gerência de arquivos.
•	Possibilidade de indexação:
- Chave Primária (Árvores Binárias e Árvore-B)
- Chave Primária e Secundária (Árvore K-D)
Duas opções: 
•	Arquivo Único: Utilizamos uma árvore diretamente, colocando tanto a chave como os dados em um nodo da árvore.
Vantagem: Economia de espaço
Desvantagem: Dados misturados com informação de indexação. Só um índice é possivel.
•	Utilizamos a árvore como Arquivo de Índices. Cada nodo da árvore possui informação sobre a chave e ponteiros para um outro arquivo, o arquivo de registros de dados, que contém os reais registros de dados completos.
Vantagens: Dados independentes do arquivo de índices. 
Arquivo de índices pode ser jogado fora, registros de dados copiados independentemente de seus índices ou novo arquivo de índices pode ser gerado indexando os dados por outra chave. 
Vários arquivos de índices para um mesmo arquivo de dados são possíveis simultaneamente, indexando-o por diferentes chaves.
Podemos gerar um novo arquivo de índices enquanto o velho continua disponível para usuários.
Desvantagem: Desperdício de espaço - chaves do arquivo de registros de dados utilizadas para indexação replicadas no arquivo de índices. 
Conjunto de dados indexado por uma chave longa (ex.: nome, endereço) terá arquivo de índices extremamente grande.
10.3.1.	Aspectos Gerais
Vantagens
•	Aplicação Imediata: Supondo-se a possibilidade do endereçamento relativo por registros de arquivos, algoritmos de gerência de árvores podem ser (quase todos) diretamente aplicados a arquivos. Ao invés de ponteiros para áreas de memória, utiliza-se campos inteiros com endereços relativos de registros.
•	Pesquisa rápida: Árvores oferecem tempos de acesso a registros relativamente curtos, com caminhos de busca O(log n).
Desvantagens
•	Desperdício de Espaço. Indexação por chave secundária impõe (com exceção das árvores k-d) necessidade de vários arquivos de índices, um para cada índice.
•	Redundância de valor de chave cara. Quando um valor de chave tem alta redundância (índices de chave secundária. Ex.: cargo em um arquivo de depto. pessoal) muitos registros do arquivo de índices têm de ser lidos.
•	Manutenção Cara. Em aplicações com freqüentes inserções e exclusões de registros e chaves, a manutenção de um arquivo de índices em uma árvore balanceada é extremamente cara.
Solução: Registros excluídos são somente marcados. 
Registros novos incluídos são sempre incluídos como folhas. 
Rebalanceamento com exclusão definitiva realizado periodicamente.
Problema: Deterioração rápida da árvore.
•	Listagem seqüencial cara. Listagem de registros em ordem de chave implica em visitas repetidas a todos os nodos da árvore que não são folha.
Solução: colocar o próprio registro na pilha. Problema: estouro de pilha para registros grandes ou árvores profundas.
Resumo Geral
Árvores são indicadas para aplicações onde uma pesquisa rápida é muito importante, poucas alterações ocorrem em um período de tempo e a atualização da árvore (rebalanceamento) pode ser feita em batch em períodos em que a estrutura não é utilizada.
10.3.2.	Árvore Binária Paginada
•	Subárvores são concatenadas em um único registro.
•	Adequado para árvores com nodos pequenos:
- Árvores onde nodo possui um ponteiro p/arquivo de registros
- Árvores com registros de dados realmente pequenos.
•	A nível de arquivo de índices, um registro do arquivo possui vários nodos da árvore.
Vantagem
•	Muito menos acessos a a disco são realizados.
Desvantagens
•	Todos os algoritmos sofrem alterações.
•	Rebalanceamento fica muito mais complexo.
10.3.3.	Árvore B 
•	Árvores-B (Bayer&MCCreight 1972) às vezes também chamadas Árvores-Bayer ou Árvores Multivias, foram originalmente concebidas para a implementação de mecanismos de indexação por chave primária em memória secundária. 
•	Permite um número menor de nós (menor altura) e por conseguinte menos acessos a disco.
•	Implementações comuns utilizam arquivo de índices com ponteiros para arquivo de registros de dados.
Vantagens
•	Mais adequada a arquivos voláteis do que árvores binárias. 
Inclusão: Redistribuição de chaves pode ser efetuada em tempo de operação. 
•	Nodos com muitas chaves tornam paginação desnecessária.
•	Economia de espaço: poucos ponteiros entre nodos.
•	Algoritmos são os mesmos que para árvore-B em memória principal.
Desvantagens
•	Não oferece solução econômica para indexação por chave secundária ou com alta redundância de valor de chave.
•	Exclusão com marcação e redistribuição offline.
•	Não oferece solução barata para problema de percurso por seqüencia de chave. 
Performance de busca por chave é idêntica a da árvore binária, se só ponteiros para nodos são empilhados. 
Problema: Nodo não-folha com m chaves é visitado m vezes.
10.3.4.	Árvore B+
•	Nas árvores de índices, os nodos só possuem, além da chave, um ponteiro para o registro de dados em outro arquivo. 
Isto pode ser levado ao extremo, se nós concentramos os ponteiros para o arquivo de registros nas folhas. 
- Nós internos servem só como referência para o percurso.
- Chaves de nós internos são repetidas nas folhas.
•	Árvore é dividida em Index Set e Sequence Set.
•	Nodos do Sequence Set (folhas) são encadeados.
Vantagens Árvore B+:
•	Mecanismo para percorrer seqüencialmente o arquivo de registros de dados sem que seja necessário visitar toda a árvore.
•	Mecanismo para percorrer seqüencialmente o arquivo de registros de dados sem que seja necessário ordenar o arquivo de registro de dados.
10.3.5.	Árvore K-D
•	Árvore binária para indexação multichave. Também chamada Árvore de Pesquisa Binária Multidimensional.
•	“Redescoberta” pela Inteligência Artificial como mecanismo de indexação de Cases de Casos em Raciocínio Baseado em Casos (CBR - Case-Based Reasoning).
Estrutura
•	Uma árvore k-d é uma árvore onde k é o número de chaves para cada registro. Assim, chamamos uma árvore com três chaves de árvore 3-d (tridimensional), etc.
•	Cada registro em uma árvore k-d possui, além dos dados e ponteiros, um conjunto ordenado de k valores de chaves (v0,...,vk-1). 
•	Associado a cada nodo P está um discriminador DISC(P), que é utilizado para especificar qual chave da k-tupla v0,...,vk-1 será utilizada neste nodo para tomar uma decisão de ramificação.
Geralmente o discriminador é função da profundidade do nodo (resto da divisão da profundidade pelo número de chaves).
•	O filho à esquerda é chamado loson(P) e o à direita hison(P).
•	Caminhamento e Inserção (nas folhas) são realizados seguindo-se a seguinte regra de decisão (dados Q = chaves do registro procurado ou registro a ser incluído e P = nodo):
SE Kj(Q) < Kj(P) ENTÃO o registro Q está em loson(P)
SE Kj(Q) < Kj(P) ENTÃO o registro Q está em loson(P)
•	Se dois valores de chave são iguais, a decisão é tomada com base nos demais valores de chave na seguinte ordem (superchave):
Sj(P) = Kj(P),Kj+1(P),...,Kk-1(P),K0(P),...,Kj-1(P)
•	Se incluirmos o conjunto de registros com 3 chaves abaixo em uma árvore 3-d teremos a árvore mostrada abaixo:
•	A primeira decisão de ramificação (raiz) é tomada com base na chave primária (8), no nível 1 com base na segunda chave e no nível 2 com base na terceira chave. No nível 3 voltamos a usar a chave 0 como critério de decisão.
Vantagens
•	Árvores k-d podem ser utilizadas diretamente para todos os 3 tipos de pesquisa: simples, com limites e booleana.
•	O tempo médio de acesso a um registro não é pior do que o da árvore binária. Todas as características de tempo de pesquisa, complexidade, etc da árvore binária valem, no que diz respeito à pesquisa, também para a árvore k-d: O(1,4 log2 n).
•	Inserção (não balanceada) de um nodo requer também tempo O(log2 n).
•	Flexibilidade: Aplicável a qualquer tipo de aplicação onde se queira fazer recuperação de chaves secundárias ou recuperação multichaves.
Desvantagens
•	Gera árvores de profundidade extremamente grande. 
Solução: Pode ser resolvido através da paginação.
•	Inserção balanceada é extremamente cara.
•	Rebalanceamento (apos várias inserções ou exclusões) 
também extremamente caro.
Resumo
•	Boa técnica de indexação para arquivos somente com ou com muitas chaves secundárias (Ex.: bases de casos em CBR).
•	Boa técnica para aplicações onde há poucas modificações.
•	Utilização da árvore k-d como árvore de índices com paginação é sugerida para implementações em disco.
Sugestão para facilitar buscas booleanas: pelo menos uma subárvore com k níveis em cada página.

10.4.	Técnicas de Gerência de Arquivos Utilizando Listas
•	Técnicas de indexação através de listas provêem uma solução excelente para a recuperação de chaves secundárias. 
•	Exemplos típicos de chave secundária: CARGO, DEPARTAMENTO, IDADE, etc.
•	Lista: estrutura de acesso inerentemente seqüencial. 
Não é adequada: para conjuntos de dados com somente um ou muito poucos registros por valor de chave. 
Situação ideal: Poucos valores possíveis para uma chave e muitos registros possuindo este valor de chave.
•	Suportam os três tipos de solicitações de recuperação.
•	Se a aplicação possui uma chave tipicamente primária 
(Ex.: nome, cpf, id), a melhor técnica é utilizar uma técnica de indexação primária (árvore-B p.ex.) para a organização geral do arquivo e utilizar uma das duas técnicas de listas encadeadas abaixo para a indexação somente de chaves secundárias.
10.4.1.	Atualização de Arquivos com Índices em Lista
Independentemente do tipo de indexação por lista, dois aspectos são gerais:
1.	Um registro pode ser membro de duas ou mais listas.
2.	Marcar um registro como excluído é aqui muito mais prático do que atualizar diversas listas. 

10.4.2.	Multilista
O arquivo multilista é a implementação mais intuitiva da idéia de se utilizar listas encadeadas para indexar chaves secundárias.
Princípios básicos:
•	Cada campo do arquivo de registros de dados a ser tratado como uma chave é encadeado como uma lista, possuindo além do campo com o valor de chave, também um campo com um apontador para o próximo registro com o mesmo valor de chave p/este campo.
•	Além desse encadeamento, o arquivo possuirá um diretório.
•	O diretório do arquivo multilista é constituído por um arquivo índice para cada campo indexado e um índice geral apontando para os índices-de-campo.
•	O arquivo-índice de um campo possue uma seqüência de cabeças-de-lista contendo: o valor de chave indexado, o número de elementos na lista e o endereço do primeiro elemento da lista. 
Em caso de chaves contínuas, o limite superior do intervalo representado pela entrada será dado.
Exemplo de um diretório (baseado em Claybrook 77):
Visão “pictórica” do encadeamento provocado pelas listas dos gráficos anteriores (Claybrook 77):
•	Os endereços (1.5, 0.7, 2.7) referem-se a uma forma de endereçamento relativo mais antiga, onde um arquivo é dividido em “células”.
Formas de Pesquisa
•	A pesquisa é realizada através de criação de tabelas de resultados parciais, cuja união ou intersecção é calculada de acordo com o tipo de pesquisa (disjuntiva ou conjuntiva) que é realizado.
•	Uma lista é percorrida e todos os elementos (registros de dados desta lista) são colocados em uma tabela.
•	Em pesquisas simples (chave=valor) a primeira tabela gerada já é a resposta à pesquisa.
•	Em pesquisas booleanas ou por intervalo o procedimento é mais complexo:
1.	Para todas expressões conjuntivas escolhemos o valor de chave com o menor número de elementos para a geração da tabela inicial. Esta tabela é gerada copiando-se todos os registros correspondentes do arquivo de registros de dadso para lá.

Em seguida, todas as outras listas de valores-de-chave são percorridas e elementos da primeira tabela não encontrados nestas são eliminados.
2.	Para operações disjuntivas, o procedimento consiste em se iniciar com uma tabela gerada a partir da maior lista de elementos e incluir elementos das outras listas ainda não presentes.
3.	Para combinações de operações conjuntivas e disjuntivas a geração de tabelas intermediárias é necessária. Claybrook sugere aqui, que inicialmente se transforme a expressão-pergunta na forma disjuntiva normal, para depois iniciar o processo de busca.

Vantagens
•	É um método relativamente simples e cononômico em termos de espaço de se indexar arquivos por chave secundária.
•	Para pesquisas simples por chave secundária é o método mais econômico: O(m) : m<n, para devolver todos os registros que satisfazem uma condição simples.
•	Suporta todos os tipos de pesquisa, mesmo expressões booleanas complexas.
Desvantagens
•	Chave Primária: É totalmente inadequado para chaves 
primárias.
•	Operação de Cópia: A técnica de pesquisa de se copiar registros de dados para uma tabela pode se tornar cara em uma pesquisa conjuntiva, onde:
a) registros completos que vão mais tarde ser descartados são copiados para uma tabela.
b) todas as listas que fazem parte de uma pesquisa conjuntiva são pesquisadas completamente, mesmo que só uma fração muito pequena dos dados satisfaça a expressão booleana.
•	Não existe nenhum mecanismo, em pesquisas por intervalo ou booleanas que impeça que registros que já tenham sido visitados através de uma das listas sejam visitados novamente através de outra lista.
Resumo
A Multilista é um método intuitivo. A sua grande desvantagem é que precisamos sempre copiar os registros por completo para uma tabela para podermos trabalhar com eles em pesquisas que não sejam simples.

10.4.3.	Lista Invertida
A organização de um arquivo Lista Invertida consiste de um diretório contendo uma ou mais listas-índice e um ou mais arquivos endereços de de registros de dados, além do arquivo de registrso de dados em si. 
O diretório é constituído por dois grupos de arquivos:
1.	Listas-índice para valores de chaves;
2.	Arquivo com apontadores para registros organizado por valores de chave.
Uma entrada do índice de uma chave possui os seguintes dados:
1.	O valor da chave;
2.	Um indicador para a lista de registros contendo o valor de chave;
3.	O número de registros da lista.
Uma entrada da lista de registros possui os seguintes dados:
1.	Um conjunto de m campos contendo endereços de registros de dados;
2.	Um apontador para a posição do próximo registro da lista de registros.
Isto está representado no exemplo adiante:

Exemplo (as listas-índice para cargo e depto estão omitidas, da mesma forma só foram representados endereços de registro para idade = 18 e 20 e salário = 10.000 e 20.000):
•	No exemplo acima endereços de registro dos arquivos presentes no gráfico estão representados por setas, endereços de registros do arquivo de registros de dados por valores de endereço relativo.
•	Evidentemente podem existir vários arquivos de endereços de registro e várias listas-índice. Alternativamente podemos colocar os registros de endereços todos em um único arquivo.
Exemplo (Claybrook 77):
•	Neste exemplo somente um arquivo para listas de endereços de registro é utilizado.
•	Os endereços do exemplo (1.5, 0.7, 2.7) também se referem a uma forma de endereçamento relativo mais antiga, onde um arquivo é dividido em “células”.

Técnica de Pesquisa
•	Pesquisas de chaves em arquivos Lista Invertida são realizadas também através da geração de tabelas. 
•	Ao contrário da multilista, aqui as tabelas podem ser bem mais simples e a pesquisa para a construção destas pode ser bem mais efetiva, sem realmente ler os registros de dados.
•	Pesquisas de chave simples geram uma tabela de saída com todos os registros com o valor de chave para aquela chave, depois de ter sido gerada uma tabela de endereços de registros com o valor de chave.
•	Pesquisas booleanas são as mais complexas. Nestas pesquisas, várias tabelas de endereços são geradas, iniciando-se sempre pelo valor de chave com o menor número de ocorrências. 
Em pesquisas conjuntivas, endereços não encontrados p/outras chaves são retirados.
Em pesquisas disjuntivas, são adicionados. 
Com a tabela de endereços resultante é criada a tabela de registros de dados definitiva. Assim somente os registros realmente necessários vão ser lidos do arquivo de registros de dados.
•	Exemplo: Considere o seguinte arquivo de lista invertida:
•	Se fizermos a pesquisa (idade = 18 & salário = 10.000) para descobrir que são os filhos dos donos da empresa, vamos ter como tabela inicial (103, 205, 101), pois salário=10.000 tem só 3 registros na sua lista de endereços de registros.
•	A seguir a lista de endereços de registros de idade = 18 é percorrida e todos os não encontrados são eliminados da tabela.
•	Pesquisas mais complexas vão dar origem a tabelas mais complexas.
Vantagens
•	Bom suporte para todos os tipos de pesquisas, desde que o campo pesquisado seja indexado.
•	Uma das melhores técnicas para chaves secundárias com altas taxas de redundância de valor de chave.
•	O fato de podermos realizar todas as pesquisas de chaves que possuam índices diretamente nas tabelas de endereços provê uma vantagem imensa sobre a multilista.
Desvantagens
•	Em pesquisas booleanas onde pelo menos dois dos elementos procurados não estão indexados, temos de criar tabelas contendo cópias de todos os registros que satisfizeram a parte indexada da consulta.
•	Se mais de um elemento não está indexado e a pesquisa é conjuntiva, isto pode gerar tabelas grandes e se tornar caro.
•	Atualização é complexa, pois todos os arquivos de índices devem ser atualizados.