Вы находитесь на странице: 1из 36

Rafael da Silva RA 11115509

Srgio Maracaj Junior - RA 11000315


Ren Gutierrez RA 11184109

rvores 2-3
Estudo terico e prtico sobre a estrutura de dados rvore 2-3

Projeto apresentado disciplina MCTA002 Algoritmos e Estrutura de Dados II


do Bacharelado em Cincia e Tecnologia da Universidade Federal do ABC.

Prof. Dr. Harlen Costa Batagelo

Santo Andr - SP
2016
1. Definies
A rvore 2-3 representa o tipo mais simples de uma rvore multidirecional: uma rvore de
busca que composta por no mximo dois diferentes tipos de ns: o 2-n e o 3-n. A
presena dos 3-ns o que a difere das rvores binrias, como veremos adiante.
Esta uma soluo para diminuir o crescimento da altura das rvores, utilizando-se do
artifcio de colocar mais de uma chave num mesmo n.

1.1. Ns
Os ns da rvore 2-3, como em toda rvore, podem ser definidos como ns internos ou
folhas. Uma folha segue sua definio trivial, ou seja, no possui filhos. A literatura diverge
entre definir as folhas como ns sem contedo (NIL) ou como ns comuns que possuem
apontadores nulos; esta segunda forma ser como consideraremos os ns folhas, por questes
de maior objetividade.
Desta forma, os ns que compem a rvore 2-3 se apresentam como se segue:
O 2-n exatamente um n de rvore binria, ou seja, possui 1 chave e 2 filhos;
O 3-n possui 2 chaves e 3 filhos;
Os ns folhas so exatamente como os tipos acima listados, porm seus filhos
apontam para null.
A estrutura dos ns prev alm das chaves e dos apontadores filhos, um contador de chaves,
que auxiliar na correta implementao da rvore:

classe No23
{
int numeroDeChaves;
TipoChave chave[2];
TipoValores dadosSatelites[2]; // Se houver dados satlites...
No23* filhos[3]; /* 0 = esquerda, 1 = meio (se 3-n) ou direita (se 2-
n), 2 = direita (se 3-n) */
}
Cdigo 1 Pseudocdigo da classe No23

Obedecendo a estrutura de uma rvore de busca tpica, temos que se o n for um 2-n,
ocorrer o mesmo que um n de rvore binria de chave k, ou seja, a subrvore esquerda
possui todas as suas chaves menores k, ao passo que a subrvore direita contm todos seus
elementos maiores que k. J quanto ao 3-n, temos que suas duas chaves estaro sempre
ordenadas, ou seja, se chave[0] = k1 e chave[1] = k2, ento k1 k2; de forma anloga ao 2-n,
a subrvore esquerda contm todos as chaves menores que k1, a subrvore central possui
todas as chaves compreendidas entre k1 e k2 e a subrvore direita corresponde s chaves
maiores que k2.

1.2. Propriedades da rvore 2-3


Toda rvore 2-3 obedece s seguintes propriedades:
Todo n, necessariamente, um 2-n ou um 3-n;
Todo filho de um n interno um n, ou seja, no h n interno com apontador nulo;
Todas as folhas esto no mesmo nvel.

1
Esta ltima propriedade o trao mais importante da rvore 2-3: ela perfeitamente
balanceada. Este fato torna a rvore 2-3 bastante eficiente quando tratamos da operao de
busca. Uma rvore 2-3 apresentar-se-, assim, como na figura 1:

Figura 1 Exemplo de rvore 2-3 apresentando sua estrutura tpica [1]

2. Busca
A busca em uma rvore 2-3 segue lgica similar busca em uma rvore binria, somente
acrescentando um condicional associado ao nmero de chaves, para que se realize uma
segunda comparao apenas quando for necessrio. O processo consiste em fazer
comparaes entre uma chave k procurada e a(s) chave(s) do n selecionado, partindo da raiz.
De acordo com o resultado baseado na ordem da estrutura definida no fim do item 1.1 ,
ser decidido em qual subrvore continuar com o processo, repetindo estas etapas at que se
encontre o n que contem a chave (ou null, se esta no existir na rvore), conforme a figura 2:

Figura 2 Operaes de busca (bem-sucedida e malsucedida) numa rvore 2-3[1]

2
Podemos proceder com a busca utilizando o mtodo recursivo (que chama a funo de busca
para a raiz da subrvore escolhida cada vez que o n no encontrado) ou um mtodo
sequencial, mais praticvel em rvores muito grandes.
Um algoritmo no recursivo para a busca apresentado a seguir:

/* busca retorna o n que possui a chave k procurada */


No23 busca(Arvore T, TipoChave k)
{
No23 x = T.raiz;
// Se k no a primeira chave ou a segunda (se houver), faa a busca.
while (x != null && k != x.chave[0] && (x.numeroDeChaves == 1 ||
(x.numeroDeChaves == 2 && k != x.chave[1])))
{
if (k < x.chave[0]) x = x.filho[0];
else if (x.numeroDeChaves == 2 && k > x.chave[1])
x = x.filho[2];
else x = x.filho[1];
}
return x;
}
Cdigo 2 Busca em uma rvore 2-3

A complexidade de tempo da busca na rvore 2-3, assim como na rvore binria, est
relacionada diretamente sua altura. simples a anlise deste caso, pois os piores casos, que
envolvem buscas malsucedidas ou uma chave encontrada na ltima comparao possvel,
obrigam o algoritmo a percorrer toda a altura da rvore. Os casos extremos consistem numa
rvore com todos os ns sendo 2-ns (ou seja, uma rvore binria) e o melhor caso em
relao altura aquele no qual todos os ns esto cheios (ou seja, 3 ns).
Para o pior caso, ocorre o mesmo que a rvore binria cheia, ou seja, a altura da rvore ser
log 2 (sendo n o nmero de chaves), demandando o mesmo nmero de operaes (1
comparao em cada n visitado) no caso mais extremo. J para o melhor caso, temos que a
altura cai para log 3 . Desta forma a altura h da rvore log 3 log 2 , portanto
0,6309 log 2 log 2 . O possvel inconveniente que para os 3-ns, com chaves k1
k2, caso se busque uma chave maior que k1, ser necessrio efetuar 2 comparaes para
determinar qual ser o prximo n; mesmo assim espera-se que para a busca seu desempenho
mdio seja melhor que o das rvores binrias estudadas no curso (AVL e Rubro-Negra).
Enfim, fica claro que a complexidade de tempo da busca (log ).

