Sunteți pe pagina 1din 21

Hash table

-pe baza unei functii hash, cheia de cautare e pusa in corespondenta cu


pozita elementului din cadrul colectiei

Cheia de cautare
functia Hash

Valoare Valoare
alfanumerica numerica

Valoare[elem1,ele
m n]

mai multe valori


pt acelasi index
evitare coliziuni
=> trebuie
creata o lista

Elem 1 Elem 2 Elem3 ... Elem n

Tabela cu acces direct


Functia Hash ->prelucreaza cheia asociata fiecarei inregistrari si determina
pozitia in cadrul tabelei de dispersie a elementului respectiv.

HashStudent size=
2

elem[0] elem[1]

inf
NodDat inf
next
e next

nr_matricol
**elem

info
nume

elem[i]-retine adresa urmatorului nod

inserare

-calculeaza pozitia nr_matricol%hs.size


nod_no
u

next
-trebuie sa punem nodul inNULL
vectorul de liste
-verifica daca elem[index] e liber, daca este pune nodul acolo
**elem
ex: index =1

elem[0] elem[1]

s nod_no
u

next

NULL

-daca index 2 nu era liber=> COLIZIUNE

t
s

next

**elem

elem[0] elem[1]

next
t

info

next

info

#include <conio.h> next


#include <iostream> NULL
using namespace std;

//structura de date stocata in tabela de dispersie


struct Student
{
int nr_matricol;
char nume[20];
};

//elementele tabelei de dispersie


//pentru simplificarea codului s-a utilizat o structura
struct NodDate
{
Student inf;
NodDate *next;

};

//Cheia este nr_matricol al studentului, dupa asta se va face cautarea


//size-nr de elemente
// **elem-vector de liste
struct HashStudent
{
int size;
NodDate ** elem;
};

//functie simpla de dispersie care utilizeaza operatorul modulo pentru a genera pozitia in
tabela
//cheia=nr_matricol, size=101 => pt nr_matricol =1000 => index=1000%101=91
int HashFunction(int cheie, HashStudent hs)
{
return cheie%hs.size;
};

//aloca memorie pentru structura si initializeaza cu NULL valorile


HashStudent AlocaMemorie()
{
HashStudent hs;
hs.size = 101;
//vector de liste
hs.elem = new NodDate*[hs.size];
for (int i = 0; i<hs.size; i++)
hs.elem[i] = NULL;
return hs;
}

//insereaza un element pe o pozitie generata de functia de dispersie


//pe baza valorii matricolei din structura Student
int Insereaza(Student s, HashStudent hs)
{
int index = -1;

if (s.nr_matricol<0)
return index;
//adresa nu e nula, avem elem
if (hs.elem != NULL)
{
//genereaza pozitia in tabela
//apeleaza HashFunction care va face nr_matricol%101 pentru a genera o
pozitie
index = HashFunction(s.nr_matricol, hs);
//prima inregistrare
NodDate *nod_nou = new NodDate;
nod_nou->next = NULL;
nod_nou->inf = s;

if (hs.elem[index] == NULL)
{
hs.elem[index] = nod_nou;
}
else //coliziune
{
NodDate *t = hs.elem[index];
while (t->next != NULL)
t = t->next;
t->next = nod_nou;
}
}
return index;
}

//Afiseaza continutul tabelei de dispersie


void Afiseaza(HashStudent hs)
{
if (hs.elem != NULL)
{
for (int i = 0; i<hs.size; i++)
{
if (hs.elem[i] != NULL)
{
NodDate *t = hs.elem[i];
while (t != NULL)
{
cout << "S-a inserat in pozitia: " << i << " cheia: " << t-
>inf.nr_matricol << endl;
t = t->next;
}
}
}
}
}

//cauta un element dupa cheia nr_matricol


//in cazul in care nu este gasita nici o inregistrare este
//returnata o structura Student cu nr_matricol -1
Student Cauta(int nr_matricol, HashStudent hs)
{
//valoare de retur pentru cazurile in care nu este gasit elementul
Student s_negasit;
s_negasit.nr_matricol = -1;

if (nr_matricol<0)
return s_negasit;

if (hs.elem != NULL)
{
int index = HashFunction(nr_matricol, hs);
if (hs.elem[index] == NULL)
{
return s_negasit;
}
else
{
if (hs.elem[index]->inf.nr_matricol == nr_matricol)
return hs.elem[index]->inf;
else//coliziune
{
NodDate *t = hs.elem[index];
while (t != NULL && t->inf.nr_matricol != nr_matricol)
t = t->next;
if (t == NULL)
return s_negasit;
else
return t->inf;
}
}
}
//neinitializat sau nu exista inregistrarea
return s_negasit;
}

