You are on page 1of 28

UNIAN CENTRO UNIVERSITRIO ANHANGUERA DE NITERI

Cincia da Computao 4 Perodo


Classificao e Pesquisa
Prof. Deise Galvo

ATIVIDADES PRTICAS
SUPERVISIONADAS - ETAPA 2

Tayline Queiroz 7228576588


Fernanda Ledig -

Niteri
2015

Relatrio 3 rvores Binrias de Pesquisa

Passo 1
Fazer leitura de material disponibilizado.
Passo 2
Fazer a discusso em equipe e tomar nota dos principais diferenciais entre os
modelos de rvores apresentados nas leituras realizadas, focando na implementao das
rvores no que tange:
Insero de dados em rvores Binrias.

o Procure um local para inserir o novo n, comeando a procura a partir do nraiz;


o Para cada n-raiz de uma sub-rvore, compare; se o novo n possui um valor
menor do que o valor n raiz (vai para sub-rvore esquerda), ou se o valor
maior que o valor no n-raiz (vai para sub-rvore direita);
o Se uma referncia (filho esquerdo/direito de um n raiz) nula atingida, coloque
o novo n como sendo filho do n-raiz.
Exemplo de implementao:
def arvore_binaria_inserir(no, chave, valor):
if no is None:
return TreeNode(None, chave, valor, None)
if chave == no.chave:
return TreeNode(no.filho_esquerdo, chave, valor, no.filho_direito)
if chave < no.chave:
return TreeNode(arvore_binaria_inserir(no.filho_esquerdo, chave, valor),
no.chave, no.valor, no.filho_direito)
else:
return TreeNode(no.filho_esquerdo, no.chave, no.valor,
arvore_binaria_inserir(no.filho_direito, chave, valor))
}
}
}

Pesquisa de dados em rvores Binrias.


o Comece a busca a partir do n-raiz;
o Para cada n-raiz de uma sub-rvore compare: Se o valor procurado menor que
o valor no n-raiz (continua pela sub-rvore esquerda), ou se o valor maior que
o valor no n-raiz (sub-rvore direita); caso o n contendo o valor pesquisado
seja encontrado, retorne o n; caso contrrio retorne nulo.
Exemplos de Implementao:
# 'no' refere-se ao n-pai, neste caso
def arvore_binaria_buscar(no, valor):
if no is None:
# valor no encontrado
return None
else:
if valor == no.valor:
# valor encontrado
return no.valor
elif valor < no.valor:
# busca na subrvore esquerda
return arvore_binaria_buscar(no.filho_esquerdo, valor)
elif valor > no.valor:
# busca na subrvore direita
return arvore_binaria_buscar(no.filho_direito, valor)

Ordenao de dados em rvores Binrias.


Vrias operaes podem ser feitas usando rvores binrias de busca. Podemos
citar, por exemplo, algoritmos de ordenao. O HeapSort um desses algoritmos que
usam uma rvore para fazer a ordenao de uma lista de valores. No entanto, ao invs
de usar uma rvore binria de busca, o algoritmo usa um tipo de rvore chamada Heap,
onde a ordem dos elementos diferente. Usando uma rvore binria de busca, temos um
cdigo de ordenao um pouco melhor, j que a ordenao feita na medida que os
objetos entram na rvore. No entanto, devido essa necessidade de se adicionar o item
ordenadamente cada insero, essa estrutura acaba no sendo a melhor escolha para