3. Insero
O algoritmo para insero mais simples quando mostrado na teoria do que quando aplicado
na prtica. Desta forma, para no poluir o relatrio com pseudocdigos demasiados extensos,
inclumos um apndice com os cdigos relativos insero (e tambm a busca) na linguagem
Java, devidamente comentados. Estes cdigos sero os mesmos utilizados para os testes
prticos da ltima seo.
O processo de insero numa rvore 2-3, assim como numa rvore binria, ocorre a partir de
uma busca pela posio na qual deve ser inserida a nova chave. Em vez de criar um novo n
com esta chave e simplesmente inseri-la num ponteiro nulo (o que estragaria o perfeito
balanceamento da rvore), devemos inserir esta chave na folha que foi encontrada ao fim do
processo de busca.

3
Se esta folha um 2-n, o processo mais simples: basta comparar a nova chave k com a
chave do n, kn. Se k < kn, ento kn deslocada para a direita e k assume sua posio. Caso
contrrio, k passa a ser a chave do lado direito. A figura 3 ilustra esta situao:

Figura 3 Insero em uma folha do tipo 2-n [1]

O problema muda quando tentamos realizar a mesma operao em uma folha 3-n. Para
solucionar este caso, criado temporariamente um 4-n (n que pode abrigar 3 chaves e 4
filhos). Para no infringir a propriedade mais bsica da rvore 2-3, este 4-n precisa ser
convertido em uma subrvore com trs ns, contendo uma chave cada. A figura 4 ilustra este
procedimento:

Figura 4 Insero local em um 3-n [1]

Caso o 3-n em questo no seja a raiz, devemos levar em considerao que o n pai
resultante da diviso do 4-n ser incorporado pelo nvel acima. Quando o pai do 3-n
original (antes da insero) um 2-n, a questo simples de resolver, trata-se de repetir o
algoritmo da figura 3 com o cuidado de arrumar os ponteiros para os novos filhos, de acordo
com a correta ordenao. Para a insero em um 3-n cujo pai tem uma chave, deve-se criar
novamente o 4-n temporrio, quebr-lo como na figura 4, e incluir a chave do meio no n
pai. A figura 5 mostra esse processo:

4
Figura 5 Insero em um 3-n cujo pai tambm um 3-n [1]

O mtodo de insero pode se prolongar e fazer com que essas inseres e divises vo
subindo pela rvore, somente se interrompendo ao se encontrar um 2-n. Se no decorrer da
insero a prpria raiz ficar com trs chaves, a chave do meio vira um n raiz, e as outras
duas chaves viram cada uma um n, com uma chave. Esta a nica situao em que ocorre o
crescimento da altura da rvore. Ao contrrio das rvores binrias, onde o crescimento
acontece em torno das folhas, a rvore 2-3 cresce pela raiz.

5
Figura 6 Insero e quebra na raiz [1]

A complexidade temporal da insero no uma questo difcil, j que a busca realizada no


incio, como foi discutido anteriormente, O(log n). Tomando o fato que a atribuio de
novos ponteiros e chaves O(1), temos que a operaes de construo e diviso dos 4-ns,
quando necessrios, tambm ser O(1).
Sendo h a altura da rvore e analisando o pior caso, que envolve a quebra da raiz,
observamos que ocorrero no mximo h + 1 alocaes envolvendo 4-ns a cada nova
insero. Sendo h (log n), observamos que todo o mecanismo de insero envolver
O(log n) + O(log n) + O(1) operaes ao total. Logo, a complexidade de tempo assinttica da
insero em uma rvore 2-3 O(log n).

4. Remoo
O algoritmo para remoo mais complexo, inclusive pouco detalhado o contedo a
respeito desta operao na literatura. Trata-se de uma operao com mais casos especficos
que a insero e a nica que pode danificar a estrutura da rvore 2-3, em especial a
propriedades envolvendo a completude (que um n tem todos os filhos vlidos ou todos
nulos) e o balanceamento (que todas as folhas esto no mesmo nvel).

6
Desta forma, muitas vezes necessrio proceder a ajustes especficos na estrutura da rvore
(assim como acontece com rvores AVL e rubro-negras), mas considerando que nas rvores
2-3, no basta apenas modificar ponteiros entre ns, mas muitas vezes preciso modificar a
estrutura dos prprios ns (modificando o nmero de chaves) e permutar chaves entre ns,
como veremos nas figuras a seguir. A estratgia para lidar com este problema fazer a
remoo de forma anloga insero, em outras palavras, se procura levar a chave, atravs de
permutaes entre ns, at uma folha, e da eliminar o registro, fazendo ajustes quando
necessrio.
A seguir, apresentam-se alguns casos tpicos de remoo em rvores 2-3 (figuras 7 e 8):

Figura 7 Remoo de uma chave interna: o n trocado com o sucessor na folha, e da a chave no 3-n
facilmente eliminada [2]

7
Figura 8 Remoo de uma chave em folha 2-n: sendo o pai um 3-n, bastou descer uma das chaves e
reajustar a estrutura para sua forma correta [2]

Em casos extremos, os ajustes podem chegar at a raiz, sendo possvel que sua chave seja
eliminada ou realocada. Neste caso, a raiz passa a ser seu nico filho restante. Assim como
no crescimento, a diminuio da altura da rvore tambm ocorre pela raiz. Veremos um
exemplo na figura 9 (prxima pgina).
Mais uma vez, conclumos que, assim como na insero, o pior caso nos leva a sucessivos
ajustes de complexidade temporal O(1) at se chegar raiz. Como, neste caso, estes ajustes
esto diretamente relacionados altura da rvore, temos que tambm a remoo tem
complexidade O(log n).

8
Figura 9 Aqui a remoo e os ajustes levaram realocao da chave original da raiz e um esvaziamento do
n correspondente. Neste caso, o n simplesmente eliminado, baixando a altura da rvore [2].

5. Conceitos relacionados

5.1. Vantagens e desvantagens


Dado tudo o que foi visto neste relatrio, podemos listar como vantagens da rvore 2-3 o seu
balanceamento perfeito (que otimiza a busca) e complexidade temporal de crescimento
logartmico em todas as operaes bsicas.
J a grande desvantagem deste tipo de estrutura a dificuldade maior de implementao em
relao a rvores binrias.

5.2. rvores 2-3-4 e Rubro-Negras