//dupa ce am cautat dupa nr matricol, daca acesta e gasit in tabela de dispersie se va afisa pe
ecran nr_matricol si numele studentului
void Afisare(Student s)
{
cout << "Nr_matricol: " << s.nr_matricol << endl;
cout << "Nume: " << s.nume << endl;
}

void main()
{
Student grupa[] = {
{ 1000, "Ion Vlad" },
{ 204, "Mihai Vlad" },
{ 406, "Dan Vlad" },
{ 305, "Lili Vlad" },
{ 1022, "Silviu Vlad" },
{ 1021, "Alina Vlad" },
{ 1030, "Sorin Vlad" },
{ 1032, "Titi Vlad" },
{ 1200, "Gigel Vlad" },
{ 2021, "Anca Vlad" },
{ 1230, "Maria Vlad" },
{ 1008, "Elena Vlad" }
};
HashStudent hs;

hs = AlocaMemorie();
// i<12
for (int i = 0; i<sizeof(grupa) / sizeof(Student); i++)
{
Insereaza(grupa[i], hs);
}
Afiseaza(hs);
int m;
//in m retin nr_matricol
cout << "Nr_matricol: ";
cin >> m;

while (m != -1)
{
Student rez = Cauta(m, hs);
if (rez.nr_matricol != -1)
Afisare(rez);
cout << "nr_matricol: ";
cin >> m;
}
Afiseaza(hs);

_getch();
}

Creati o structura de tip tabela de dispersie, cheia de cautare va fi nr_matricol, dupa


nr_matricol sa se stearga inregistrari, sa se dezaloce memoria utilizata.

#include <conio.h>
#include <iostream>
using namespace std;

//structura de date stocata in tabela de dispersie


struct Student
{
int nr_matricol;
char nume[20];
};

void Afisare(Student s)
{
cout << "Nr_matricol: " << s.nr_matricol << endl;
cout << "Nume: " << s.nume << endl;
}

//elementele tabelei de dispersie


//pentru simplificarea codului s-a utilizat o structura
struct NodDate
{
NodDate *next;
Student inf;
};

//Cheia este nr_matricol studentului


struct HashStudent
{
int size;
NodDate ** elem;
};

//functie simpla de dispersie care utilizeaza operatorul modulo


//pentru a genera pozitia in tabela
int HashFunction(int cheie, HashStudent hs)
{
return cheie%hs.size;
};

//aloca memorie pentru structura si initializeaza cu NULL valorile


HashStudent AlocaMemorie()
{
HashStudent hs;
hs.size = 101;
hs.elem = new NodDate*[hs.size];
for (int i = 0; i<hs.size; i++)
hs.elem[i] = NULL;
return hs;
}

//insereaza un element pe o pozitie generata de functia de dispersie


//pe baza valorii matricolei din structura
int Insereaza(Student s, HashStudent hs)
{
int index = -1;

if (s.nr_matricol<0)
return index;

if (hs.elem != NULL)
{
index = HashFunction(s.nr_matricol, hs);
//prima inregistrare
NodDate *nod_nou = new NodDate;
nod_nou->next = NULL;
nod_nou->inf = s;

if (hs.elem[index] == NULL)
{
hs.elem[index] = nod_nou;
}
else //coliziune
{
NodDate *t = hs.elem[index];
while (t->next != NULL) t = t->next;
t->next = nod_nou;
}
}
return index;
}

//cauta un element dupa cheia nr_matricol


//in cazul in care nu este gasita nici o inregistrare este
//returnata o structura Student cu nr_matricol -1
Student Cauta(int nr_matricol, HashStudent hs)
{
//valoare de retur pentru cazurile in care nu este gasit elementul
Student s_negasit;
s_negasit.nr_matricol = -1;

if (nr_matricol<0) return s_negasit;

if (hs.elem != NULL)
{
int index = HashFunction(nr_matricol, hs);
if (hs.elem[index] == NULL)
{
return s_negasit;
}
else
{
if (hs.elem[index]->inf.nr_matricol == nr_matricol)
return hs.elem[index]->inf;
else//coliziune
{
NodDate *t = hs.elem[index];
while (t != NULL && t->inf.nr_matricol != nr_matricol)
t = t->next;
if (t == NULL)
return s_negasit;
else
return t->inf;
}
}
}
//neinitializat sau nu exista inregistrarea
return s_negasit;
}