ordenao. Aqui, temos um exemplo de como usaramos a rvore para ordenar. Veja o
exemplo:
Exemplo de implementao:
//todosnaonulos
def organiza(valores):
_arvore = None
if valores is not None:
_arvore = []
for _v in valores:
insere(_arvore, _v)
_res = []
percorre(_arvore, lambda valor: _res.append(valor))
return _res
Remoo de dados em rvores Binrias.
Para a remoo de um n em uma rvore binria, devem ser considerados trs
casos:
Caso 1: o n folha O n pode ser retirado sem problema;
Caso 2: o n possui uma sub-rvore (esq./dir.) O n-raiz da sub-rvore (esq./dir.)
ocupa o lugar do n retirado;
Caso 3: o n possui duas sub-rvores O n contendo o menor valor da sub-rvore direita
pode ocupar o lugar; ou o maior valor da sub-rvore esquerda pode ocupar o lugar
Exemplo de implementao
def exclusao_em_arvore_binaria(n_arvore, valor):
if n_arvore is None: return None # Valor no encontrado
esquerda, n_valor, direita = n_arvore.esquerda, n_arvore.valor, n_arvore.direita

if n_valor == valor:
if esquerda is None:
return direita
elif direita is None:
return esquerda
else:
valor_max, novo_esquerda = busca_max(esquerda)
return TreeNode(novo_esquerda, valor_max, direita)
elif valor < n_valor:
return TreeNode(exclusao_em_arvore_binaria(esquerda, valor), n_valor, direita)
else:
return TreeNode(esquerda, n_valor, exclusao_em_arvore_binaria(direita, valor))
def busca_max(n_arvore):
esquerda, n_valor, direita = n_arvore.esquerda, n_arvore.valor, n_arvore.direita
if direita is None: return (n_valor, esquerda)
else:
(valor_max, novo_direita) = busca_max(direita)
return (valor_max, (esquerda, n_valor, novo_direita))

Passo 3

Fazer as atividades apresentadas a seguir.


1. Desenvolver como base na estrutura de residncias, uma rvore Binria que
represente a estrutura de residncias considerando:
Ruas e Residncias.
Medidores de Consumo de energia.
2. Implementar uma funo para cada uma das atividades discutidas no passo 2 pela
equipe:
Insero de dados em rvores Binrias.
Pesquisa de dados em rvores Binrias.
Ordenao de dados em rvores Binrias.
Remoo de dados em rvores Binrias.

Cdigo Fonte: rvore Binria de Pesquisa


#include <stdio.h>
#include <stdlib.h>
// Estrutura do N, onde foi utilizado recursividade para os ponteiros da subarvore
esquerda e direita.
typedef struct No{
char rua[30];
char residencia[30];
int medidor;
struct No *esquerda;
struct No *direita;
}No;
// Funo iniciar Arvore que inicializa a arvore binaria com o valor vazio.
void iniciarArvore(No **Raiz){
*Raiz = NULL;
}
/* Funo inserir, onde os valores que sero salvos no N da arvore,caso seja o primeiro
elemento ser salvo como a raiz da arvore. Caso contrrio ser salvo de acordo com a
sua devida posio.
*/
void inserir(No **pRaiz, char r[30], int med, char res[30]){
if(*pRaiz == NULL){
*pRaiz = (No *) malloc(sizeof(No));
(*pRaiz)->esquerda = NULL;
(*pRaiz)->direita = NULL;
strcpy((*pRaiz)->rua, r);
strcpy((*pRaiz)->residencia, res);
(*pRaiz)->medidor = med;
}else{
if(med < (*pRaiz)->medidor)

inserir(&(*pRaiz)->esquerda, r, med, res);


if(med > (*pRaiz)->medidor)
inserir(&(*pRaiz)->direita, r, med, res);
}
}
// Funo remover, onde ser eliminado um nico n por vez na arvore
// e os elementos da sua subarvore esquerda e direita so realocados
No *remover(No *r, int v)
{
if (r == NULL)
return NULL;
else if (r->medidor > v)
r->esquerda = remover(r->esquerda, v);
else if (r->medidor < v)
r->direita = remover(r->direita, v);
else {
if (r->esquerda == NULL && r->direita == NULL) {
free (r);
r = NULL;
}
else if (r->esquerda == NULL) {
No* t = r;
r = r->direita;
free (t);
}}}
// Exibio dos valores seguindo a seguinte ordem:
// Subarvore Esquerda - Raiz - Subarvore Direita
void EmOrdem(No *pRaiz){
if(pRaiz != NULL){
EmOrdem(pRaiz->esquerda);
printf("---------------------------\n");
printf("Medidor.....:%d\n", pRaiz->medidor);

printf("Rua.........:%s\n", pRaiz->rua);
printf("Residencia..:%s\n", pRaiz->residencia);
printf("---------------------------\n");
EmOrdem(pRaiz->direita);
}
}
// Exibio dos valores seguindo a seguinte ordem:
// Raiz - Subarvore Esquerda - Subarvore Direita
void PreOrdem(No *pRaiz){
if(pRaiz != NULL){
printf("---------------------------\n");
printf("Medidor.....:%d\n", pRaiz->medidor);
printf("Rua.........:%s\n", pRaiz->rua);
printf("Residencia..:%s\n", pRaiz->residencia);
printf("---------------------------\n");
PreOrdem(pRaiz->esquerda);
PreOrdem(pRaiz->direita);
}
}
// Exibio dos valores seguindo a seguinte ordem:
// Subarvore Esquerda - Subarvore Direita - Raiz
void PosOrdem(No *pRaiz){
if(pRaiz != NULL){
PosOrdem(pRaiz->esquerda);
PosOrdem(pRaiz->direita);
printf("---------------------------\n");
printf("Medidor.....:%d\n", pRaiz->medidor);
printf("Rua.........:%s\n", pRaiz->rua);
printf("Residencia..:%s\n", pRaiz->residencia);
printf("---------------------------\n");
}
}