Uma rvore 2-3-4, tambm chamada de rvore 2-4, uma estrutura de dados bastante similar
rvore 2-3. A nica diferena a presena dos 4-ns (ns com 3 chaves e 4 filhos) como
estruturas vlidas, sendo as demais propriedades como o balanceamento perfeito e as
complexidades logartmicas (neste caso, uma altura de crescimento mais lento) sendo
mantidas.
Existe uma equivalncia entre a rvore 2-3-4 e a rvore rubro-negra correspondente
associao os ns da 2-3-4 e o esquema de cores da Rubro-negra. Uma propriedade essencial
da rvore rubro-negra, conforme visto em aula, a altura preta (quantidade de ns pretos at
um ponteiro nulo) igual para todos os ns da rvore, sugerindo um balanceamento pleno entre
os ns de mesmo nvel. A converso se d por uma fuso de ns pretos e seus filhos
vermelhos: um 2-n se converte em um n preto com filhos pretos; um 3-n se relaciona com
um n preto com 1 filho vermelho; um 4-n equivalente a um n preto com ambos os filhos
vermelhos.

9
Figura 10 Transformando um n de rvore 2-3-4 em rvore rubro-negra [3]

5.2. rvores B
As rvores B so rvores multidimensionais que so largamente utilizadas com manipulaes
de memria secundria, pois representam uma diviso de ns bem menor que as rvores
binrias. Podem aceitar um nmero mximo (definido previamente) de chaves em um mesmo
n. So ordenadas e possuem complexidade logartmica de busca e insero/remoo,
podendo ter alturas muito menores que uma rvore binria correspondente. Como tambm
so rvores cujas folhas esto no mesmo nvel, pode-se afirmar que a rvore 2-3 nada mais
que o caso mnimo de uma rvore B.

6. Estudo prtico
O objetivo desta seo verificar, na prtica, o desempenho real de gasto de tempo e sua
evoluo conforme o nmero de chaves registradas das operaes de busca e insero para a
rvore 2-3 em comparao com os dois tipos de rvore binria vistos nesta disciplina: AVL e
Rubro-Negra. Queremos ir alm da verificao terica e verificar as discrepncias que podem
ocorrer devido aos percalos de nvel computacional referentes execuo dos mtodos
inerentes a estas estruturas.
Os algoritmos desenvolvidos para as rvores AVL e Rubro-Negra so baseados nos
contedos dos slides da disciplina, j o da rvore 2-3 se baseou em parte nas referncias

10
consultadas, j que nenhuma delas apresentou um pseudocdigo que pudesse auxiliar com
maior clareza em como programar esta estrutura de dados.
Todos os cdigos, listados integralmente no apndice, foram desenvolvidos em linguagem
Java e foram compilados atravs da plataforma BlueJ. A execuo foi realizada no sistema
operacional Windows 7 numa mquina de processador Intel Core i3 2350M e 4GB de
memria RAM. Todas as chaves utilizadas foram nmeros inteiros.
Para ambas as operaes, exibida uma mdia de 10 repeties de cada algoritmo para cada
tamanho de rvore, sendo as tabelas geradas diretamente pelo programa testador. Observa-se
que o teste avalia com mais preciso o caso mdio.

6.1. Insero
Testaram-se os algoritmos de insero procedendo de trs maneiras: inserindo em ordem
crescente, em ziguezague, e em ordem aleatria, de forma a testar o comportamento e a
influncia dos ajustes de balanceamento no tempo de execuo.

Ordem crescente - tempos medios (ms):


-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 1064,50 | 71,20 | 99,10 |
| 512 | 2829,10 | 112,80 | 260,40 |
| 1024 | 14163,60 | 348,10 | 507,60 |
| 2048 | 51291,60 | 428,20 | 513,70 |
| 4096 | 205425,80 | 954,30 | 4042,60 |
| 8192 | 869156,90 | 2421,40 | 9944,90 |
| 16384 | 3679234,00 | 5685,90 | 4824,30 |
| 32768 | 14477564,00 | 12968,10 | 11983,50 |
| 65536 | 63831685,40 | 31565,00 | 25894,30 |
-----------------------------------------------------------------
Tabela 1 Tempos para a insero de chaves em ordem crescente

7000000

700000
Tempo (ms)

AVL
70000
ARN
A23
7000

700

70
255 1275 6375 31875
Nmero de chaves
Grfico 1 Tempos para a insero de chaves em ordem crescente

11
Ordem zigue-zague - tempos medios (ms):
-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 1042,00 | 57,30 | 71,00 |
| 512 | 4162,50 | 113,00 | 133,60 |
| 1024 | 16793,90 | 296,40 | 311,10 |
| 2048 | 69681,50 | 596,90 | 632,70 |
| 4096 | 296692,30 | 1189,20 | 1120,90 |
| 8192 | 1377430,50 | 2493,80 | 2904,60 |
| 16384 | 5593573,90 | 5876,60 | 7926,20 |
| 32768 | 25509617,80 | 13019,10 | 12607,00 |
| 65536 |121620091,90 | 34864,00 | 29651,60 |
-----------------------------------------------------------------
Tabela 2 Tempos para a insero de chaves em ziguezague

50000000

5000000

500000
Tempo (ms)

AVL
50000
ARN

5000 A23

500

50
255 1275 6375 31875
Nmero de chaves
Grfico 2 Tempos para a insero de chaves em ziguezague

Ordem aleatoria - tempos medios (ms):


-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 962,50 | 52,80 | 66,50 |
| 512 | 3417,40 | 119,40 | 218,00 |
| 1024 | 19708,10 | 323,80 | 383,50 |
| 2048 | 82322,60 | 587,80 | 784,80 |
| 4096 | 338438,10 | 1046,40 | 1520,30 |
| 8192 | 1845195,00 | 2765,90 | 4051,70 |
| 16384 | 8822440,40 | 6174,40 | 9780,60 |
| 32768 | 40208148,90 | 14587,80 | 21926,80 |
| 65536 | 80054915,60 | 44393,60 | 44462,40 |
-----------------------------------------------------------------
Tabela 3 Tempos para a insero de chaves em ordem aleatria

12
50000000

5000000

500000
Tempo (ms)

AVL
50000
ARN

5000 A23

500

50
255 1275 6375 31875
Nmero de chaves
Grfico 3 Tempos para a insero de chaves em ordem aleatria

