Cod sursa(job #716917)

Utilizator Marius_mFMI-M2 Marius Melemciuc Marius_m Data 19 martie 2012 13:29:28
Problema Hashuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.09 kb
#include<cstdio>
#include<iostream>
#define subunitar 0.618                                                  // aproximarea numarului sugerat de Donald Knuth
#define m 1048576                                             // pow(2,20)
#define POSITIVE(a)  (a>=0) ? a : a+prim                           // pentru a afla pozitia in cadrul hash-ului a numerelor negative
#define prim 1000003

using namespace std;

class Hash
{
	typedef struct nod {int info;
						nod* back;
						nod* next;}NOD;                            // folosesc liste liniare dublu inlantuite                                                        // coliziunile se rezolva cu chaining
	typedef NOD* PNOD;
	PNOD *v,p,r;
public:
	Hash()                                                // constructor
	{
		v=new PNOD[prim];
		for(int i=0;i<prim;i++)                                       // initializam hash-ul reprezentat de vectorul v cu NULL in fiecare pozitie
			v[i]=NULL;
	}
	
	inline int h(int value)                                    // returneaza pozitia in cadrul vectorului v                                                              
	{
		//return (int)( m * ( value*subunitar-(int)(value*subunitar) ) );       // functie hash bazata pe metoda inmultirii
		//return value%prim;		                                                          // division method
		return (value+(prim*3)/7)%prim;                               	// Alqrainy's hash function  ,  sursa: internet                                                    	
	}

	int search_value(int value)                                // cautam elementul b in lista v[x]
	{
		register int x,k=0;
		x=h(value);                            //  x reprezinta pozitia in cadrul hash-ului,v[x] fiind lista asociata
		p=v[x];                                     
		while(p!=NULL&&k==0)
		{
			if(p->info==value)                               // daca gasim elementul b in lista v[x],k devine 1 si se iese din while
				k=1;
			r=p;                        // la cautarea cu succes,p este cu un pas in fata la iesire din bucla,iar r memoreaza adresa corecta,fiind cu un pas in urma lui p
			p=p->next;                              // p pointeaza catre urmatorul element al liste v[x]
		}
		return k;                          
	}

	int insert(int value)            // returneaza 1 daca s-a facut inserarea,elementul nu se afla deja in hash,si 0 daca inserarea nu a avut loc,adica elementul se afla deja in hash
	{
		register int x=h(value);                             //  x reprezinta pozitia in cadrul hash-ului,v[x] fiind lista asociata
		p=v[x];
		if(search_value(value)==0)                                  // elementul care trebuie inserat nu se gaseste in hash
		{
			if(v[x]==NULL)                    // daca lista care incepe de la hash[x] e vida
			{
				v[x]=new NOD;
				v[x]->info=value;
				v[x]->next=NULL;
				v[x]->back=NULL;
			}
			else
			{
				p=v[x];
				while(p->next!=NULL)
					p=p->next;
				r=new NOD;
				r->info=value;
				r->next=NULL;
				r->back=p;
				p->next=r;
			}
			return 1;
		}
		return 0;
	}

	int delete_value(int value)             // returneaza 1 daca elementul s-a gasit in hash si s-a sters,returneaza 0 daca elementul nu este in hash
	{
		register int x=h(value);
		p=v[x];               
		if(search_value(value)==1)                               // elementul care trebuie sters se gaseste in lista v[x]
		{
			if(r==v[x])                   // daca elementul care trebuie sters este primul element din lista v[x]
			{
				PNOD s;
				s=v[x];                    // s memoreaza locatia primului element din lista v[x],care trebuie sters din memorie
				v[x]=v[x]->next;
				if(v[x]!=NULL)            //verificam daca este unicul element al listei v[x],caz in care dupa eliminare,lista devine vida,v[x] fiind NULL
					v[x]->back=NULL;             // daca nu este singurul element al listei v[x],v[x]->back va deveni NULL
				delete s;                         // eliberam memoria in care se afla elementul eliminat din lista
			}
			else
			{
				p=r->back;                            // p reprezinta elementul de inainte celui care trebuie sters
				p->next=r->next;                         // schimbam legaturile
				if(r->next!=NULL)                       // verificam daca elementul care trebuie sters este ultimul din lista v[x]
					r->next->back=p;
				delete r;                       // eliberam memoria in care se afla elementul eliminat din lista
			}
			return 1;
		}
		return 0;
	}
	
	~Hash()                                      // destructor in care sterg din memorie vectorul v,care a fost alocat dinamic cu new
	{
		delete [] v;
	}
};


int main()
{
	Hash H;                                       // H este un obiect al clasei Hash
	register int N,i,a,b;                          // N reprezinta numarul de comenzi din fisierul de intrare
	FILE *in,*out;
	in=fopen("hashuri.in","r");
	out=fopen("hashuri.out","w");
	fscanf(in,"%d",&N);
	for(i=1;i<=N;i++)
	{
		fscanf(in,"%d %d",&a,&b);                        // a reprezinta tipul comenzii,b numarul citit
		if(a==1)
			H.insert(b);
		else
			if(a==2)
				H.delete_value(b);
			else
				if(a==3)
					fprintf(out,"%d\n",H.search_value(b));
	}
	fclose(in);
	fclose(out);
	return 0;
}