Cod sursa(job #741451)

Utilizator SimeneSimene Robert Simene Data 26 aprilie 2012 01:36:38
Problema Hashuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.82 kb
//Double hashing with template without global variables Simene Robert Gr.135
//functia de hash  h(k, i ) = (h1(k) + i*h2(k))
#include <stdio.h>
#include <fstream>
#define prim_1 1015453
#define prim_2 1000003
using namespace std;
template <class H> //clasa pentru orice tip de date
class hash
{
	H *V;
	char *vector_verificari;//unde  verifican data e stres sau nu
	char *vector_ocupat;//unde vedem daca este ocupata o pozitie
    unsigned int h(H,int);// functia de hash

public:
	hash()
	{
		V=new H[prim_1];
		vector_verificari=new char[prim_1];
		vector_ocupat=new char[prim_1];
		for (int i=0;i<prim_1;i++)
		{
			V[i]=0;
			vector_verificari[i]=0;
			vector_ocupat[i]=0;
		}
	}
	~hash()
	{
		delete[] V;
		delete[] vector_verificari;
		delete[] vector_ocupat;
	}

	int f_find(H x)
	{
		int j;
		for(int i=0;;i++)//  parcurege  pana nu il gaseste adica vector ocupat[h(x,i)]=0 ori pana il gaseste
		{
			j=h(x,i);
			if (vector_ocupat[j]==0) return 0;
			if (V[j]==x && !vector_verificari[j]) return 1;
		}
		return 0;
	}
	unsigned int f_insert(H x)
	{
		unsigned int i,t,j;
		for (i=0;t=h(x,i), vector_ocupat[t]&&(V[t]!=x||vector_verificari[t])&&(i<prim_2); i++); //parcurge pana fie il gaseste fie il insereaza
		if (V[t]==x && vector_ocupat[t]) return -1;
		for (j=0;vector_ocupat[h(x,j)]&&!vector_verificari[h(x,j)];j++);
		V[h(x,j)]=x;
		vector_verificari[h(x,j)]=0;
		vector_ocupat[h(x,j)]=1;
		return h(x,j);
	}
	unsigned int f_erase(H x)
	{
		unsigned int t;
		for(int i=0;;i++)
		{        //parcurge tabela  pana cand  gaseste elementul de sters sau returneaza unu in cazul in care ajunge la sfarsit si nu l-a gasit
			t=h(x,i);
			if (!vector_ocupat[t]) return -1;
			if (V[t]==x && !vector_verificari[t])
			{
				vector_verificari[t]=1;
				return t;
			}
		}
	}
};


template<class H>
unsigned int hash<H>::h(H x, int i) //functia de hash valabila pentru orice tip de date
{
	int parte_int =(int)x;
	int parte_fract=int(1000*(x-parte_int ));
	return ((((parte_int +parte_fract)%prim_1)+i*(1+(parte_int +parte_fract)%prim_2))%prim_1); // care poate fi convertit la int prin operatorul cast
}

template<>
unsigned int hash<char *>::h(char *str, int i)
{
	unsigned long  x = 5381;	//O metoda a algoritmului lui Dan Bernstein prin care calculez valuarea de hash pentru stringuri http://www.cse.yorku.ca/~oz/hash.html
	int c;
	while ((c = *str++))
		x = ((x << 5) + x) + c;
	return (((x%prim_1)+i*(1+x%prim_2))%prim_1);
}

int main()
{
	int n;
	hash<unsigned int> hash_1;
	freopen("hashuri.in","r",stdin);
	freopen("hashuri.out","w",stdout);
	unsigned int op,nr;
	scanf("%d",&n);
	for (register int i=1;i<=n;i++){
		scanf("%d %d",&op,&nr);
		if (op==1) hash_1.f_insert(nr);
		if (op==2) hash_1.f_erase(nr);
		if (op==3) printf("%d\n",hash_1.f_find(nr));
	}
	return 0;
}