Observou-se, nos trs casos, que a requisio por vrios ajustes de balanceamento como
sucessivas rotaes e atualizao de dados de balanceamento individuais dos ns
comprometeu muito a velocidade das inseres na rvore AVL, fazendo desta uma boa
rvore para busca, mas pssima para manipulao de dados que alterem a estrutura da rvore.
J as rvores rubro-negra e 2-3 demonstraram certa aproximao, com alguma irregularidade
quanto rvore 2-3. A diferena entre as duas s ficou mais clara na insero em ordem
aleatria, quando se revelou maior eficincia da rvore rubro-negra, provavelmente devido
aos mais frequentes remanejamentos de estruturas internas como os 4-ns temporrios.

6.2. Busca
Para a busca, novamente trs testes foram realizados. A busca foi realizada de forma
crescente para rvores formadas atravs das formas de insero listadas anteriormente: ordem
crescente, em ziguezague e aleatoriamente. O objetivo verificar possveis diferenas de
rendimento devido s diferenas de altura.

13
Ordem crescente - tempos medios (ms):
-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 113,40 | 147,20 | 121,30 |
| 512 | 177,10 | 188,90 | 179,50 |
| 1024 | 223,10 | 233,60 | 297,50 |
| 2048 | 473,00 | 484,70 | 498,30 |
| 4096 | 1055,00 | 1013,80 | 635,80 |
| 8192 | 1941,30 | 1288,80 | 1237,80 |
| 16384 | 2478,20 | 2160,30 | 1926,70 |
| 32768 | 5074,50 | 5283,10 | 4961,10 |
| 65536 | 11293,30 | 10540,70 | 10530,00 |
-----------------------------------------------------------------
Tabela 4 Tempos para a busca de chaves em ordem crescente

10000
Tempo (ms)

AVL
1000 ARN
A23

100
255 1275 6375 31875
Nmero de chaves
Grfico 4 Tempos para a busca de chaves em ordem crescente

14
Ordem zigue-zague - tempos medios (ms):
-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 15,00 | 18,00 | 17,10 |
| 512 | 54,80 | 53,60 | 41,70 |
| 1024 | 120,80 | 117,10 | 104,50 |
| 2048 | 272,50 | 271,00 | 277,40 |
| 4096 | 566,70 | 515,40 | 469,10 |
| 8192 | 1234,30 | 1158,00 | 1129,00 |
| 16384 | 2374,70 | 2321,20 | 2208,40 |
| 32768 | 5233,40 | 5173,60 | 5102,60 |
| 65536 | 11202,20 | 10985,50 | 10627,70 |
-----------------------------------------------------------------
Tabela 5 Tempos para a busca de chaves em ziguezague

10000

1000
Tempo (ms)

AVL

ARN

100 A23

10
255 1275 6375 31875
Nmero de chaves
Grfico 5 Tempos para a busca de chaves em ziguezague

15
Ordem aleatoria - tempos medios (ms):
-----------------------------------------------------------------
| Qtd. | AVL | ARN | A23 |
-----------------------------------------------------------------
| 256 | 15,50 | 18,50 | 20,70 |
| 512 | 50,90 | 53,50 | 50,10 |
| 1024 | 108,40 | 104,40 | 91,80 |
| 2048 | 242,70 | 242,70 | 246,40 |
| 4096 | 527,80 | 527,70 | 551,30 |
| 8192 | 1217,30 | 1020,50 | 898,30 |
| 16384 | 2453,30 | 2224,30 | 2387,40 |
| 32768 | 5504,20 | 5080,10 | 4948,40 |
| 65536 | 10713,50 | 10827,50 | 10711,80 |
-----------------------------------------------------------------
Tabela 6 Tempos para a busca de chaves em ordem aleatria

10000

1000
Tempo (ms)

AVL

ARN

100 A23

10
255 1275 6375 31875
Nmero de chaves
Tabela 6 Tempos para a busca de chaves em ordem aleatria

Observou-se, nos trs casos, que a evoluo dos tempos para as trs rvores segue muito
prxima, mas para quantidades maiores verifica-se que a rvore 2-3 apresenta desempenho
ligeiramente melhor, sugerindo que a altura menor e o balanceamento ideal deixam a rvore
2-3 como uma melhor opo para busca em grandes arranjos de dados.

De forma mais geral, podemos concluir que a rvore 2-3 , quando bem implementada, uma
boa alternativa de estrutura de dados, com bom comportamento mdio tanto para busca
quanto para insero ou remoo de dados, com desempenho comparvel rvore rubro-
negra nestes atributos e muito superior rvore AVL no contexto de alterao da estrutura.

16
Apndice
Abaixo so listados todos os cdigos utilizados para a execuo do estudo prtico.

A1. rvores AVL e Rubro-Negra


/** Cores.java
* Cores utilizadas para a implementao da rvore rubro-negra
*/
public enum Cor { SEM_COR, VERMELHO, PRETO }
Cdigo A1.1 Cores.java

/** Node.java
* A classe Node implementa um n de rvore binria.
* Contm atributos e mtodos bsicos de rvore binria de busca,
* bem como funes e atributos que podem ser explorados pelas
implementaes
* de rvores AVL e Rubro-Negra.
*/

public class Node


{
// Geral
private int key;
public Node[] filho = new Node[2];
public Node pai;

// Especficos ARN
Cor cor = Cor.SEM_COR;
private boolean isNIL = false;

//Especficos AVL
private int altura;

/** Construtores */

// Construtor genrico
public Node()
{
filho[0] = filho[1] = pai = null;
altura = 0;
}

// Construtor que atribui chave


public Node(int chave)
{
this();
setChave(chave);
}

// Construtor para NIL (se n = true)


public Node (boolean n)
{
this();
isNIL = n;
if (n) filho[0] = filho[1] = this;
}

17
/** Mtodos gerais */

// Modifica a chave
public void setChave(int chave)
{ key = chave; }

// Obtm a chave
public int chave()
{ return key; }

/** Mtodos ARN */

// Retorna se o n NIL
public boolean NIL()
{ return isNIL; }

/** Mtodos AVL */

// Calcula o balanceamento do n
public int balanceamento()
{ return (filho[1] != null ? filho[1].altura + 1 : 0) - (filho[0] !=
null ? filho[0].altura + 1 : 0); }

// Atualiza altura do n
public void atualizaAltura()
{
int ae = 0, ad = 0;
if (filho[0] != null)
{
filho[0].atualizaAltura();
ae = filho[0].altura;
}
if (filho[1] != null)
{
filho[1].atualizaAltura();
ad = filho[1].altura;
}
altura = (ae > ad ? ae : ad);
if (filho[0] != null || filho[1] != null) ++altura;
}
}
Cdigo A1.2 Node.java

