Sei sulla pagina 1di 6

Estruturas de Dados II Arvores B

Universidade Federal Rural do Semirido a Tibrius O. Bonates e


tbonates@ufersa.edu.br

Introduo ca

Como vimos anteriormente, rvores binrias de busca balanceadas (tais como rvores AVL) so uma a a a a excelente ferramenta para se manter dados ordenados na memria principal. No entanto, seu uso o para armazenamento e, sobretudo manipulao, de dados em memria secundria limitado. As ca o a e razes para tal limitao advm do fato de que a leitura e escrita em memria secundria so tipio ca e o a a camente muito mais lentas do que as operaes correspondentes em memria principal, chegando a co o ser at trs ordens de magnitude (isto , da ordem de milhares de vezes) mais lentas. e e e As principais razes para a relativa lentido do acesso a dados em memria secundria so: o a o a a a movimentao de componentes mecnicos do disco r ca a gido para alcancar um determinado endereo, onde residem os dados de interesse; c dados armazenados em memria secundria so lidos em unidades de tamanho relativamente o a a grande, chamadas de blocos ou pginas, e comum que a leitura de uma seqncia de a e ue dados (por exemplo, chaves lidas durante uma busca em uma rvore), envolva a leitura de a vrios blocos. a Tipicamente, o custo de leitura de um bloco superior ao custo de processar todos os dados e lidos. Diantes destes fatos, interessante que o nmero de acessos a disco seja reduzido. e u Ao lidarmos com uma estrutura de rvore binria de busca, este nmero de acessos est diretaa a u a mente relacionado ` altura da rvore: o nmero de operaes de um algoritmo de busca, insero a a u co ca ou remoo em uma rvore deste tipo proporcional ` altura da rvore, isto , O(log2 n) operaes. ca a e a a e co Modicando-se o nmero mximo de lhos por n (quantidade que chamaremos de fator de ramu a o icao), temos uma expresso diferente para a altura da rvore: uma rvore perfeitamente balca a a a anceada com fator de ramicacao k tem altura O(logk n). Para um mesmo valor de n e diferentes valores de k, a altura da rvore pode variar amplamente. a Alm disso, pode ser vantajoso organizar os dados de forma a aumentar a quantidade de ine formao sobre a rvore que se torna dispon a cada operao de leitura no disco. Desta forma, ca a vel ca aumentamos as chances de que, durante uma operao de busca, o bloco lido mais recentemente ca contenha a informao necessria para concluir a busca: o registro procurado ou a evidncia de que ca a e o registro no existe na rvore. O mesmo racioc a a nio se aplica `s operaes de insero e remoo. a co ca ca As rvores B so uma generalizao de rvores binrias que incorporam as duas estratgias a a ca a a e descritas acima com a inteno de superar as diculdades causadas pela velocidade de acesso a ca memria secundria: (i) uma rvore B tende a ter uma altura baixa, signicando um menor nmero o a a u 1

de acessos a disco; e (ii) a altura reduzida obtida por meio do amrazenamento de vrias chaves por e a n, aumentando as chances de se encontrar rapidamente a informao necessria para se concluir o ca a uma operao de busca, remoo ou insero. ca ca ca

Estrutura do N o

Para o propsito de denir o tamanho do n de uma rvore B, iremos utilizar um parmetro inteiro o o a a d, de forma que cada n possua 2d chaves. A estrutura de um n NoB dada pelos seguintes campos: o o e a o num chaves: inteiro especicando quantas chaves esto sendo atualmente armazenadas no n; folha: valor Booleano indicando se o n uma das folhas da rvore (este campo opcional); oe a e pai: ponteiro para o pai do n; NULL se o n for a raiz; o o chaves[]: vetor contendo espao para 2d chaves; c f[]: vetor contendo espao para 2d + 1 ponteiros, um para cada lho do n. c o

Propriedades

Uma rvore B deve satisfazer todas as seguintes propriedades, para que se possa garantir o correto a funcionamento das operaes de busca, insero e remoo de elementos. E tambm de forma a co ca ca e garantir que a altura da rvore seja mantida baixa e que o espao reservado a cada n no seja a c o a sub-utilizado. as chaves armazenadas em um dado n esto ordenadas; o a f[0]: aponta para a subrvore que contm todos os ns com chave x satisfazendo x < a e o chaves[0]; f[num chaves]: aponta para a subrvore que contm todos os ns com chaves x satisfazendo a e o x > chaves[num chaves-1]; f[i]: aponta para a subrvore que contm todos os ns com chave x satisfazendo chaves[i-1] < a e o x < chaves[i]; todos os ns folhas tm mesma altura; o e todos os ns, exceto possivelmente a raiz, possuem pelo menos d elementos. Ao mesmo tempo o em que desejamos aumentar o fator de ramicao dos ns da rvore, importante tambm ca o a e e garantir que cada n esteja bem utilizado, isto , o espao resevado para cada n no esteja o e c o a sendo desperdiado ao se armazenar apenas algumas poucas chaves no n. c o

Percursos

As rotinas de percurso que vimos em conexo com rvores binrias podem ser diretamente adapa a a tadas para o caso de rvores com maior fator de ramicao, tais como as rvores B. Em particular, a ca a poss e vel processar cada uma das chaves armazenadas em uma rvore B de acordo com a ordem a natural destas chaves, utilizando-se um percurso em ordem. O cdigo abaixo implementa um percurso pr-ordem sobre uma rvore B: o e a

void preOrdem(NoB *x) { if (x != NULL) { visita(x); for (int i=0; i<num_chaves; i++) PreOrdem(x->f[i]); preOrdem(x->f[num_chaves]); } } Como exerc cio, interessante escrever os cdigos para as rotinas de percurso em-ordem e pse o o ordem para uma rvore B. a

Busca

A rotina de busca por uma determinada chave pode ser escrita de maneira similar ` rotina de busca a em rvores binrias: a a NoB * busca(NoB *p, int dado) { if (p == NULL) return NULL; int i=0; for (; i<p->num_chaves; i++) if (p->chave[i] >= dado) break; if ((i<p->num_chaves) && (p->chave[i] == dado)) return p; return busca(p->f[i], dado); } Uma verso no-recursiva desta rotina tambm pode ser facilmente implementada. No entanto, o a a e ganho em desempenho que geralmente se obtm com tal tipo de implementao bem menor do e ca e que no caso de rvores binrias. Isto se deve ao fato de que a altura de uma rvore B tende a ser a a a baixa, e o custo computacional elevado de funes recursivas est diretamente ligado ` quantidade co a a de chamadas recursivas efetuadas, que pode ser bem mais alta em uma rvore binria. a a

Insero ca

A rotina de insero em uma rvore B um pouco mais complexa do que a operao de busca. No ca a e ca entanto, trata-se de um procedimento naturalmente recursivo e sem casos especiais a serem tratados, como veremos a seguir. Em uma rvore B, com d chaves em cada n, que esteja inicialmente vazia, a insero de um a o ca novo elemento x (chave) acarreta a criao de um n, que passa a ser a raiz da rvore e que contm ca o a e apenas o elemento x inserido. Neste ponto, temos uma rvore B vlida, j que a raiz pode armazenar a a a uma quantidade menor do que d elementos. A insero subseqente de elementos se d atravs do armazenamento de cada novo elemento no ca u a e prprio n raiz, at que a raiz esteja cheia (isto , esteja armazenando exatamente 2d elementos). o o e e Por ocasio da insero de mais um elemento, teremos que criar espao extra para acomod-lo. a ca c a Neste caso, realizamos uma diviso do n raiz, criando um n adicional N e dividindo os 2d + 1 a o o elementos (os 2d existentes, mais o novo elemento) da seguinte forma: 3

os d menores elementos so armazenados no n original; a o os d maiores elementos so transferidos para o novo n N ; e a o um terceiro n P criado para acomodar unicamente a mediana dos 2d + 1 elementos, ou seja, o e o elemento do meio, que maior do que os d menores valores e menor do que os d maiores e valores. Este novo n P se torna a nova raiz da rvore. o a O n P , portanto, ir conter apenas uma chave e ir apontar para o n original e para o novo n N o a a o o como seus dois lhos. Desta forma, a rvore continua satisfazendo as propriedades de uma rvore a a B, e agora possui um n a mais. vel ` A medida em que novos elementos so inseridos, estes sero armazenados em uma das duas a a folhas da rvore, dependendo dos valores das chaves. No momento em que uma das folhas estiver a cheia e tentarmos inserir uma nova chave naquela folha, um outra operao de diviso precisar ser ca a a efetuada, durante a qual: (i) as chaves da referida folha, juntamente com a nova chave, sero divididas entre o prprio n a o o folha e um novo n folha; e o (ii) o elemento mediano dentre os 2d + 1 valores (os 2d valores existentes na folha e a nova chave que est sendo inserida) ser armazenado na raiz, que, por sua vez, conter tambm um novo a a a e ponteiro para o n recm-criado, totalizando trs lhos. o e e Este procedimento pode ser repetido at que a prpria raiz j esteja cheia e tentemos adicionar uma e o a nova chave a ela. Esta operao ocasionaria uma divio do n raiz em dois ns da mesma forma ca a o o descrita acima e a criao de uma nova raiz, que teria como lhos a raiz anterior e o novo n criado. ca o Na verdade, este algoritmo de insero pode ser aplicado igualmente para rvores maiores do que ca a a que consideramos acima. De maneira geral, novas chaves so sempre inseridas em algum n folha. a o Quando tentarmos inserir uma chave em um n folha que j estiver cheio, um novo n ser criado, d o a o a elementos sero transferidos para este n, um elemento ser inserido no n pai, juntamente com um a o a o ponteiro para o novo n. No entanto, esta insero de chave no n pai pode, por sua vez, resultar na o ca o diviso deste n, e assim por diante. E poss a o vel, portanto, que uma nova insero desencadeie uma ca seqncia de inseres at chegar ` raiz. Neste caso, a raiz propriamente dita poderia ser dividida, ue co e a resultando na criao de uma nova raiz. ca Note que esta discusso essencialmente mostra que a insero em uma rvore B pode exigir a ca a uma quantidade de operaes da ordem de logk n, onde k o fator de ramicao da rvore, j que co e ca a a pode ser necessrio efetuar a diviso de O(logk n) ns. Alm disso, interessante notar que o unico a a o e e momento em que a altura da rvore aumenta durante uma operao de diviso da raiz. a e ca a

Remoo ca

A operao de remoo em rvores B um pouco mais complexa do que a operao de insero. No ca ca a e ca ca caso da remoo de um elemento x que reside em um n interno (ou seja, um n que no folha), ca o o a e o procedimento similar ` remoo em uma rvore binria de busca: obtemos um ponteiro para o e a ca a a sucessor de x, trocamos de posio o elemento x e seu sucessor, e, por m, deletamos o elemento x ca na sua nova posio de folha. ca O sucessor de uma chave em uma rvore B pode ser obtido seguindo-se a subrvore que contm a a e elementos maiores que x (e menores do que o elemento imediatamente superior a x no n) e seguindo o 4