// Busca do medidor recebido como parmetro em toda a arvore


No *arvorebusca(No *pRaiz,int med){
while (pRaiz != NULL && pRaiz->medidor != med) {
if (pRaiz->medidor > med)
pRaiz = pRaiz->esquerda;
else
pRaiz = pRaiz->direita;
}
return pRaiz;
}
int main(int argc, char *argv[])
{
char rua[30],res[30];
int op, med, es, busca;
No *arvore;
No *aux;
iniciarArvore(&arvore);
while (op!=5){
printf("---------------------------\n");
printf("| BEM VINDO AO CADASTRO |\n");
printf("|

DE RESIDENCIAS

|\n");

printf("---------------------------\n");
printf("---------------------------\n");
printf("MENU PRINCIPAL

\n");

printf("1- Inserir um novo cadastro\n");


printf("2- Consultar os cadastros \n");
printf("3- Buscar nos cadastros

\n");

printf("4- Remover um cadastro


printf("5- Sair

\n");

printf("---------------------------\n");
scanf("%d",&op);
switch(op){

\n");

case 1:
printf("Digite a rua da residencia: \n");
scanf("%s",&rua);
printf("Digite o numero da residencia: \n");
scanf("%s",&res);
printf("Digite o medidor de consumo: \n");
scanf("%d",&med);
inserir(&arvore, rua, med, res);
break;
case 2:
printf("Escolha a forma de exibio: \n");
printf("1 - Pre-Ordem \n");
printf("2 - Em Ordem \n");
printf("3 - Pos Ordem \n");
scanf("%d",&es);
switch (es){
case 1:
PreOrdem(arvore);
break;
case 2:
EmOrdem(arvore);
break;
case 3:
PosOrdem(arvore);
break;
}
break;
case 3:
printf("Qual valor do medidor de consumo deseja pesquisar? \n");
scanf("%d",&busca);
aux= arvorebusca(arvore, busca);
if(aux->medidor == busca){
printf("O valor foi encontrado \n");
printf("---------------------------\n");

printf("Medidor.....:%d\n", aux->medidor);
printf("Rua.........:%s\n", aux->rua);
printf("Residencia..:%s\n", aux->residencia);
printf("---------------------------\n");
}
else
printf("Valor nao encontrado \n");
break;
case 4:
printf("Qual valor do medidor de consumo deseja remover? \n");
scanf("%d",&busca);
remover(arvore,busca);
break;
}
}
system("PAUSE");
return 0;
}

Imagens e Resultados Obtidos:

Imagem 1: Inserir um novo cadastro, ou seja, insero de um novo n na rvore.

Imagem 2: Exibio da rvore em Pre-Ordem.

Imagem 3: Busca de um medidor de consumo.

ETAPA 4
TEMA NOVO: MergeSort. Tabelas Hash estticas. Tabelas Hash dinmicas.
- Toda a etapa ser transformada em pesquisa terica.
- De cada um dos temas propostos, dever ser pesquisado o funcionamento, principais
caractersticas, principais aplicaes e exemplos de implementao em C.

Mergesort
O mergesort, ou ordenao por mistura, um exemplo de algoritmo de
ordenao do tipo dividir-para-conquistar.
Sua ideia bsica consiste em Dividir (o problema em vrios subproblemas e
resolver esses subproblemas atravs da recursividade) e conquistar (aps todos os
subproblemas terem sido resolvidos ocorre a conquista que a unio das resolues dos
subproblemas). Como o algoritmo do MergeSort usa a recursividade em alguns
problemas esta tcnica no muito eficiente devido ao alto consumo de memria e
tempo de execuo.
Os trs passos teis dos algoritmos dividir-para-conquistar, ou divide and
conquer, que se aplicam ao mergesort so:
Dividir: Dividir os dados em subsequncias pequenas;
Conquistar: Classificar as duas metades recursivamente aplicando o merge sort;
Combinar: Juntar as duas metades em um nico conjunto j classificado.

um algoritmo de ordenao estvel que se preserva a ordem de registros de


chaves iguais. Isto , se tais registros aparecem na sequncia ordenada na mesma ordem
em que esto na sequncia inicial. Esta propriedade til apenas quando h dados
associados s chaves de ordenao.
eficiente para ordenar listas, por exemplo se quisermos ordenar algo mais do
que um vetor? rvores binrias j so todas pr-ordenadas, mas e as listas ligadas? Para
isso, temos o MergeSort que funciona ainda melhor em listas ligadas em comparao
que ele faz em matrizes. Isso evita a necessidade de um espao auxiliar, e se torna um
simples e confivel algoritmo de ordenao. E ainda como bnus, muito estvel.

Resumo das Vantagens e desvantagem do mergesort:


Vantagens:

eficiente para ordenao externa


Fcil implementao
Recomendado para aplicaes com restrio de tempo
Desvantagens:
Utiliza memria auxiliar
Alto consumo de memria

Implementao em C

Exemplo 1 :

void merge (int M[5o], int inicio, int fim)


{
int meio;
comparaes[3]++;
if (inicio < fim)
{
meio = ((inicio + fim)/2);
merge (M, inicio, meio);
merge (M, meio+1, fim);
intercala (M, inicio, meio, fim);
}
}
void intercala (int M[50], int inicio, int fim)
{

int primeiro, res, segundo, k;


int C[]50;
primeiro = res = inicio;
segundo = meio + 1;
while (primeiro <= meio && segundo <= fim)
{
comparacoes[3]++;
if (M[primeiro] <= M[segundo])
{
atribuicoes [3]++;
C[res]= M[primeiro];
primeiro++;
}
else
{
atribuicoes[3]++;
C[res] = M[segundo];
segundo++;
}
res++;
}
comparacoes[3]++;
if (primeiro > meio)

for (k=segundo; k<=meio; k++)


{
atribuicoes[3]++;
C[res] = M[k];
res++;
}
else
for (k=primeiro; k<=meio; k++)
{
atribuicoes[3]++;
C[res] = M[k];
res++;
}
for (k=inicio; k<=fim; k++)
M[k] = C[k];
}
Exemplo 2 :

void merge(int vec[], int vecSize) {


int mid;
int i, j, k;
int* tmp;
tmp = (int*) malloc(vecSize * sizeof(int));

if (tmp == NULL) {
exit(1);
}
mid = vecSize / 2;
i = 0;
j = mid;
k = 0;
while (i < mid && j < vecSize) {
if (vec[i] <= vec[j]) {
tmp[k] = vec[i++];
}
else {
tmp[k] = vec[j++];
}
++k;
}
if (i == mid) {
while (j < vecSize) {
tmp[k++] = vec[j++];
}
}
else {
while (i < mid) {

tmp[k++] = vec[i++];
}
}
for (i = 0; i < vecSize; ++i) {
vec[i] = tmp[i];
}
free(tmp);
}
void mergeSort(int vec[], int vecSize) {
int mid;
if (vecSize > 1) {
mid = vecSize / 2;
mergeSort(vec, mid);
mergeSort(vec + mid, vecSize - mid);
merge(vec, vecSize);
}
}
Tabelas hash esttica
-

Inicialmente definido o nmero de buckets do arquivo, sendo cada um do tamanho


de uma pgina. Os registros so inseridos no bucket determinado pela funo hash.
Se um bucket fica cheio, uma ou mais pginas adicionais podem ser ligadas a ele.
As pginas adicionais so mantidas em uma lista ligada.

A pesquisa a um registro feita aplicando a funo hash ao valor da chave de


pesquisa daquele registro para identificar o bucket onde o registro se encontra. A
localizao do registro desejado feita percorrendo todas as pginas do bucket.

A remoo de um registro feita usando a funo hash para localizar o bucket onde
o registro se encontra. Uma vez localizado, o registro removido de acordo com a
estratgia de remoo sendo adotada.

A principal desvantagem desta estratgia que podem ocorrer longas cadeias de


pginas adicionais nos buckets, o que afetar o desempenho do sistema na medida
que todas as pginas de um bucket precisam ser pesquisadas.

No arquivo mantido por uma funo hash as pginas so mantidas com 80% de
ocupao no momento em que os registros so inicialmente organizados. O objetivo
deixar algum espao para futuras inseres e minimizar pginas adicionais
medida que o nmero de dados no arquivo aumenta.

A organizao dos registros num hashed file pode exigir mais pginas que num heap
file

As consideraes feitas nos ltimos dois itens tornam a varredura em todas as


pginas de um hashed file mais 1.25 % mais lenta que no heap file

Exemplo 1:
Considere uma relao cliente (cod, nome, idade);
Considere que a chave de pesquisa seja idade;
Considere que o hashed file seja divido em 4 buckets e que a funo hash seja
h(idade) = idade mod 4;

Considere que caibam 10 regsitros por pgina.

Para os seguintes registros, quantas pginas sero necessrias no heap file? E no


hashed file?

(001, Joo, 40)


(002, Maria,31)
(003, Cristina, 23)
(004, Ana,33)

Anlise de custo
- Varredura (scan)
Custo =1.25* NP*(TP+TR*NR)
-

Pesquisa por seleo de igualdade: suportada eficientemente se a chave de


pesquisa for a mesma com a que o arquivo foi organizado. Caso contrrio, o todo
arquivo ter que ser percorrido para realizar a pesquisa (scan). Uma vez aplicada
funo hash, um grupo escolhido e a pesquisa realizada somente nas pginas
deste grupo.

Para efeito de anlise de custo, consideraremos que o grupo contenha apenas


uma pgina.
Considere H o custo de calcular h (v)
a)

Pesquisa feita com chave primria


Custo = H+TP+0,5*(NR*TR)

b)

Pesquisa feita com chave secundria

Custo = H+TP+0,5*(NR*TR)

Neste caso vrios registros podem satisfazer a condio.

- Pesquisa com intervalo de seleo: Neste caso a organizao hash no oferece


qualquer vantagem uma vez que todo o arquivo deve ser percorrido.

Custo = 1,25*NP*(TP+TR*NR)

- Insero
O registro ser inserido no final da pgina do grupo definido pela funo hash.

a) Insero sem considerar replicao


(*) custo = H+2*TP+TR

b) Insero considerando replicao


Custo = H+2*TP+NR*TR+TR

- Remoo
Remove a primeira ocorrncia do registro
Custo = H+ TP+0,5*(NR*TR)+TR+TP

Tabelas hash dinmicas

a) Tabela hash extensvel