18
/** ARN.java
* Implementa os mtodos correspondentes a busca e insero
* na rvore AVL, bem como rotinas auxiliares
*/

public class AVL


{
Node raiz;

/** Inicializa a rvore AVL */


public AVL()
{ raiz = null; }

/** Busca (retorna n com a chave procurada, ou null se no existir) */


public Node busca(int k)
{
Node x = raiz;
while (x != null && k != x.chave())
x = x.filho[(k < x.chave() ? 0 : 1)];
return x;
}

// Executa o processo de rotao, usado nas inseres e remoes


// esq define o sentido de rotao (true = esquerda)
private void rotacao(Node x, boolean esq)
{
Node y = x.filho[(esq ? 1 : 0)];
x.filho[(esq ? 1 : 0)] = y.filho[(esq ? 0 : 1)];
if (y.filho[(esq ? 0 : 1)] != null)
y.filho[(esq ? 0 : 1)].pai = x;
y.pai = x.pai;
if (x.pai == null) raiz = y;
else if (x == x.pai.filho[(esq ? 0 : 1)])
x.pai.filho[(esq ? 0 : 1)] = y;
else x.pai.filho[(esq ? 1 : 0)] = y;
y.filho[(esq ? 0 : 1)] = x;
x.pai = y;
}

/** Cria um novo n com a nova chave e o insere na rvore */


public void insercao(int k)
{
Node z = new Node(k);
Node x = raiz;
Node y = null;
while (x != null)
{
y = x;
x = x.filho[(z.chave() < x.chave() ? 0 : 1)];
}
z.pai = y;
if (y == null) raiz = z;
else y.filho[(z.chave() < y.chave() ? 0 : 1)] = z;
balanceia(z);
}

// Faz o balanceamento da rvore em torno do n n (usado nas inseres


e remoes)
private void balanceia(Node n)
{
Node x = n;

19
while (x != null)
{
consertaBalanco(x);
x = x.pai;
}
}

// Corrige a falha de balanceamento para manter as propriedades da


rvore AVL
private void consertaBalanco(Node p)
{
p.atualizaAltura();
if (p.balanceamento() == 2)
{
if (p.filho[1] != null && p.filho[1].balanceamento() < 0)
rotacao (p.filho[1], false);
rotacao (p, true);
}
else if (p.balanceamento() == -2)
{
if (p.filho[0] != null && p.filho[0].balanceamento() > 0)
rotacao (p.filho[0], true);
rotacao (p, false);
}
}
}
Cdigo A1.3 AVL.java

20
/** ARN.java
* Implementa os mtodos correspondentes a busca e insero
* na rvore rubro-negra, bem como rotinas auxiliares
*/

public class ARN


{
public Node raiz; // raiz
private Node nil; // n sentinela NIL

/** Inicializa a rvore rubro-negra com sua raiz e o n sentinela nil


*/
public ARN()
{
nil = new Node(true);
raiz = nil;
}

/** Busca (retorna n com a chave procurada, ou nil se no existir) */


public Node busca(int k)
{
Node x = raiz;
while (!x.NIL() && k != x.chave())
x = x.filho[(k < x.chave() ? 0 : 1)];
return x;
}

// Executa o processo de rotao, usado nas inseres e remoes


// esq define o sentido de rotao (true = esquerda)
private void rotacao(Node x, boolean esq)
{
Node y = x.filho[(esq ? 1 : 0)];
x.filho[(esq ? 1 : 0)] = y.filho[(esq ? 0 : 1)];
if (!y.filho[(esq ? 0 : 1)].NIL())
y.filho[(esq ? 0 : 1)].pai = x;
y.pai = x.pai;
if (x.pai.NIL()) raiz = y;
else if (x == x.pai.filho[(esq ? 0 : 1)])
x.pai.filho[(esq ? 0 : 1)] = y;
else x.pai.filho[(esq ? 1 : 0)] = y;
y.filho[(esq ? 0 : 1)] = x;
x.pai = y;
}

/** Cria um novo n com a nova chave e o insere na rvore */


public void insercao(int k)
{
Node z = new Node(k);
Node y = nil;
Node x = raiz;
while (!x.NIL())
{
y = x;
x = x.filho[(z.chave() < x.chave() ? 0 : 1)];
}
z.pai = y;
if (y.NIL()) raiz = z;
else y.filho[(z.chave() < y.chave() ? 0 : 1)] = z;
z.filho[0] = z.filho[1] = nil;
z.cor = Cor.VERMELHO;
consertaInsercao(z);

21
}

// Mantm as propriedades da rvore rubro-negra aps a insero


private void consertaInsercao(Node z)
{
while (z.pai.cor == Cor.VERMELHO)
{
boolean lado = z.pai == z.pai.pai.filho[0];
Node y = z.pai.pai.filho[(lado ? 1 : 0)];
if (y.cor == Cor.VERMELHO)
{
z.pai.cor = Cor.PRETO;
y.cor = Cor.PRETO;
z.pai.pai.cor = Cor.VERMELHO;
z = z.pai.pai;
}
else
{
if (z == z.pai.filho[(lado ? 1 : 0)])
{
z = z.pai;
rotacao (z, lado);
}
z.pai.cor = Cor.PRETO;
z.pai.pai.cor = Cor.VERMELHO;
rotacao (z.pai.pai, !lado);
}
}
raiz.cor = Cor.PRETO;
}
}
Cdigo A1.4 ARN.java

22
A2. rvores 2-3

/** ADTNo.java
* Implementao de um n de rvore 2-3
* e respectivos mtodos
*/

public class ADTNo


{
public int numChaves; // nmero de chaves
public int[] chave = new int[2]; // chaves
public ADTNo[] filho = new ADTNo[3]; // 0 = esq, 1 = meio (dir, se 2-
no), 2 = dir (se 3-no)
public ADTNo pai;
public No4 p = null; // pai temporrio 4-n

/** Construtores */

// Construtor genrico
public ADTNo()
{ filho[0] = filho[1] = filho[2] = pai = null; }

// Construtor de 2-n
public ADTNo(int ch)
{
this();
chave[0] = ch;
numChaves = 1;
}

