Você está na página 1de 75

Livro Projeto de Algoritmos Nvio Ziviani

Captulo 5
http://www2.dcc.ufmg.br/livros/algoritmos/

Pesquisa em Memria
Primria

Algoritmos e Estrutura de Dados II

 Listas Encadeadas, Endereamento Aberto, Hashing Perfeito

 Trie , Patricia
Transformao de Chave (Hashing)

 Pesquisa Digital

 Transformaes para Manuteno da Propriedade SBB

 rvores SBB

 rvores Binrias de Pesquisa com Balanceamento

 rvores Binrias de Pesquisa sem Balanceamento

 rvores de Pesquisa

 Pesquisa Seqencial

 Introduo - Conceitos Bsicos

Pesquisa em Memria Primria

Algoritmos e Estrutura de Dados II

 Pesquisa com sucesso X Pesquisa sem sucesso.

 Objetivo da pesquisa:Encontrar uma ou mais


ocorrncias de registros com chaves iguais chave de
pesquisa.

 Cada registro possui uma chave para ser usada na


pesquisa.

 A informao dividida em registros.

 Estudo de como recuperar informao a partir de uma


grande massa de informao previamente armazenada.

Introduo - Conceitos Bsicos

Algoritmos e Estrutura de Dados II

 arquivo: tabela de valores de funes.

 tabela: arquivo de ndices

 Distino no rgida:

 Arquivo:geralmente associado a entidades de vida mais


longa, armazenadas em memria externa.

 Tabela:associada a entidades de vida curta, criadas na


memria interna durante a execuo de um programa.

 Conjunto de registros ou arquivos TABELAS

 Tabelas

Introduo - Conceitos Bsicos

Algoritmos e Estrutura de Dados II

 Se contedo do arquivo estvel importante


minimizar o tempo de pesquisa, sem preocupao
com o tempo necessrio para estruturar o arquivo

 Depende principalmente:
1. Quantidade dos dados envolvidos.
2. Arquivo estar sujeito a inseres e retiradas
freqentes.

Escolha do Mtodo de Pesquisa mais


Adequado a uma Determinada Aplicao

Algoritmos e Estrutura de Dados II

 Operaes mais comuns:


1. Inicializar a estrutura de dados.
2. Pesquisar um ou mais registros com determinada chave.
3. Inserir um novo registro.
4. Retirar um registro especfico.
5. Ordenar um arquivo para obter todos os registros em ordem de
acordo com a chave.
6. Ajuntar dois arquivos para formar um arquivo maior.

 importante considerar os algoritmos de pesquisa como tipos


abstratos de dados, com um conjunto de operaes associado a
uma estrutura de dados, de tal forma que haja uma independncia
de implementao para as operaes.

Algoritmos de Pesquisa
Tipos Abstratos de Dados

Algoritmos e Estrutura de Dados II

 Analogia com um dicionrio da lngua portuguesa:


Chaves palavras
Registros entradas associadas com
pronncia, definio, sinnimos, outras informaes

 Nome comumente utilizado para descrever uma estrutura de


dados para pesquisa.
 Dicionrio um tipo abstrato de dados com as operaes:
1. Inicializa
2. Pesquisa
3. Insere
4. Retira

Dicionrio

Algoritmos e Estrutura de Dados II

 Armazenamento de um conjunto de registros por


meio do tipo estruturado arranjo:

 Mtodo de pesquisa mais simples: a partir do


primeiro registro, pesquise seqencialmente at
encontrar a chave procurada; ento pare.

Pesquisa Seqencial

typedef struct Tabela {


Registro Item[Maxn + 1];
Indice n;
} Tabela;

typedef int Indice;

typedef struct Registro {


TipoChave Chave;
/* outros componentes */
} Registro;

# define Maxn
10
typedef long TipoChave;

Algoritmos e Estrutura de Dados II

Pesquisa Seqencial

T->Item[0].Chave = x;
i = T->n + 1;
do {
i--;
} while (T->Item[i].Chave != x);
return i;

Indice Pesquisa(TipoChave x, Tabela *T)


