Pagini recente » Cod sursa (job #1480135) | Cod sursa (job #2318390) | Cod sursa (job #1002587) | Cod sursa (job #376934) | Cod sursa (job #716071)
Cod sursa(job #716071)
// Ion Vlad-Doru, Grupa 135, Facultatea de Matematica si Informatica
// Cuckoo Hashing, Programare Orientata pe Obiecte
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdlib>
#define NA -1
#define FREE 0
using namespace std;
const int PRIM=1073807359; // numarul prim mare folosit la evaluarea functiilor de hash random
class hash_function{ // h(x)=((a*x+b)%p)%m unde a si b sunt random si a!=0
int a,b,p,m;
public:
bool generate(int prim,int h_size); // genereaza valorile a si b primind p si m
int evaluate(int x); // evalueaza functia in punctul intreg x
};
bool hash_function::generate(int prim,int h_size){
this->p=prim;
this->m=h_size;
this->a=(rand())%(this->m);
while(this->a==0) // ne asiguram ca a e diferit de 0
this->a=(rand())%(this->m);
this->b=(rand())%(this->m);
if(a!=0 && b<=m && a<=m)
return true;
return false;
}
int hash_function::evaluate(int x){
long long value; // intram pe long long
value=(long long)((long long)a*(long long)x+(long long)b);
value%=p;
value%=m;
return (int)value;
}
template <class T>
class hash{
int size; // dimensiunea hashului
int *h; // vom aloca dinamic un vector h de dimensiune size
int p; // p numar random folosit pentru functiile de hash
hash_function h1,h2;
public:
hash<T>(int hash_size);
~hash();
int find(T value);
bool erase(T value);
bool insert(T value); // returneaza 1 daca insereaza cu succes si 0 fara succes ceea ce implica refacerea hashului
};
template <class T>
hash<T>::hash(int hash_size){
this->size=hash_size*3; // aloc de doua ori numarul maxim de elemente ce se vor gasi in hash in acelasi timp deoarece fiecare element are doua valori de hashing asociate
this->h=new T[this->size];
for(int i=0;i<size;++i) // initializam tabelul cu FREE peste tot
h[i]=FREE;
this->p=PRIM;
this->h1.generate(this->p,this->size); // generez functiile random
this->h2.generate(this->p,this->size);
}
template <class T>
hash<T>::~hash(){
delete [] this->h; // sterg zona alocata dinamica in hash
}
template <class T>
int hash<T>::find(T value){ // caut valoarea value in una din cele doua pozitii posibile;
int location1=this->h1.evaluate(value),location2=this->h2.evaluate(value);
if(h[location1]==value)
return location1;
if(h[location2]==value)
return location2;
return NA;
}
template <class T>
bool hash<T>::erase(T value){ // eliberez locatia ocupata de value daca exista si returnez 1 daca eliberez si 0 altfel
int location=find(value);
if(location!=NA){
h[location]=FREE;
return true;
}
return false;
}
template <class T>
bool hash<T>::insert(T value){ // inserez valuarea value in tabel
int location1,location2,explorated=0,upper_bound=(int)log((double)size);
T aux,ant=value;
location1=h1.evaluate(value); // location1=h1(value)
if(find(value)!=NA) // daca e deja inserat atunci iesim din metoda
return true;
if(h[location1]==FREE){ // daca prima locatie e libera il inseram in hash
h[location1]=value;
return true;
}
else{ //altfel scoatem ce se afla in hash pe prima locatie si punem elementul curent pe prima sa locatie
aux=h[location1];
h[location1]=value;
explorated++;
}
while(explorated<=upper_bound){ // cat timp am scos mai putin de log(hash size) elemente executam
location1=h1.evaluate(aux);//calculam cele 2 pozitii posibile si ne uitam la ce diferita de pozitia de pe care elementul a fost scos
location2=h2.evaluate(aux);
if(h[location2]==ant){ // elementul a fost scos de pe pozita data de h2 si il inseram pe pozitia data de h1
if(h[location1]==FREE){ // daca aceasta a doua pozitie e libera inseram elementul
h[location1]=aux;
return true;
}
else{ // altfel scoatem elementul de pe pozitia h1 si inseram elementul nostru
ant=aux;
aux=h[location1];
h[location1]=ant;
}
}
else{ // elementul a fost scos de pe pozitia data de h1
if(h[location2]==FREE){ //cazul se rezolva analog cu primul
h[location2]=aux;
return true;
}
else{
ant=aux;
aux=h[location2];
h[location2]=ant;
}
}
explorated++; // crestem numarul de elemente explorate
}
return false;
}
bool solve();
int main(){
while(!solve()); // daca e nevoie de rehashing refacem hashul
return 0;
}
bool solve(){
ifstream in("hashuri.in");
ofstream out("hashuri.out");
int operations,value,opcode;
bool ok=1;
in>>operations;
hash <int> H(operations); // declaram hashul necesar pentru un numar dat de operatii
for(int i=1;i<=operations;++i){
in>>opcode>>value;
if(opcode==1){
ok=H.insert(value);
if(!ok){
cout<<"E nevoie de rehashing";
in.close();
out.close();
return false;
}
continue;
}
if(opcode==2){
H.erase(value);
continue;
}
if(opcode==3){
if(H.find(value)==NA)
out<<"0\n";
else
out<<"1\n";
}
}
return true;
}