// Construtor de 3-n
public ADTNo(int ch1, int ch2)
{
this();
chave[0] = ch1;
chave[1] = ch2;
numChaves = 2;
}

// Verifica se o n uma folha.


// Basta ver, devido ao balanceamento, se o primeiro filho existe ou
no
public boolean folha()
{ return this.filho[0] == null; }
}
Cdigo A2.1 ADTNo.java

23
/** No4.java
* Aqui est implementado o 4-n utilizado para etapas
* intermedirias do algoritmo de insero em rvores 2-3
*/

public class No4


{
public ADTNo[] filho = new ADTNo[4];
public ADTNo pai;
public int[] chave = new int[3];

// Construtor genrico
public No4()
{ filho[0] = filho[1] = filho[2] = filho[3] = pai = null; }

// Construtor com as 3 chaves


public No4(int k1, int k2, int k3)
{
this();
chave[0] = k1;
chave[1] = k2;
chave[2] = k3;
}

// Verifica se folha, da mesma forma que o ADTNo


public boolean folha()
{ return this.filho[0] == null; }
}
Cdigo A2.2 No4.java

/** ADT.java
* Implementa os mtodos correspondentes a busca e insero
* na rvore 2-3, bem como rotinas auxiliares
*/

public class ADT


{
ADTNo raiz;

// Construtor
public ADT()
{ raiz = null; }

/** Realiza a busca, conforme pseudocdigo do relatrio */


public ADTNo busca(int k)
{
ADTNo x = raiz;
while (x != null && k != x.chave[0] && (x.numChaves == 1 ||
(x.numChaves == 2 && k != x.chave[1])))
{
if (k < x.chave[0]) x = x.filho[0];
else if (x.numChaves == 2 && k > x.chave[1])
x = x.filho[2];
else x = x.filho[1];
}
return x;
}

/** Mtodo de insero */

24
public void insercao(int k)
{
ADTNo z = new ADTNo(k); // cria um n z com a nova chave
ADTNo x = raiz;
if (x == null) raiz = z; // se a rvore vazia, z a raiz
else // caso contrrio, busca o local da insero
{
while (!x.folha())
{
if (k < x.chave[0]) x = x.filho[0];
else if (x.numChaves == 2 && k > x.chave[1]) x =
x.filho[2];
else x = x.filho[1];
}
// Uma vez que achou a folha, insere utilizando
// algoritmos especficos para cada caso
if (x.numChaves == 1) insereNo2(z, x);
else insereNo3(z, x);
}
}

/* Implementa a quebra do 4-n temporrio, retorna o n pai resultante


*/
private ADTNo quebraNo(No4 no)
{
// Cria os trs ns resultantes
ADTNo a = new ADTNo(no.chave[0]);
ADTNo b = new ADTNo(no.chave[1]); // chave central (a que deve
subir)
ADTNo c = new ADTNo(no.chave[2]);
// atribui ponteiros pai e filho para os ns recm-criados
// (b o pai; a e c so seus filhos)
b.pai = no.pai; // o n pai resultante tem como pai o pai do 4-n
a.pai = c.pai = b;
b.filho[0] = a;
b.filho[1] = c;
// Associa os filhos do 4-n aos filhos novos
for (int i = 0; i < 2; ++i)
{
a.filho[i] = no.filho[i];
c.filho[i] = no.filho[i + 2];
// Se o n interno, necessrio arrumar o pai
// dos ns que esto abaixo
if (!no.folha())
{
a.filho[i].pai = a;
c.filho[i].pai = c;
}
}
return b;
}

/* Faz a insero da chave do 2-n x no 2-n y;


* tambm insere em y os filhos de x.
S chamado quando se sabe que o n y tem apenas 1 chave */
private void insereNo2(ADTNo x, ADTNo y)
{
// se a chave em x menor...
if (x.chave[0] < y.chave[0])
{
// ... desloca-se o filho direita para o ltimo ponteiro

25
y.filho[2] = y.filho[1];
// traz os filhos de x para y
for (int i = 0; i < 2; ++i)
{
y.filho[i] = x.filho[i];
// caso y no seja folha, arruma os ponteiros para pai
if (!y.folha()) y.filho[i].pai = y;
}
// reordena as chaves
y.chave[1] = y.chave[0];
y.chave[0] = x.chave[0];
}
else // se maior...
{
// a nova chave colocada no lugar vago ( direita)
y.chave[1] = x.chave[0];
// os filhos de x tambm estaro mais direita
for (int i = 2; i >= 1; i--)
{
y.filho[i] = x.filho[i - 1];
if (!y.folha()) y.filho[i].pai = y;
}
}
y.numChaves++; // atualiza o nmero de chaves
}

/* Faz a insero da chave do 2-n x no 3-n y;


* tambm insere em y os filhos de x.
S chamado quando se sabe que o n y tem 2 chaves */
private void insereNo3(ADTNo x, ADTNo y)
{
No4 no; // 4-n temporrio requisitado
// se a chave em x menor que a menor chave de y...
if (x.chave[0] < y.chave[0])
{
// ... o 4-n criado contendo a chave de x esquerda
no = new No4(x.chave[0], y.chave[0], y.chave[1]);
// se os ns envolvidos no so folhas, no h filhos para
atualizar
if (!x.folha() && !y.folha())
{
for (int i = 0; i < 2; ++i)
{
// filhos de x ficam esquerda, os de y direita
no.filho[i] = x.filho[i];
no.filho[i + 2] = y.filho[i + 1];
// atualiza os pais temporrios
x.filho[i].p = y.filho[i + 1].p = no;
}
}
}
else if (x.chave[0] > y.chave[1])
{ // se a nova chave maior que a maior chave...
// ... o 4-n tem a chave nova inserida direita
no = new No4(y.chave[0], y.chave[1], x.chave[0]);
if (!x.folha() && !y.folha())
{
for (int i = 0; i < 2; ++i)
{
// filhos de y desta vez estaro esquerda
no.filho[i] = y.filho[i];

26
no.filho[i + 2] = x.filho[i];
no.filho[i].p = no.filho[i + 2].p = no;
}
}
}
else // caso contrrio, a chave deve entrar no meio
{ // seus filhos ficam entre os filhos
no = new No4(y.chave[0], x.chave[0], y.chave[1]);
if (!x.folha() && !y.folha())
{
no.filho[0] = y.filho[0];
no.filho[3] = y.filho[2];
y.filho[0].p = y.filho[2].p = no;
for (int i = 0; i < 2; ++i)
{
no.filho[i + 1] = x.filho[i];
x.filho[i].p = no;
}
}
}
no.pai = y.pai; // o 4-n recebe o pai do n anterior
ADTNo z = quebraNo(no); // z recebe o pai do n "quebrado"
if (!no.folha()) // se no folha, os pais temporrios dos filhos
so resetados
for (int i = 0; i < 4; ++i) no.filho[i].p = null;
if (z.pai == null) raiz = z; // Se o n no tinha pai, ento z a
raiz
else if (z.pai.numChaves == 1) insereNo2(z, z.pai); // Se o pai
um 2-n, faz a insero
else insereNo3(z, z.pai); // Se o pai um 3-n, faz a insero
}