As principais alteraes feitas com relao tabela hash esttica so:


-

H um nvel de indireo introduzido pelo diretrio de buckets para as pginas que


representam os buckets, ao invs de um array consistindo das prprias pginas;

O diretrio de buckets pode crescer. Seu comprimento sempre potncia de 2;

No exigido que cada bucket esteja associado a apenas uma entrada no diretrio de
buckets, ou seja, vrios buckets podem compartilhar uma mesma entrada no
diretrio de buckets se esta for suficiente para armazenar todos os registros dos
buckets associados;

A funo hash h calcula para cada chave de pesquisa uma sequncia de N bits para
algum valor alto de N., No entanto a identificao dos buckets num determinado
momento pode precisar de um nmero menor de bit, digamos i bits. Neste caso o
dirtrio de buckets ter 2i entradas quando i for o nmero de bits usados para
identificar os buckets

Exemplo:
Considere a seguinte situao: suponha que SEQ=4, ou seja, a funo hash
produz uma sequncia de 4 bits (mximo de 16 buckets) e at o momento apenas 1 bit
est sendo utilizado (foram inseridos os registros 1, 2 e 3 sabendo que h (k 1) = 0001, h
(k2)=1001 e h (k3)=1100, onde kn a chave de pesquisa do registro n):

i=1