{ int i;

void Inicializa(Tabela *T)


{
T->n = 0;
}

Algoritmos e Estrutura de Dados II

 Implementao para as operaes Inicializa, Pesquisa :

Pesquisa Seqencial

Algoritmos e Estrutura de Dados II

Indice getN(Tabela *T)


{ return T->n;
}
Indice Pesquisa(TipoChave x, Tabela *T, Indice k)
{ int i;
T->Item[0].Chave = x;
i = k;
do { i--; } while (T->Item[i].Chave != x);
return i;
}
void recuperaRegistros(Tabela *T, TipoChave x)
{ Indice k;
k =Pesquisa(x,T, getN(T)+1);
if (k!= 0) printf(Achou x no %d!\n,k);
else printf(Nao achou x!\n);
while (k != 0) {
k = Pesquisa(x,T,k); printf(Achou x no %d!\n,k);
}
}

Pesquisa Seqencial

void Insere(Registro Reg, Tabela *T)


{
if (T->n == Maxn)
printf("Erro : tabela cheia\n");
else
{
T->n++;
T->Item[T->n] = Reg;
}
}

 Implementao para a operacao Insere:

Algoritmos e Estrutura de Dados II

Pesquisa Seqencial

Algoritmos e Estrutura de Dados II

 Para aplicaes com esta caracterstica


necessrio incluir um argumento a mais na funo
Pesquisa para conter o ndice a partir do qual se
quer pesquisar.

 A implementao no suporta mais de um registro


com uma mesma chave.

 Caso no esteja presente, o valor retornado zero.

 Pesquisa retorna o ndice do registro que contm a


chave x;

Pesquisa Seqencial

isto faz com que esta tcnica seja conhecida como


pesquisa seqencial rpida.
Algoritmos e Estrutura de Dados II

o anel interno da funo Pesquisa extremamente


simples: o ndice i decrementado e a chave de pesquisa
comparada com a chave que est no registro.

 No necessrio testar se i > 0, devido a isto:

 Garante que a pesquisa sempre termina: se o ndice retornado


por Pesquisa for zero, a pesquisa foi sem sucesso.

 Utilizao de um registro sentinela na posio zero do array:

Pesquisa Seqencial

Algoritmos e Estrutura de Dados II

O algoritmo de pesquisa seqencial a melhor


escolha para o problema de pesquisa em tabelas com
at 25 registros.

Anlise:
Pesquisa com sucesso:
melhor caso : C(n) = 1
pior caso : C(n) = n
caso mdio: C(n) = (n + 1) / 2
Pesquisa sem sucesso:
C (n) = n + 1.

Pesquisa Seqencial

Algoritmos e Estrutura de Dados II

4. Repita o processo at que a chave seja encontrada, ou fique


apenas um registro cuja chave diferente da procurada,
significando uma pesquisa sem sucesso.

3. Se a chave maior ento o registro procurado est na


segunda metade da tabela.

2. Se a chave menor ento o registro procurado est na


primeira metade da tabela

1. Compare a chave com o registro que est na posio do meio


da tabela.

 Para saber se uma chave est presente na tabela

 Pesquisa em tabela pode ser mais eficiente Se registros


forem mantidos em ordem

Pesquisa Binria

Algoritmos e Estrutura de Dados II

Exemplo de Pesquisa Binria para a


Chave G

Algoritmos e Estrutura de Dados II

Conseqentemente, a pesquisa binria no deve ser


usada em aplicaes muito dinmicas.

Ressalva: o custo para manter a tabela ordenada


alto: a cada insero na posio p da tabela implica no
deslocamento dos registros a partir da posio p para
as posies seguintes.

Logo: o nmero de vezes que o tamanho da tabela


dividido ao meio cerca de log n.

A cada iterao do algoritmo, o tamanho da tabela


dividido ao meio.

 Anlise

Pesquisa Binria

Algoritmos e Estrutura de Dados II

Fazer picadinho de carne e vegetais para cozinhar.


Fazer uma baguna. (Websters New World Dictionary)

 Hash signica:

 Os registros armazenados em uma tabela so diretamente


endereados a partir de uma transformao aritmtica sobre
a chave de pesquisa.

Transformao de Chave (Hashing)

Algoritmos e Estrutura de Dados II

 Um mtodo de pesquisa com o uso da transformao de


chave constitudo de duas etapas principais:
1 - Computar o valor da funo de transformao, a qual
transforma a chave de pesquisa em um endereo da tabela.
2 - Considerando que duas ou mais chaves podem ser
transformadas em um mesmo endereo de tabela,
necessrio existir um mtodo para lidar com colises.
 Qualquer que seja a funo de transformao, algumas
colises iro ocorrer fatalmente, e tais colises tm de ser
resolvidas de alguma forma.
 Mesmo que se obtenha uma funo de transformao que
distribua os registros de forma uniforme entre as entradas da
tabela, existe uma alta probabilidade de haver colises.

Transformao de Chave (Hashing)

Algoritmos e Estrutura de Dados II

 Assim, se for utilizada uma funo de transformao


uniforme que enderece 23 chaves randmicas em
uma tabela de tamanho 365, a probabilidade de que
haja colises maior do que 50%.

que em um grupo de 23 ou mais pessoas, juntas ao


acaso, existe uma chance maior do que 50% de que 2
pessoas comemorem aniversrio no mesmo dia.

 O paradoxo do aniversrio (Feller,1968, p. 33), diz

Transformao de Chave (Hashing)

Algoritmos e Estrutura de Dados II

 A probabilidade p de se inserir N itens consecutivos


sem coliso em uma tabela de tamanho M :

Transformao de Chave (Hashing)

p
0,883
0,524
0,493
0,303

Algoritmos e Estrutura de Dados II

 Para N pequeno a probabilidade p pode ser aproximada


por p N (N 1))/730 . Por exemplo, para N = 10
ento p 87,7%.