/** Mostra todas as chaves em ordem crescente */


public void imprimeEmOrdem()
{ imprimeEmOrdem(raiz); }

// Imprime chaves em ordem a partir de um n x inicial


private static void imprimeEmOrdem(ADTNo x)
{
if (x != null)
{
imprimeEmOrdem(x.filho[0]);
System.out.printf ("%d ", x.chave[0]);
imprimeEmOrdem(x.filho[1]);
if (x.numChaves == 2)
{
System.out.printf ("%d ", x.chave[1]);
imprimeEmOrdem(x.filho[2]);
}
}
}
}
Cdigo A2.3 ADT.java

27
A3. Testes
/** Testes.java
* Executa os testes propostos para busca e insero
*/

import java.util.Random;

public class Testes


{
public static final int REPETICOES = 10;

// auxiliar para o embaralhamento


private static void troca(int[] n, int i, int j)
{
int temp = n[i];
n[i] = n[j];
n[j] = temp;
}

// insere os nmeros 1...n no array de tamanho n


private static void encheArray(int[] n)
{ for (int i = 0; i < n.length; ++i) n[i] = i + 1; }

// coloca os nmeros em ordem aleatria


private static void embaralha(int[] n)
{
Random r = new Random();
for (int i = 0; i < n.length; i++)
{
int j = r.nextInt(n.length);
troca(n, i, j);
}
}

/*** INSERO ***/

/** Insero em ordem crescente */


private static void insCrescente(int N)
{
// Inicializao
long t1, t2; // instantes iniciais e finais
AVL avl; // rvores
ARN rbt;
ADT adt;
int[] n = new int[N]; // Vetor de chaves
encheArray(n);
/** Inseres: */
// AVL
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
avl = new AVL();
for (int i = 0; i < n.length; i++)
avl.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tAvl = (double) (t2 - t1) / REPETICOES;
// ARN
t1 = System.nanoTime() / 1000;

28
for (int cont = 0; cont < REPETICOES; ++cont)
{
rbt = new ARN();
for (int i = 0; i < n.length; i++)
rbt.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tArn = (double) (t2 - t1) / REPETICOES;
// A23
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
adt = new ADT();
for (int i = 0; i < n.length; i++)
adt.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tAdt = (double) (t2 - t1) / REPETICOES;
// Tempos:
System.out.printf(" |%12d |%12.2f |%12.2f |%12.2f |\n", N,
tAvl, tArn, tAdt);
}

/** Insero em ordem ziguezague, com estrutura similar ao mtodo


anterior */
private static void insZigZag(int N)
{
// Inicializao
long t1, t2;
int idx;
AVL avl;
ARN rbt;
ADT adt;
int[] n = new int[N];
encheArray(n);
if (N % 2 == 0) idx = N/2 - 1;
else idx = (N - 1)/2;
/** Inseres: */
// AVL
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
avl = new AVL();
for (int i = 0; i <= idx; i++)
{
avl.insercao(n[i]);
avl.insercao(n[N - 1 - i]);
}
if (N % 2 != 0) avl.insercao(n[idx + 1]);
}
t2 = System.nanoTime() / 1000;
double tAvl = (double) (t2 - t1) / REPETICOES;
// ARN
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
rbt = new ARN();
for (int i = 0; i <= idx; i++)
{
rbt.insercao(n[i]);
rbt.insercao(n[N - 1 - i]);

29
}
if (N % 2 != 0) rbt.insercao(n[idx + 1]);
}
t2 = System.nanoTime() / 1000;
double tArn = (double) (t2 - t1) / REPETICOES;
// A23
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
adt = new ADT();
for (int i = 0; i <= idx; i++)
{
adt.insercao(n[i]);
adt.insercao(n[N - 1 - i]);
}
if (N % 2 != 0) adt.insercao(n[idx + 1]);
}
t2 = System.nanoTime() / 1000;
double tAdt = (double) (t2 - t1) / REPETICOES;
System.out.printf(" |%12d |%12.2f |%12.2f |%12.2f |\n", N,
tAvl, tArn, tAdt);
}

/** Insero em ordem aleatria */


private static void insAleatorio(int N)
{
// Inicializao
long t1, t2;
AVL avl;
ARN rbt;
ADT adt;
int[] n = new int[N];
encheArray(n);
embaralha(n);
/** Inseres: */
// AVL
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
avl = new AVL();
for (int i = 0; i < n.length; i++)
avl.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tAvl = (double) (t2 - t1) / REPETICOES;
// ARN
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
rbt = new ARN();
for (int i = 0; i < n.length; i++)
rbt.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tArn = (double) (t2 - t1) / REPETICOES;
// A23
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
{
adt = new ADT();
for (int i = 0; i < n.length; i++)

30
adt.insercao(n[i]);
}
t2 = System.nanoTime() / 1000;
double tAdt = (double) (t2 - t1) / REPETICOES;
System.out.printf(" |%12d |%12.2f |%12.2f |%12.2f |\n", N,
tAvl, tArn, tAdt);
}

/** Testa os mtodos de insero para as trs rvores */


