Estruturas de Dados - T.332
Capítulo 10
Gerenciamento de Arquivos
Parte II: Árvores e Listas
[RTF] [PostScript]
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[Atilde]O o registro Q está em loson(P)
SE Kj(Q) < Kj(P) ENT[Atilde]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:
- Um registro pode ser membro de duas ou mais listas.
- 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:
- 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.
- 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.
- 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:
- Listas-índice para valores de chaves;
- Arquivo com apontadores para registros organizado por valores de chave.
Uma entrada do índice de uma chave possui os seguintes dados:
- O valor da chave;
- Um indicador para a lista de registros contendo o valor de chave;
- O número de registros da lista.
Uma entrada da lista de registros possui os seguintes dados:
- Um conjunto de m campos contendo endereços de registros de dados;
- Um apontador para a posição do próximo registro
da lista de registros.
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.