You are on page 1of 29

ESTRUTURAS DE DADOS

E ALGORITMOS

2015, Gizelle Kupac Vianna (PPGMMC/UFRRJ)


Gizelle Kupac Vianna (PPGMMC/UFRRJ) 2

TABELAS DE DISPERSO
Aula 15
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 3

Tabelas de Disperso
Tabelas usadas para implementar ndices de bancos de
dados. so usadas para compactar tabelas de dados
esparsas, as tabelas de hash otimizam o acesso a
campos de um banco de dados.

Ex: criar um ndice para uma tabela contendo dados de


alunos. A tabela original contm espao suficiente para
armazenar 5000 registros mas, atualmente s 100
campos foram preenchidos.

A rea de memria utilizada para armazenar os dados


teis pode ser reduzida se usarmos uma tabela de hash
para armazenar suas chaves.
4

Tabelas de Disperso (Hash Tables)


Os ndices devem, de alguma forma, estar relacionados aos
contedos das posies correspondentes.
Esse relacionamento estabelecido por uma funo h:NM,
onde o domnio N o espao de chaves e M o espao de
ndices. Exemplo:
N o conjunto de todas as cadeias alfabticas
M um inteiro entre 65 e 91
h o cdigo ASCII do primeiro caractere da cadeia:
h(AMORA) = 65
h(ZEBRA) = 91
No melhor caso, o acesso a uma dada chave pode ser feito em
O(1). No pior caso, entretanto, o custo do acesso pode ser de
O(n).
5

Funes de Disperso
Idealmente, funes de disperso deveriam ser injetivas,
isto , todas as chaves deveriam ser mapeadas por h em
um ndice distinto.

Mas isso s seria possvel se o nmero de chaves N fosse


menor ou igual ao espao disponvel para armazenamento,
M. Um caso trivial h(x) = x, ou seja, quando usamos
acesso direto.

Em geral, |N| >> |M| e podemos ter duas chaves x e y, x y


tais que h(x) = h(y). Ao tentarmos inserir ambas as chaves
na tabela, ocorre uma coliso.
6

Funes de Disperso
Em geral, uma boa funo de disperso deve
reunir as seguintes qualidades:
produzir poucas colises: requer alguma anlise sobre a
distribuio das chaves sendo acessadas. Ex.: se o dado
a ser armazenado so cdigos alfanumricos que
comeam sempre por A ou B, usar o primeiro caractere
como chave pode levar a muitas colises .
ser fcil de computar: conter poucas e simples
operaes aritmticas.
ser uniforme: essa funo precisa garantir que todas as
posies tenham probabilidade semelhante de serem
escolhidas.
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 7

Funes de Disperso
A funo MOD uma das funes de disperso mais
empregadas. Utiliza-se h(x) = x mod m, onde:
x = chave do registro a ser armazenado
m = dimenso da tabela de armazenamento.

Uma abordagem comum para a solucionar a ocorrncia


de uma coliso utilizar outra funo de disperso que
indica o prximo ndice a ser tentado.

Em geral temos a nova funo de disperso h (x, k) onde


x a chave
k = 0, 1, 2, etc. o nmero da tentativa
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 8

Tabelas de Hash Estticas


As funes da tabela hash so:
Cria_hash
Hash_vazio
Hash_cheio
Inserir
Remover
Percorrer
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 9

Tabelas de Hash Estticas


#define TAM 10
#define VAZIO -1
typedef long tno;

typedef struct {
tno chave[TAM];
} thash;