j
0001 (reg1)

0
1
j

1001 (reg2)
Diretrio de
de dados)

1
buckets

1100 (reg3)

buckets (pginas

As entradas do diretrio de buckets apontam para dois buckets: o primeiro


mantm todos os registros, at o momento, cujo resultado da aplicao da funo hash
chave de pesquisa comea com 0 e a segunda com 1. O nub que aparece na pgina, na
verdade faz parte do cabealho da pgina e identifica o nmero de bits i necessrios
para identificar a pertinncia dos registros ao bucket . Este nmero pode variar por
pgina medida que o arquivo cresce.

a) insero em uma tabela hash extensvel


Para inserir um registro com chave de pesquisa K, a funo hash h (k)
calculada e os i bits mais significativos da sequncia resultante so reservados. Estes i
bits identificam uma entrada no diretrio de buckets. O registro deve ser inserido na
pgina B apontada por esta entrada, se houver lugar.
Caso no haja lugar neste bucket, duas possibilidades podem ocorrer,
dependendo do nmero de bits necessrios para representar os registros da pgina
escolhida. Seja j o nmero de bits mantido no cabealho da pgina de dados do bucket
em questo:

1.

Se j < i ento (significa que o bucket apontado por mais


de uma entrada no diretrio de buckets):
-

Divide o bloco B em dois