public static void testaInsercao()
{
// o nmero de elementos aumenta em PG iniciada em 256 com razo 2
int n = 256;
int mult = 8; // total de 9 tamanhos diferentes
System.out.println("\n ****** INSERCOES ******\n");

System.out.println(" Ordem crescente - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
insCrescente((int)Math.pow(2, i) * n);
linhaTab();
System.out.println();

System.out.println(" Ordem zigue-zague - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
insZigZag((int)Math.pow(2, i) * n);
linhaTab();
System.out.println();

System.out.println(" Ordem aleatoria - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
insAleatorio((int)Math.pow(2, i) * n);
linhaTab();
System.out.println();
}

/** Algoritmo principal de busca, seguindo o mesmo princpio para


* buscar nas trs diferentes rvores
*/
private static void buscaTeste(AVL avl, ARN rbt, ADT adt, int N)
{
// Inicializao
long t1, t2;
ADTNo a; // ns para receber o valor buscado, no so usados depois
Node b;
int[] n = new int[N];
encheArray(n);
/** Buscas */
// AVL
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
for (int i = 0; i < n.length; ++i)
b = avl.busca(n[i]);
t2 = System.nanoTime() / 1000;
double tAvl = (double) (t2 - t1) / REPETICOES;
// ARN
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
for (int i = 0; i < n.length; ++i)

31
b = rbt.busca(n[i]);
t2 = System.nanoTime() / 1000;
double tArn = (double) (t2 - t1) / REPETICOES;
// A23
t1 = System.nanoTime() / 1000;
for (int cont = 0; cont < REPETICOES; ++cont)
for (int i = 0; i < n.length; ++i)
a = adt.busca(n[i]);
t2 = System.nanoTime() / 1000;
double tAdt = (double) (t2 - t1) / REPETICOES;
System.out.printf(" |%11d |%11.2f |%11.2f |%11.2f |\n",
N, tAvl, tArn, tAdt);
}

/** Teste final para a busca


* Primeiro insere as chaves nas trs rvores pelas trs ordens
* (crescente, ziguezague e aleatria) para os 9 tamanhos a serem
testados.
* Depois, faz a busca no nmero de repeties sugerido.
*/
public static void testaBusca()
{
int N = 256;
int mult = 8;
AVL[] avlC, avlZ, avlA;
ARN[] rbtC, rbtZ, rbtA;
ADT[] adtC, adtZ, adtA;
avlC = avlZ = avlA = new AVL[mult + 1];
rbtC = rbtZ = rbtA = new ARN[mult + 1];
adtC = adtZ = adtA = new ADT[mult + 1];
inicializaAVL(avlC); inicializaAVL(avlZ); inicializaAVL(avlA);
inicializaARN(rbtC); inicializaARN(rbtZ); inicializaARN(rbtA);
inicializaADT(adtC); inicializaADT(adtZ); inicializaADT(adtA);

//Inseres
long soma = 0;
for (int v = 0; v <= mult; v++)
{
int[] n = new int[(int)Math.pow(2, v) * N];
encheArray(n);
int[] m = n;
embaralha(m);
for (int i = 0; i < n.length; i++)
{
// Ordem crescente
avlC[v].insercao(n[i]);
rbtC[v].insercao(n[i]);
adtC[v].insercao(n[i]);
// Aleatoriamente
avlA[v].insercao(m[i]);
rbtA[v].insercao(m[i]);
adtA[v].insercao(m[i]);
}
for (int i = 0; i < N/2; i++)
{
// Ziguezague
avlZ[v].insercao(n[i]);
avlZ[v].insercao(n[n.length - i - 1]);
rbtZ[v].insercao(n[i]);
rbtZ[v].insercao(n[n.length - i - 1]);

32
adtZ[v].insercao(n[i]);
adtZ[v].insercao(n[n.length - i - 1]);
}
}

/** Buscas */
System.out.println("\n ****** BUSCAS ******\n");

System.out.println(" Ordem crescente - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
buscaTeste(avlC[i], rbtC[i], adtC[i], (int)Math.pow(2, i) * N);
linhaTab();
System.out.println();

System.out.println(" Ordem zigue-zague - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
buscaTeste(avlZ[i], rbtZ[i], adtZ[i], (int)Math.pow(2, i) * N);
linhaTab();
System.out.println();

System.out.println(" Ordem aleatoria - tempos medios (ms):");


cabecalho();
for (int i = 0; i <= mult; i++)
buscaTeste(avlA[i], rbtA[i], adtA[i], (int)Math.pow(2, i) * N);
linhaTab();
System.out.println();
}

// Auxilia na apresentao em formato de tabela


private static void linhaTab()
{ System.out.println(" ------------------------------------------------
-----------------"); }

// Cabealho das tabelas


private static void cabecalho()
{
linhaTab();
System.out.println(" | Qtd. | AVL | ARN
| A23 |");
linhaTab();
}

// Inicializao da AVL
private static void inicializaAVL(AVL[] a)
{
for (int i = 0; i < a.length; i++)
a[i] = new AVL();
}

// Inicializao da Rubro-negra
private static void inicializaARN(ARN[] a)
{
for (int i = 0; i < a.length; i++)
a[i] = new ARN();
}

// Inicializao da rvore 2-3


private static void inicializaADT(ADT[] a)
{

33
for (int i = 0; i < a.length; i++)
a[i] = new ADT();
}

/** Mtodo main: chama os testes implementados */


public static void main(String[] args)
{
testaBusca();
testaInsercao();
}
}
Cdigo A3 Testes.java

34
Referncias

[1] Balanced Search Tree Disponvel em http://algs4.cs.princeton.edu/33balanced/


Acessado em 16/11/2016 s 19:00.

[2] 2-3 Trees Disponvel em


http://ee.usc.edu/~redekopp/cs104/slides/L19_BalancedBST_23.pdf. Acessado em
15/11/2016 s 17:09

[3] 2-3 Tree, 2-3-4 Tree & Red-black tree Disponvel em


http://www2.thu.edu.tw/~emtools/Adv.%20Data%20Structure/2-3,2-3-4%26red-
blackTree_952.pdf. Acessado em 15/11/2016 s 16:30.

[4] 2-3 Trees: Inserting and Deleting Disponvel em


http://www-bcf.usc.edu/~dkempe/CS104/11-14.pdf. Acessado em 03/12/2016 s 15:39.

[5] 2-3 Trees Disponvel em http://software.ucv.ro/~mburicea/lab9ASD.pdf. Acessado em


14/11/2016 s 18:55

[6] rvores 2-3 Disponvel em


http://www.ime.usp.br/~pf/estruturasdedados/aulas/sttwothree.html. Acessado em 25/11/2016
s 22:41

[7] Drozdek, Adam. Estrutura de dados e algoritmos em C++. So Paulo: Cengage Learning,
2008.

[8] Notas de aula produzidas pelo Prof. Dr. Harlen Costa Batagelo para a disciplina
MCTA002 Algoritmos e Estruturas de Dados II no 3 quadrimestre de 2016

35

Вам также может понравиться