os lhos mais ` esquerda naquela subrvore. Veja que este procedimento anlogo `quele utilizado a a e a a para se encontrar o sucessor de um elemento em uma rvore binria de busca. a a A seguir, discutiremos a operao de remoo do ponto de vista de que o elemento a ser removido ca ca est armazenado em uma folha, j que o caso da remoo de um elemento em um n interno recai, a a ca o em ultima anlise, no caso de remoo em uma folha, conforme discutido acima. a ca Se a folha armazena mais de d chaves, podemos simplesmente remover o elemento e a rvore a resultante continua sendo uma rvore B vlida. No entanto, caso a folha possua apenas d elementos, a a a remoo causaria uma violao da propriedade de que cada n (exceto possivelmente pela raiz) ca ca o deve armazenar um m nimo de d chaves. Para corrigir esta situao, necessrio examinar um dos vizinhos do n folha em questo. Seja ca e a o a v este n folha, que contm o elemento a ser removido. Caso o vizinho w armazene mais de d chaves, o e poss e vel redistribuir os elementos de w e v, juntamente com o elemento armazenado no n pai o que separava w e v, de forma que w e v passem a ter ambos pelo menos d elementos. Note que e necessrio atualizar a chave do n pai que separa w e v. a o Caso o vizinho w armazene apenas d elementos, podemos mover os elementos de w para v, juntamente com o elemento do n pai que separa v de w. Desta maneira, combinamos os dois ns em o o um unico n, deletamos w, e removemos o ponteiro existente no n pai e que apontava para w. Esta o o operao, contudo, pode resultar em um nmero de elementos menor do que d no n pai. Neste ca u o caso, a operao de recombinao de um n com um de seus vizinhos aplicada sobre o n pai, e ca ca o e o assim por diante, subindo na rvore na medida do necessrio. a a No cenrio em que a raiz tenha seu unico elemento removido devido ` recombinao de seus dois a a ca unicos lhos em um unico n, a raiz pode ser deletada e o n resultante da recombinao passa a o o ca ser a nova raiz. Este a unica situao em que a altura da rvore reduzida. e ca a e Note, tambm, que esta discusso estabelece o pior caso da operao de remoo como O(logk n), e a ca ca assim como no caso da operao de insero. ca ca

Extenses o

Apesar de nossa denio de n de uma rvore B no incluir nenhuma informao adicional associca o a a ca ada a cada chave, o uso t pico de uma rvore B envolve o armazenamento deste tipo de informao a ca extra. Ou seja, ao se fazer uma busca em uma rvore B, deseja-se encontrar a informao que est a ca a associada `quela chave que foi buscada. A aplicao clssica deste tipo de estrutura no projeto de a ca a e ndices para bancos de dados. Note que, ao armazenarmos informaes adicionais em um n, precisamos ceder espao em cada co o c n, reduzindo o nmero de chaves (e ponteiros) que podemos armazenar em cada n individual. o u o Diante desta situao, faz sentido denir uma variao de rvores B que permita armazenar tais ca ca a informaes adicionais sem comprometer o fator de ramicao da rvore. Uma destas variaes co ca a co e exatamente o tipo de rvore que descreveremos a seguir: a rvore B+. a a Arvores B+ so variantes de rvores B, nas quais os ns internos (aqueles que no so folhas) a a o a a armazenam apenas as chaves propriamente ditas mas no as informaes perifricas associadas `s a co e a chaves. Apenas os ns folhas armazenam as informaes perifricas. Desta forma, cada chave o co e e

armazenada em um n interno e tambm em um n folha. o e o Conseqentemente, o fator de ramicao pode ser aumentado nos ns internos, j que o espao u ca o a c utilizado por estes ns utilizado exclusivamente para armazenar as chaves e os ponteiros. Portanto, o e uma implementao de rvores B+ faz uso de dois tipos de registros, com um deles sendo espec ca a co para ns internos, onde no se reserva espao para as informaes perifricas. o a c co e

Exerc cios
1. Implementar uma rotina de percurso em ordem para uma rvore B. a 2. Implementar uma rotina de percurso ps-ordem para uma rvore B. o a 3. Implementar uma rotina de percurso em n vel para uma rvore B. a 4. Implementar uma rotina no-recursiva de busca em uma rvore B. a a 5. Inserir os elementos de 1 a 20 em uma rvore B mantida em memria e com fator de ramicao a o ca 4.

Implementar os seguintes itens em C ou C++.

Potrebbero piacerti anche