Distribui os registros de B entre estes dois blocos baseando-se no valor do


seu (j+1) simo bit menos significativo da sequncia resultante da aplicao
da funo h, isto , se (j+1) simo bit 0, fica no bloco B seno vai para o
novo bloco;

Altera o bit j da pgina B e da nova pgina para j+1

Ajusta os ponteiros do diretrio de buckets tal que as entradas apontem


corretamente para o bloco B e o novo bloco de acordo com o (j+1) esimo bit.

Note que esta diviso pode no resolver o problema uma vez que todos os
registros podem ter o mesmo (j+1) esimo bit. Neste caso outras divises sero
necessrias.

Se j=i ento (no h mais entradas disponveis no diretrio de buckets apenas uma
entrada aponta para o bucket):
-

Incrementar i de 1, o que aumenta o nmero de entradas do diretrio de buckets


para 2(i+1).

Inserir o registro na pgina correta.

As novas entradas w0 e w1 no diretrio de buckets continuam apontando para os


mesmos buckets que as entradas w apontavam. O contedo dos buckets no se
altera.

Finalmente a insero feita dividindo a pgina como indicado anteriormente,


uma vez que agora j < i.

Exemplo:

Considere o exemplo anterior e uma chave de pesquisa k, onde h (k) = 1010.