//functie recursiva care elibereaza memoria ocupata de nodurile listei


void ElibereazaMemorieLista(NodDate *&inceput)
{
if (inceput == NULL)
return;
else
{
ElibereazaMemorieLista(inceput->next);
cout << "Eliminat nodul cu codul: " << inceput->inf.nr_matricol << endl;
delete inceput;
}
}

//elibereaza memoria ocupata de tabela de dispesie


void dezalocHashStudent(HashStudent hs)
{
if (hs.elem != NULL)
{
for (int i = 0; i<hs.size; i++)
ElibereazaMemorieLista(hs.elem[i]);
delete[] hs.elem;
}
}

//Sterge elementul al carui nr_matricol coincide cu nr_matricol trimis ca parametru


//returneaza pozitia din tabela de unde a fost eliminat elementul
//sau -1 in cazul in care nu exista elementul cu cheia data
int Sterge(int nr_matricol, HashStudent hs)
{
if (nr_matricol<0)
return nr_matricol;

if (hs.elem != NULL)
{
int index = HashFunction(nr_matricol, hs);
if (hs.elem[index] == NULL)
{
return -1;
}
else
{
//este primul
if (hs.elem[index]->inf.nr_matricol == nr_matricol)
{
if (hs.elem[index]->next == NULL)
{
delete hs.elem[index];
hs.elem[index] = NULL;
}
else//mai sunt si alte elemente in lista
{
NodDate *t = hs.elem[index];
hs.elem[index] = t->next;
delete t;
}
}
else//coliziune, nu este primul, il cautam
{
NodDate *t = hs.elem[index];
while (t->next != NULL && t->next->inf.nr_matricol !=
nr_matricol)
t = t->next;
if (t->next == NULL)
return -1;
else//t->next->inf.nr_matricol == nr_matricol
{
NodDate *p = t->next;
if (p->next == NULL)
{
t->next = NULL;
delete p;
}
else
{
t->next = p->next;
delete p;
}
}
}
return index;
}
return -1;
}
}

//Afiseaza continutul tabelei de dispersie


void Afiseaza(HashStudent hs)
{
if (hs.elem != NULL)
{
for (int i = 0; i<hs.size; i++)
{
if (hs.elem[i] != NULL)
{
NodDate *t = hs.elem[i];
while (t != NULL)
{
cout << "S-a inserat in pozitia: " << i << " cheia: " << t-
>inf.nr_matricol << endl;
t = t->next;
}
}
}
}
}

void main()
{
Student grupa[] = {
{ 1000, "Ion Vlad" },
{ 204, "Mihai Vlad" },
{ 406, "Dan Vlad" },
{ 305, "Lili Vlad" },
{ 1022, "Silviu Vlad" },
{ 1021, "Alina Vlad" },
{ 1030, "Sorin Vlad" },
{ 1032, "Titi Vlad" },
{ 1200, "Gigel Vlad" },
{ 2021, "Anca Vlad" },
{ 1230, "Maria Vlad" },
{ 1008, "Elena Vlad" }
};
HashStudent hs;

hs = AlocaMemorie();

for (int i = 0; i<sizeof(grupa) / sizeof(Student); i++)


{
Insereaza(grupa[i], hs);
}
Afiseaza(hs);
int m;
cout << "Nr_matricol: ";
cin >> m;

while (m != -1)
{

Student rez = Cauta(m, hs);


if (rez.nr_matricol != -1) Afisare(rez);
cout << "Nr_matricol: ";
cin >> m;
}
Sterge(1008, hs);
Sterge(406, hs);
Sterge(305, hs);
Afiseaza(hs);
dezalocHashStudent(hs);

_getch();
}

AlocareMemorie-se aloca memorie mai intai pentru vectorul de liste, apoi pentru fiecare
element din vector, toate elementele din vector sunt nule.

**ele
m
NULL NULL
hs.elem[0] hs.elem[1]

TOATE elementele vectorului sunt nule!

