Cod sursa(job #708559)

Utilizator vlad.doruIon Vlad-Doru vlad.doru Data 6 martie 2012 22:11:11
Problema Hashuri Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include <fstream>
#include <cmath>
#include <cstdlib>
#define NA -1
#define FREE 0

using namespace std;

ifstream in("hashuri.in");
ofstream out("hashuri.out");

int prime[]={7, 23, 79, 1087, 66047, 263167,1000003, 2097593, 16785407, 1073807359};
int prime_size=9;
/*lista de numere prime pentru a alege numarul prim potrivit pentru functii de hash in functie de dimensiunea hashului*/
//Lista de numere prime poate fi citita si dintr-un fisier text pregenerat;

int find_prim(int x); // cauta binar numarul prim din lista mai mare decat x;

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:
	void generate(int prim,int h_size);
	int evaluate(int x);
};

void hash_function::generate(int prim,int h_size){
	this->p=prim;
	this->m=h_size;
	this->a=(rand())%(this->p);
	while(this->a==0) // ne asiguram ca a e diferit de 0
		this->a=(rand())%(this->p);
	this->b=(rand())%(this->p);
	return;
}

int hash_function::evaluate(int x){
	int value;
	value=((a*x+b)%p)%m;
	return value;
}

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(int hash_size);
	~hash();
	int find(int value);
	void erase(int value);
	bool insert(int value); // returneaza 1 daca insereaza cu succes si 0 fara succes ceea ce implica refacerea hashului
};

hash::hash(int hash_size){
	this->size=hash_size;
	this->h=new int[this->size];
	this->p=find_prim(hash_size);
	this->h1.generate(this->p,this->size - 1);
	this->h2.generate(this->p,this->size - 1);
}

hash::~hash(){
	delete[] this->h;
}

int hash::find(int value){
	int locate1=this->h1.evaluate(value),locate2=this->h2.evaluate(value);
	if(h[locate1]==value)
		return locate1;
	if(h[locate2]==value)
		return locate2;
	return NA;
}

void hash::erase(int value){
	int location=find(value);
	if(location!=NA)
		h[location]=FREE;
}		

bool hash::insert(int value){
	int aux,ant=value,location1,location2,explorated=0,upper_bound=floor(log((double)size));
	location1=h1.evaluate(value);
	if(h[location1]==FREE){
		h[location1]=value;
		return true;
	}
	else{
		aux=h[location1];
		h[location1]=value;
		explorated++;
	}
	while(explorated<upper_bound){
		location1=h1.evaluate(aux);
		location2=h2.evaluate(aux);
		if(h[location2]==ant){
			if(h[location1]==FREE){
				h[location1]=value;
				return true;
			}
			else{
				ant=aux;
				aux=h[location1];
				h[location1]=ant;
				explorated++;
			}
		}
		else{
			if(h[location2]==FREE){
				h[location2]=value;
				return true;
			}
			else{
				ant=aux;
				aux=h[location2];
				h[location2]=ant;
				explorated++;
			}
		}
	}
	return false;
}
	

int main(){
	hash H(1000000);
	int operations,value,opcode;
	in>>operations;
	for(int i=1;i<=operations;++i){
		in>>opcode>>value;
		if(opcode==1)
			H.insert(value);
		if(opcode==2)
			H.erase(value);
		if(opcode==3)
			if(H.find(value)==NA)
				out<<"0\n";
			else
				out<<"1\n";
	}
	return 0;
}

int find_prim(int x){
	int i,pas;
	for(pas=1;pas<=prime_size;pas<<=1);
	for(i=0;pas;pas>>=1){
		if(i+pas<prime_size && prime[i+pas]<=x)
			i+=pas;
	}
	return prime[i+1]; // returnam cel mai mic numar prim mai mare decat x din lista de prime
}