void cria_tabHash (thash * th) {


int i;

for (i=0; i<TAM; i++) {


th->chave[i] = VAZIO;
}
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 10

Tabelas de Hash Estticas


int hash_cheio (thash th) {
int i;
for (i=0; i<TAM; i++) {
if (th.chave[i] == VAZIO) return 0;
}
return 1;
}

int hash_vazio (thash th) {


int i;
for (i=0; i<TAM; i++) {
if (th.chave[i] != VAZIO) return 0;
}
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 11

Tabelas de Hash Estticas


int inserir (thash * th, tno chave) {
int i;
long ind;

if (hash_cheio(*th)) return 0;

ind = chave % TAM;


// exerccio: testar outras funes de hash!!!

if (th->chave[ind] == VAZIO) {
th->chave[ind] = chave;
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 12

Tabelas de Hash Estticas


for (i=ind;i<TAM;i++) {// se a posicao-base estava ocupada,
vou procurar nas proximas
if (th->chave[i] == VAZIO) {
th->chave[i] = chave;
return 1;
}
}
for (i=0;i<ind;i++) {// chegou ao fim e nao achou posicao
livre, volta para o inicio
if (th->chave[i] == VAZIO) {
th->chave[i] = chave;
return 1;
}
}
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 13

Tabelas de Hash Estticas


int remover (thash * th, tno chave) {
int i, ind;

if (hash_vazio(*th)) return 0;

ind = chave % TAM;

if (th->chave[ind] == chave) {
th->chave[ind] = VAZIO;
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 14

Tabelas de Hash Estticas


for (i=ind;i<TAM;i++) {// a posicao estava ocupada por outra chave,
vou procurar nas proximas
if (th->chave[i] == chave) {
th->chave[i] = VAZIO;
return 1;
}
}

for (i=0;i<ind;i++) { // chegou ao fim e nao achou posicao livre,


volta para o inicio
if (th->chave[i] == chave) {
th->chave[i] = VAZIO;
return 1;
}
}
return -1; // nao achou a chave no hash
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 15

Tabelas de Hash Estticas


void percorrer (thash th) {
int i;

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


printf("%d - ",th.chave[i]);

printf("\n");

return;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 16

Tabelas de Hash Estticas


main () {
thash H;

cria_tabHash(&H);

inserir(&H,2010390123);
remover(&H,201039012
inserir(&H,2012391234); 3);
inserir(&H,2013392301); remover(&H,201239123
inserir(&H,1); 4);
inserir(&H,2); remover(&H,2);
inserir(&H,4); remover(&H,1);
inserir(&H,11); percorrer (H);
inserir(&H,12);
inserir(&H,5); return 0;
percorrer (H); }
17

Tabelas de Hash Dinmicas


Uma outra maneira muito empregadas para lidar com
colises permitir que cada posio da tabela seja
ocupada por mais de uma chave.

Em vez de guardar uma chave, guarda-se uma lista


encadeada de chaves.

Na verdade, pode-se usar qualquer estrutura uma


rvore, por exemplo mas como a ocorrncia de
colises deve ser relativamente rara, uma lista
encadeada, ordenada ou no costuma, ser suficiente.
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 18

Tabelas de Hash Dinmicas


O ndice primrio dessa tabela semelhante ao do hash
esttico: um vetor de ndices.

A diferena que os campos do vetor agora so


ponteiros para uma lista simplesmente encadeada.

Ao realizar operaes no ndice (incluso, remoo ou


consultas), a busca pela posio inicial igual vista
anteriormente, mas no caso de colises, os registros so
adicionados a uma lista. Existe uma lista associada a
cada posio do vetor de ndices.
19

Tabelas de Hash Dinmicas


Gizelle Kupac Vianna (PPGMMC/UFRRJ) 20

Tabelas de Hash Dinmicas


As funes da tabela hash dinmica so:
Cria_hash
Hash_vazio
Inserir
Remover
Busca_anterior
Percorrer
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 21

Tabelas de Hash Dinmicas


#define TAM 10

typedef int tno;

typedef struct _tnoe {


tno chave;
struct _tnoe *prox;
} tnoe;

typedef struct {
tnoe *prim;
} tind;

typedef struct {
tind indice[TAM];
} thash;
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 22

Tabelas de Hash Dinmicas


void cria_tabHash (thash * th) {
int i;
for (i=0; i<TAM; i++) {
th->indice[i].prim = NULL;
}
return;
}

int hash_vazio (thash th) {


int i;
for (i=0; i<TAM; i++) {
if (th.indice[i].prim != NULL) return 0;
}
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 23

Tabelas de Hash Dinmicas


tnoe * cria_no (tno chave) {
tnoe *no;

no = (tnoe *) malloc(sizeof(tnoe));
if (no == NULL) {
printf("\n Erro de Memoria!");
exit(0);
}
no->chave = chave;
no->prox = NULL;

return no;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 24

Tabelas de Hash Dinmicas


int inserir (thash * th, tno valor) {
tnoe * aux;
int ind;

ind = valor % TAM;


aux = cria_no(valor);

aux->prox = th->indice[ind].prim; // insiro no


inicio da lista para simplificar
th->indice[ind].prim = aux;
return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 25

Tabelas de Hash Dinmicas


int busca_ant (thash *th, tnoe * * ant, tno valor) {
tnoe *aux;
int ind;

ind = valor % TAM;


aux=th->indice[ind].prim;
*ant=NULL;
while ((aux != NULL) && (aux->chave!=valor)) {
*ant=aux;
aux=aux->prox;
}

if (aux == NULL) return 0;


return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 26

Tabelas de Hash Dinmicas


int remover(thash *th, tno valor) {
tnoe *ant, *aux;
int ind;

ind = valor % TAM;

if (hash_vazio(*th)) return 0;

if (!busca_ant(th,&ant,valor)) {
printf("\nElemento %d nao pertence `a lista!",valor);
return -1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 27

Tabelas de Hash Dinmicas


if (ant == NULL) {//elemento e' o primeiro da lista
aux = th->indice[ind].prim;
th->indice[ind].prim = aux->prox;
}
else {
aux = ant->prox;
ant->prox = aux->prox;
}

free(aux);

return 1;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 28

Tabelas de Hash Dinmicas


void percorrer (thash th) {
int i;
tnoe * aux;

for (i=0; i<TAM; i++) {


printf("\n");
aux = th.indice[i].prim;
while (aux != NULL) {
printf("%d - ",aux->chave);
aux = aux -> prox;
}
}
return;
}
Gizelle Kupac Vianna (PPGMMC/UFRRJ) 29

Tabelas de Hash Dinmicas


main () {
thash H;
cria_tabHash(&H);

inserir(&H,1);
inserir(&H,2);
inserir(&H,4); remover(&H,1);
inserir(&H,11); remover(&H,2);
inserir(&H,12); remover(&H,4);
inserir(&H,5); remover(&H,11);
inserir(&H,15); remover(&H,12);
inserir(&H,21); remover(&H,5);
inserir(&H,22); remover(&H,15);
inserir(&H,25);
inserir(&H,33); return 0;
percorrer (H); }

You might also like