hs HashStudent (are o dimensiune si un


vector de liste->lista contine informatia
de tip student si pointer next pt
urmatorul nod)

hs.size=2

hs.elem=new NodData*[hs.size]

Insereaza (inserare din structura de tip student(student s) in tabela de dispersie


hs(HashStudent hs)

->returneaza index-ul fiecarui element.

->daca avem o tabela de dispersie in care avem elemente (hs.elem!=NULL ->adresa la care
se afla tabela de dispersie):

-se calculeaza index-ul pt elementul pe care vrem sa-l inseram nr_matricol%hs.size

exemplu: nr_matricol=101 =>index =101%2=1

info
nod_nou

next

NULL
nod_nou->info=s;

nod_nou->next=NULL;
nod_nou

next
NULL

->punem nodul in vectorul de liste in functie de index, ex index =1.

hs.elem

hs.elem[index] (index=1) (adresa )


hs.elem[index]

nod_n hs.elem[index]==NULL (nu avem nimic acolo) =>punem nodul nou


hs.elem[index]=nod_nou(are adresa la care se afla nod_nou)
s

next
NULL

nr_matricol=105 => index=105%2=1 ,mai avem ceva la index 1 =>COLIZIUNE

nod_nou
s

next

NULL

=>se creeaza un nod t care va avea adresa la care se afla hs.elem[index]->hs.elem[1]

hs.ele

hs.elem[index=1] hs.elem[index=2]

next

t
nod_nou

nod_no
t->next!=NULL =>

t->next=nod_nou next
s

next

Afisare:

Verifica daca hs.elem nu este nula, adica avem o adresa.

Se parcurg elementele din vectorul de liste, size=2 =>i =0 la 1

Verifica daca in fiecare element al vectorului avem ceva (hs.elem[i]!=NULL)

Daca avem:

creaza un nod t in care pune hs.elem[i](adresa la care se afla nodul care contine inregistrare),
t!=NULL => afiseaza si nodul t va fi urmatorul din lista, daca t->next=NULL, adica nu mai
avem alt nod in lista respectiva, t=NULL si trece la urmatorul element.
Cauta:

imi cauta un student s, intr-o structura de tip HashStudent si returneaza studentul

->calculeaza index-ul si verifica daca in index=ul respectiv e vreun element, daca nu e ,


atunci => nu s-a gasit studentul

->daca e ceva in index, compara nr_matricol din informatia nodului cu nr_matricol introdus de
la tastatura( retinut in m)

daca se potriveste => returneaza hs.elem[index]->info

daca nu, verifica urmatorul nod din lista (il pune pe hs.elem[index] intr-un nod t si il verifica pe
t->next)

cat timp t->info.nr_matricol!=NULL si t!=NULL , se pozitioneaza pe urmatorul nod si verifica


daca acolo e nr_matricol cautat

daca l-a gasit , il afiseaza.

sterge dupa nr_matricol din tabela de dispersie

calculeaza index-ul si verifica daca exista vreun element acolo

daca este si hs.elem[index]->info.nr_matricol==nr_matricol (coincide nr matricol)

verifica daca mai are vreun nod care se leaga de el, daca nu are, il sterge si face elem din
indexul respectiv 0

daca are, il pune intr-un nod t, t->next va fi ce urma dupa el in lista,

daca nu e primul nod din indexul respectiv, avem coliziune si trebuie sa-l cautam in lista, pune
intr-un nod t, primul element din lista,daca nu se potriveste cu nr_matricol si mai are inca un
nod dupa el, il face pe el t

verifica mereu daca nodul mai are ceva dupa el.


hs.elem

hs.elem[index=1] hs.elem[index=2]
hs.elem[index=3]

200300
info info
100 info
400 info
next
next
next
next
NULL NULL
verifica daca
hs.elem[index]-
>info.nr_matricol
==nr_matricol

daca DA => verifica daca


mai are vreun nod legat de
el

(nu are =>sterge), iar


hs.elem[index]=NULL

Sterg nodul cu matricol 100.

sterg nodul cu matricol 400


hs.elem

hs.elem[index=1] hs.elem[index=2]
hs.elem[index=3]
t

t->next=p-
200 info >next

next

p
300 info

next

400 info

next NULL hs.elem


il stergem cel cu 400

hs.elem[index=1] hs.elem[index=2]
hs.elem[index=3]

200 info t

next
p

400 info

next NULL

S-ar putea să vă placă și