N
10
22
23
30

 Alguns valores de p para diferentes valores de N,


onde M = 365.

Transformao de Chave (Hashing)

Algoritmos e Estrutura de Dados II

 A funo de transformao ideal aquela que:


Seja simples de ser computada.
Para cada chave de entrada, qualquer uma das
sadas possveis igualmente provvel de ocorrer.

 Uma funo de transformao deve mapear chaves em


inteiros dentro do intervalo [0..M 1], onde M o
tamanho da tabela.

Funes de Transformao

h(K) = K % M (em linguagem C)

Algoritmos e Estrutura de Dados II

onde K um inteiro correspondente chave.

ou

h(K) = K mod M

 Usa o resto da diviso por M .

Mtodo mais Usado

inteiros.

Algoritmos e Estrutura de Dados II

onde b a base do conjunto de caracteres (geralmente


b = 64 para BCD, 128 para ASCII, 256 para EBCDIC, ou
100 para alguns cdigos decimais), e i e j so pequenos

bi j

 Cuidado na escolha do valor de M. M deve ser um


nmero primo, mas no qualquer primo: devem ser
evitados os nmeros primos obtidos a partir de

Mtodo mais Usado

Algoritmos e Estrutura de Dados II

 p[i] um inteiro de um conjunto de pesos gerados


aleatoriamente para 1 i n.

 Chave[i] corresponde representao ASCII do i-simo


caractere da chave.

 n o nmero de caracteres da chave.

 As chaves no numricas devem ser transformadas em nmeros:

Transformao de Chaves No
Numricas

Algoritmos e Estrutura de Dados II

leva a duas funes de transformao h1 (K) e h2 (K)


diferentes.

Dois conjuntos diferentes de pesos p1 [i] e p2 [i], 1 i n,

 Vantagem de se usar pesos:

Transformao de Chaves No
Numricas

Algoritmos e Estrutura de Dados II

p[i] = 1+(int) (10000.0*rand()/(RAND_MAX+1.0));