A insero deve ocorrer na segunda pgina, mas esta pgina est cheia e precisa ser
partida.
Como i=j, ento i incrementado passando a 2.

i=2

j
0001

00
01
10
11

1001

1100

O registro dever ser inserido na segunda pgina, como agora j<i, ento:

i=2

j
0001

00
01

1001

10

1010

11

1100

Exemplo 2:
Insira agora os registros t e s, cujas funes hash so: h (t) =0000 e h (s) = 0111.
O registro t deve ser colocado no primeiro bucket de acordo com o diretrio de buckets.
O registro s tambm deve ser colocado no primeiro bucket, mas este est cheio. Como
j<i, basta dividir o primeiro bucket:

i=2

0001

0000
2

00
01
10
11

1001

0111
1010

1100

Vantagens:
Apenas uma pgina de dados deve ser buscada para cada registro a ser acessado.
Desvantagens:
1. O crescimento do diretrio de buckets exponencial, o que compromete na
etapa de insero em tempo.
2. O diretrio de buckets pode ficar grande o suficiente que precise ser
armazenado em disco, o que provoca mais acessos de I/O para acessar um registro.

3. O espao para suportar o diretrio de buckets pode ser muito maior do que o
necessrio, quando a ocupao das pginas pequena.

Referncias bibliogrficas
Livro texto:
ZIVIANI, Nivio. Projeto de Algoritmos: com implementao em Pascal e C.. 2 ed.
So Paulo: Pioneira Thomson Learning, 2004.
VELOSO, Paulo A. S. Estrutura de Dados. 1 ed. So Paulo: Campus, 1983.
CORMEN, Thomas H. Algoritmos: teoria e prtica. 1 ed. Rio de Janeiro: CAMPUS,
2002. Complementar SCHILDT, Herbert. C Completo e Total. 3 ed. So Paulo:
Pearson Education, 2005.
CELES, Waldemar; CERQUEIRA, Renato. Introduo a Estruturas de Dados: com
tcnicas de programao em C. 4 ed. Rio de Janeiro: Elsevier, 2004
WIRTH, Niklaus. Algoritmos e Estruturas de Dados. 1 ed. Rio de Janeiro: LTC, 1989
TENENBAUM, Aaron M; SOUZA, Tereza Cristina Flix de. Estruturas de Dados
usando C. 1 ed. So Paulo: Makron Books,1995.
Material Complementar:

BOSCARIOL, LEANDRO A.; GAMEIRO, LUCAS B.; ARRUDA, RODRIGO


L. S. Algoritmos de Ordenao. Disponvel em: <
http://www2.dc.uel.br/~rlarruda/trab/algoritmos-ordenacao.pdf>. Acesso em: 01
de jun. de 2010.

http://pt.wikipedia.org/wiki/%C3%81rvore_bin%C3%A1ria

http://equipe.nce.ufrj.br/adriano/c/apostila/arvore.htm

http://pt.slideshare.net/renatopaschoal/rvores-binrias-balanceadas

https://www.youtube.com/watch?v=MiUDxjVMeow

http://pt.wikibooks.org/wiki/Programar_em_C/%C3%81rvores_bin
%C3%A1rias

http://pt.wikipedia.org/wiki/Tabela_de_dispers%C3%A3o

http://pt.slideshare.net/CriatividadeZeroDocs/aula-sobre-tabela-hash

http://www.dca.fee.unicamp.br/cursos/EA876/apostila/HTML/node26.html

http://pt.wikibooks.org/wiki/Algoritmos_e_Estruturas_de_Dados/Tabela_de_Ha
sh

You might also like