Cod sursa(job #719667)

Utilizator mr.johnFMI - Laceanu Ionut-Adrian mr.john Data 21 martie 2012 22:42:56
Problema Hashuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.92 kb
//Laceanu Ionut-Adrian
//Double Hashing cu Template
//F.M.I., gr.135

#include <stdio.h>
#include <fstream>
#define MOD 1022467
#define MOD2 1022449

using namespace std;


template <class MyType> //clasa functioneaza pentru stringuri si pentru orice tip de date
class hash{		// care poate fi convertit la int prin cast. Deasemenea, MyType trebuie
	MyType *T; // sa suporte testul de egalitate (==)
	char *sters;
	char *ocupat;

	unsigned int h(MyType,int); // functia h este private, deoarece va fi apelata doar de metodele
	                            // insert, query si remove
public:
	hash(){
		T=new MyType[MOD];
		sters=new char[MOD];
		ocupat=new char[MOD];
		for (int i=0;i<MOD;i++){
			T[i]=0;
			sters[i]=0;
			ocupat[i]=0;
		}
	}
	~hash(){
		delete[] T;
		delete[] sters;
		delete[] ocupat;
	}
		
	int query(MyType x){
		int t;
		for(int i=0;;i++){
			t=h(x,i);                   //self-explanatory
			if (ocupat[t]==0) return 0;
			if (T[t]==x && !sters[t]) return 1;
		}
		return 0;
	}
	unsigned int insert(MyType x){
		unsigned int i,temp,j;
		for (i=0;temp=h(x,i), ocupat[temp]&&(T[temp]!=x||sters[temp])&&(i<MOD2); i++); //parcurgem tabela pana
		if (T[temp]==x && ocupat[temp]) return -1;      //gasim elementul sau o pozitie
		for (j=0;ocupat[h(x,j)]&&!sters[h(x,j)];j++);   //libera, unde il vom insera.
		T[h(x,j)]=x;
		sters[h(x,j)]=0;
		ocupat[h(x,j)]=1;
		return h(x,j);		//va returna pozitia in care s-a inserat sau, in caz de esec, -1
	}
	unsigned int remove(MyType x){
		unsigned int temp;
		for(int i=0;;i++){        //parcurgem tabela pana cand fie gasim elementul, pe care il inlocuim cu -1
			temp=h(x,i);             //fie gasim o pozitie neocupata, ceea ce inseamna ca elementul nu se afla in tabela. 
			if (!ocupat[temp]) return -1;
			if (T[temp]==x && !sters[temp]){
				sters[temp]=1;
				return temp;      //returneaza pozitia pe care se afla elementul sau, in caz de esec, -1
			}
		}
	}
};


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

template<> 
unsigned int hash<char *>::h(char *str, int i){ 
	unsigned int x = 5381;	// aceasta functie este specializata pentru stringuri
	int c;
	while ((c = *str++))
		x = ((x << 5) + x) + c; 
	return (((x%MOD)+i*(1+x%MOD2))%MOD);
}

int main(){
	int n;
	hash<unsigned int> has;
	freopen("hashuri.in","r",stdin);
	freopen("hashuri.out","w",stdout);
	unsigned int op,nr;
//	float x;
//	char c[30];
	scanf("%d %d",&n);
//	printf("%d\n",has.h(33968011,12542));
	for (register int i=1;i<=n;i++){
		scanf("%d %d",&op,&nr);
//		fin.getline(c,300);
		if (op==1){ has.insert(nr); continue;}
		if (op==2){ has.remove(nr); continue;}
		if (op==3) printf("%d\n",has.query(nr));
	}
	return 0;
}