{ /* Gera valores aleatorios entre 1 e 10.000 */


int i;
struct timeval semente;
/* Utilizar o tempo como semente para a funcao srand() */
gettimeofday(&semente,NULL);
srand((int)(semente.tv_sec + 1000000*semente.tv_usec));
for (i = 0; i < n; i++)

void GeraPesos(TipoPesos p)

 Programa que gera um peso para cada caracter de uma chave


constituda de n caracteres:

Transformao de Chaves No
Numricas

return (Soma % M);

Soma += (unsigned int)Chave[i] * p[i];

for (i = 0; i < comp; i++)

int i;
unsigned int Soma = 0;
int comp = strlen(Chave);

Algoritmos e Estrutura de Dados II

Implementao da funo de transformao:

Indice h(TipoChave Chave, TipoPesos p)

Transformao de Chaves No
Numricas

Algoritmos e Estrutura de Dados II

 Assim, todas as chaves com mesmo endereo so


encadeadas em uma lista linear.

simplesmente construir uma lista linear encadeada


para cada endereo da tabela.

 Uma das formas de resolver as colises

Listas Encadeadas

Algoritmos e Estrutura de Dados II

O resultado da insero das chaves P E S Q U I S A


na tabela o seguinte:

utilizada para M = 7,

h(Chave) = Chave % M

pelo nmero i e a funo de transformao

 Exemplo: Se a i-sima letra do alfabeto representada

Listas Encadeadas

h(A) = h(1) = 1,
h(E) = h(5) = 5,
h(S) = h(19) = 5, etc

 Por exemplo:

Algoritmos e Estrutura de Dados II

Listas Encadeadas

typedef unsigned int Indice;

typedef struct TipoItem {


/* outros componentes */
TipoChave Chave;
} TipoItem;

typedef unsigned int TipoPesos[n];

#define M
7
#define n
7
typedef char TipoChave[n];

Algoritmos e Estrutura de Dados II

Estrutura do Dicionrio para Listas Encadeadas

typedef TipoLista TipoDicionario[M];

typedef struct TipoLista {


Celula *Primeiro, *Ultimo;
} TipoLista;

typedef struct Celula {


TipoItem Item;
Apontador Prox;
} Celula;

typedef struct Celula* Apontador;

Algoritmos e Estrutura de Dados II

Estrutura do Dicionrio para Listas Encadeadas

int i;
for (i = 0; i < M; i++)
FLVazia(&T[i]);

void Inicializa(TipoDicionario T)

Algoritmos e Estrutura de Dados II

Operaes do Dicionrio Usando


Listas Encadeadas

Algoritmos e Estrutura de Dados II

{ /*Obs.: Apontador de retorno aponta para o item anterior da lista */


Indice i; Apontador Ap;
i = h(Ch, p);
if (Vazia(T[i])) return NULL; /* Pesquisa sem sucesso */
else {
Ap = T[i].Primeiro;
while ((Ap->Prox->Prox != NULL) &&
(strncmp(Ch, Ap->Prox->Item.Chave, sizeof(TipoChave)) ))
Ap = Ap->Prox;
if (!strncmp(Ch, Ap->Prox->Item.Chave, sizeof(TipoChave)))
return Ap;
else return NULL; /* Pesquisa sem sucesso */
}

Apontador Pesquisa(TipoChave Ch, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Listas Encadeadas

else

Algoritmos e Estrutura de Dados II

printf(" Registro ja esta presente\n");

Ins(x, &T[h(x.Chave, p)]);

if (Pesquisa(x.Chave, p, T) == NULL)

void Insere(TipoItem x, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Listas Encadeadas

else

Ret(Ap, &T[h(x.Chave, p)], &x);

Algoritmos e Estrutura de Dados II

if (Ap == NULL) printf(" Registro nao esta presente\n");

Ap = Pesquisa(x.Chave, p, T);

Apontador Ap;

void Retira(TipoItem x, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Listas Encadeadas

Para valores de M prximos de N , o tempo se torna


constante, isto , independente de N .
Algoritmos e Estrutura de Dados II

 Logo: as operaes Pesquisa, Insere e Retira custam


O(1 + N/M ) operaes em mdia, onde a constante 1
representa o tempo para encontrar a entrada na tabela e N/M
o tempo para percorrer a lista.

 Assumindo que qualquer item do conjunto tem igual


probabilidade de ser endereado para qualquer entrada de T,
ento o comprimento esperado de cada lista encadeada N/M,
onde N representa o nmero de registros na tabela e M o
tamanho da tabela.

Anlise

colises. (Knuth, 1973, p.518)

Algoritmos e Estrutura de Dados II

lugares vazios na prpria tabela para resolver as

uma tabela de tamanho M > N , os quais utilizam os

 Existem vrios mtodos para armazenar N registros em

armazenar os registros.

haver necessidade de usar apontadores para

tabela puder ser previamente estimado, ento no

 Quando o nmero de registros a serem armazenados na

Endereamento Aberto

Algoritmos e Estrutura de Dados II

hj = (h(x) + j) mod M, para 1 j M 1.

 Existem vrias propostas para a escolha de localizaes


alternativas. A mais simples chamada de hashing linear,
onde a posio hj na tabela dada por:

 No Endereamento aberto todas as chaves so


armazenadas na prpria tabela, sem o uso de apontadores
explcitos.

Endereamento Aberto

Algoritmos e Estrutura de Dados II

 ento o resultado da insero das chaves L U N E S na


tabela, usando hashing linear para resolver colises
mostrado abaixo.

utilizada para M = 7,

h(Chave) = Chave % M

 Se a i-sima letra do alfabeto representada pelo nmero i e


a funo de transformao

Exemplo

Algoritmos e Estrutura de Dados II

h(L) = h(12) = 5,
h(U ) = h(21) = 0,
h(N ) = h(14) = 0,
h(E) = h(5) = 5,
h(S) = h(19) = 5.

 Por exemplo:

Exemplo

7
11 /* Tamanho da chave */

#define n

"**********"

#define Retirado

#define M

"!!!!!!!!!!"

#define Vazio

Algoritmos e Estrutura de Dados II

Estrutura do Dicionrio Usando


Endereamento Aberto

typedef TipoItem TipoDicionario[M];

typedef unsigned int Indice;

} TipoItem;

TipoChave Chave;

/* outros componentes */

typedef struct TipoItem {

typedef unsigned TipoPesos[n];

typedef char TipoChave[n];

typedef unsigned int Apontador;

Algoritmos e Estrutura de Dados II

Estrutura do Dicionrio Usando


Endereamento Aberto

int i;
for (i = 0; i < M; i++)
memcpy(T[i].Chave, Vazio, n);

void Inicializa(TipoDicionario T)

Algoritmos e Estrutura de Dados II

Operaes do Dicionrio Usando


Endereamento Aberto

Algoritmos e Estrutura de Dados II

while ( (strcmp (T[(Inicial + i) % M].Chave,Vazio) != 0) &&


(strcmp ( T[(Inicial + i) % M].Chave, Ch) != 0) &&
(i < M))
i++;
if (strcmp (T[(Inicial + i) % M].Chave, Ch) == 0)
return ((Inicial + i) % M);
else return M; /* Pesquisa sem sucesso */

Inicial = h(Ch, p);

{ unsigned int i = 0;
unsigned int Inicial;

Apontador Pesquisa(TipoChave Ch, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Endereamento Aberto

unsigned int Inicial;

if (Pesquisa(x.Chave, p, T) < M) {
printf("Elemento ja esta presente\n");
return;
}
Inicial = h(x.Chave, p);
while ( (strcmp ( T[(Inicial + i) % M].Chave,Vazio) != 0) &&
(strcmp ( T[(Inicial + i) % M].Chave, Retirado) != 0) &&
( i < M)) i++;
if (i < M) {
strcpy (T[(Inicial + i) % M].Chave, x.Chave); /* Copiar os demais
campos de x, se existirem */
}
else printf(" Tabela cheia\n");
Algoritmos e Estrutura de Dados II

{ unsigned int i = 0;

void Insere(TipoItem x, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Endereamento Aberto

Algoritmos e Estrutura de Dados II

else printf("Registro nao esta presente\n");

if (i < M) memcpy(T[i].Chave, Retirado, n);

i = Pesquisa(Ch, p, T);

Indice i;

void Retira(TipoChave Ch, TipoPesos p, TipoDicionario T)

Operaes do Dicionrio Usando


Endereamento Aberto

Algoritmos e Estrutura de Dados II

ocupar uma posio na tabela que esteja contgua a outras


posies j ocupadas, o que deteriora o tempo necessrio
para novas pesquisas.

 Este fenmeno ocorre na medida em que a tabela comea a


car cheia, pois a insero de uma nova chave tende a

 O hashing linear sofre de um mal chamado


agrupamento (clustering) (Knuth, 1973, pp.520521).

 Seja = N/M o fator de carga da tabela. Conforme


demonstrado por Knuth (1973), o custo de uma pesquisa com
sucesso

Anlise

Algoritmos e Estrutura de Dados II

 O melhor caso, assim como o caso mdio, O(1).

 Entretanto, apesar do hashing linear ser um mtodo


relativamente pobre para resolver colises os resultados
apresentados so bons.

Anlise

Pior caso O(N)

Algoritmos e Estrutura de Dados II

Custo para recuperar os registros na ordem lexicogrca


das chaves alto, sendo necessrio ordenar o arquivo.

 Desvantagens:

Simplicidade de implementao

Alta ecincia no custo de pesquisa, que O(1) para o


caso mdio.

 Vantagens:

Vantagens e Desvantagens de
Transformao da Chave

Algoritmos e Estrutura de Dados II

4. Utilizao de memria primria e secundria.

3. Boa taxa de utilizao de memria.

2. Facilidade de insero e retirada de registros.

1. Acesso direto e seqencial eficientes.

 Particularmente adequada quando existe necessidade de


considerar todos ou alguma combinao de:

 A rvore de pesquisa uma estrutura de dados muito


eficiente para armazenar informao.

rvores de Pesquisa

Algoritmos e Estrutura de Dados II

2. Todos os registros com chaves maiores esto na subrvore


direita.

1. Todos os registros com chaves menores esto na


subrvore esquerda.

 Temos a relao invariante

 Para qualquer n que contenha um registro

rvores Binrias de Pesquisa sem Balanceamento

Algoritmos e Estrutura de Dados II

 O nvel do n raiz 0.
Se um n est no nvel i ento a raiz de suas subrvores
esto no nvel i + 1.
A altura de um n o comprimento do caminho mais longo
deste n at um n folha.
A altura de uma rvore a altura do n raiz.

rvores Binrias de Pesquisa sem


Balanceamento

typedef Apontador TipoDicionario;

typedef struct No * Apontador;

Algoritmos e Estrutura de Dados II

typedef Struct No {
Registro Reg;
Apontador Esq, Dir;
} No;

typedef struct Registro {


TipoChave Chave;
/* outros componentes */
} Registro;

typedef long TipoChave;

 Estrutura de dados:

Implementao do Tipo Abstrato de Dados


Dicionrio usando a Estruturade Dados
rvore Binria de Pesquisa

Algoritmos e Estrutura de Dados II

Se a pesquisa tiver sucesso ento o contedo do


registro retorna no prprio registro x.

Repita o processo recursivamente, at que a chave


procurada seja encontrada ou um n folha atingido.

Se x maior, v para a subrvore direita.

Se x menor, v para a subrvore esquerda.

Compare-a com a chave que est na raiz.

 Para encontrar um registro com uma chave x:

Procedimento para Pesquisar


na rvore

Algoritmos e Estrutura de Dados II

if (*p == NULL) {
printf("Erro : Registro nao esta presente na arvore\n");
return;
}
if (x->Chave < (*p)->Reg.Chave) {
Pesquisa(x, &(*p)->Esq);
return;
}
if (x->Chave > (*p)->Reg.Chave) Pesquisa(x, &(*p)->Dir);
else *x = (*p)->Reg;

void Pesquisa(Registro *x, Apontador *p)

Procedimento para Pesquisar


na rvore

Algoritmos e Estrutura de Dados II

 O apontador nulo atingido o ponto de insero.

 Atingir um apontador nulo em um processo de pesquisa


significa uma pesquisa sem sucesso.

Procedimento para Inserir na rvore

Algoritmos e Estrutura de Dados II

if (*p == NULL) {
*p = (Apontador)malloc(sizeof(No));
(*p)->Reg = x;
(*p)->Esq = NULL; (*p)->Dir = NULL;
return;
}
if (x.Chave < (*p)->Reg.Chave) {
Insere(x, &(*p)->Esq);
return;
}
if (x.Chave > (*p)->Reg.Chave) Insere(x, &(*p)->Dir);
else printf("Erro : Registro ja existe na arvore\n");

void Insere(Registro x, Apontador *p)

Procedimento para Inserir na rvore

void Inicializa(Apontador *Dicionario)


{
*Dicionario = NULL;
}

Algoritmos e Estrutura de Dados II

Procedimentos para Inicializar


e Criar a rvore

Algoritmos e Estrutura de Dados II

ou pelo registro mais esquerda na subrvore direita.

esquerda;

substitudo pelo registro mais direita na subrvore

a ser retirado deve ser primeiro:

3. No caso do n conter dois descendentes o registro

mximo um descendente a operao simples.

2. Se o n que contm o registro a ser retirado possui no

1. A retirada de um registro no to simples quanto a insero.

 Alguns comentrios:

Procedimento para Retirar x


da rvore

Algoritmos e Estrutura de Dados II

 Assim: para retirar o registro com chave 5 da rvore basta


troc-lo pelo registro com chave 4 ou pelo registro com chave
6, e ento retirar o n que recebeu o registro com chave 5.

Exemplo da Retirada de um Registro


da rvore

if ( (*r)->Dir != NULL)
{
Antecessor(q, &(*r)->Dir);
return;
}
q->Reg = (*r)->Reg;
q = *r;
*r = (*r)->Esq;
free(q);

void Antecessor(Apontador q, Apontador *r)

Algoritmos e Estrutura de Dados II

Exemplo da Retirada de um
Registro da rvore

if (*p == NULL) {
printf("Erro : Registro nao esta na arvore\n");
return;
}
if (x.Chave < (*p)->Reg.Chave) {
Retira(x, &(*p)->Esq);
return;
}
if (x.Chave > (*p)->Reg.Chave){
Retira(x, &(*p)->Dir);
return;
Algoritmos e Estrutura de Dados II
}

{ Apontador Aux;

void Retira(Registro x, Apontador *p)

Exemplo da Retirada de um Registro


da rvore

if ((*p)->Dir == NULL) {
Aux = *p;
*p = (*p)->Esq;
free(Aux);
return;
}
if ((*p)->Esq != NULL) {
Antecessor(*p, &(*p)->Esq);
return;
}
Aux = *p;
*p = (*p)->Dir;
free(Aux);

Algoritmos e Estrutura de Dados II

Exemplo da Retirada de um Registro


da rvore

Algoritmos e Estrutura de Dados II

Obs.: proc. recursivo Antecessor s ativado quando


o n que contm registro a ser retirado possui 2
descendentes.
Soluo usada por Wirth, 1976, p.211.

Exemplo da Retirada de um Registro


da rvore

Algoritmos e Estrutura de Dados II

Outro Exemplo de Retirada de N

Algoritmos e Estrutura de Dados II

Outro Exemplo de Retirada de N

Algoritmos e Estrutura de Dados II

 Aps construda a rvore, pode ser necessrio percorrer


todo os registros que compem a tabela ou arquivo.
 Existe mais de uma ordem de caminhamento em
rvores, mas a mais til a chamada ordem de
caminhamento central.
 O caminhamento central mais bem expresso em
termos recursivos:
1. caminha na subrvore esquerda na ordem central;
2. visita a raiz;
3. caminha na subrvore direita na ordem central.
 Uma caracterstica importante do caminhamento central
que os ns so visitados de forma ordenada.

Caminhamento Central

Algoritmos e Estrutura de Dados II

 usando caminhamento central recupera as chaves na ordem


1, 2, 3, 4, 5, 6 e 7.

 Percorrer a rvore:

Caminhamento Central

if (p == NULL) return;
Central(p->Esq);
printf("%ld\n", p->Reg.Chave);
Central(p->Dir);

void Central(Apontador p)

Algoritmos e Estrutura de Dados II

 O procedimento Central mostrado abaixo:

Caminhamento Central

Algoritmos e Estrutura de Dados II

 O tempo de execuo dos algoritmos para rvores binrias


de pesquisa dependem muito do formato das rvores.

 O nmero de comparaes em uma pesquisa com sucesso:


melhor caso : C(n) = O(1)
pior caso: C(n) = O(n)
caso mdio : C(n) = O(log n)

Anlise

Algoritmos e Estrutura de Dados II

2. Para uma rvore de pesquisa aleatoria o nmero


esperado de comparaes para recuperar um
registro qualquer cerca de 1,39 log n, apenas 39%
pior que a rvore completamente balanceada.

inseridas em ordem crescente ou decrescente.


Neste caso a rvore resultante uma lista linear,
cujo nmero mdio de comparaes (n + 1)/2.

1. Para obter o pior caso basta que as chaves sejam

Anlise

Você também pode gostar