Cod sursa(job #716265)

Utilizator Marius_mFMI-M2 Marius Melemciuc Marius_m Data 18 martie 2012 15:28:43
Problema Hashuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.63 kb
#include<stdio.h>
#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
#define prim 1000003

using namespace std;

FILE *in,*out;
typedef struct nod {int info;
					nod *back,*next;}NOD;                            // folosesc liste liniare dublu inlantuite
NOD *v[m],*p,*r;                                                        // coliziunile se rezolva cu chaining
int a,b,x;

inline int hash(int x)                                                              
{
	//return (int)( m * ( x*subunitar-(int)(x*subunitar) ) );                      // functie hash bazata pe metoda inmultirii
	//int position=(int)( m * ( x*subunitar-(int)(x*subunitar) ) );
	//return position>=0 ? position : position+prim; 
    //return POSITIVE(position);
    //return x%prim;		                                                          // division method
	return POSITIVE((x+(prim*3)/7)%prim);                                                    // Alqrainy's hash function  ,  sursa: internet                                                    	
}

void insert()
{
	int k=0;
	p=v[x];
	while(p!=NULL&&k==0)                                 // caut elementul b in lista v[x] 
	{
		if(p->info==b)
			k=1;                                              // daca il gasesc,k devine 1 si se iese fortat din while
		p=p->next;                                       // se trece la urmatorul element al listei v[x]
	}
	if(k==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=b;
			v[x]->next=NULL;
			v[x]->back=NULL;
		}
		else
		{
			p=v[x];
			while(p->next!=NULL)
				p=p->next;
			NOD *r;
			r=new NOD;
			r->info=b;
			r->next=NULL;
			r->back=p;
			p->next=r;
		}
	}
}

void delete_value()
{
	int k=0;                            // pointerul r este mereu cu un pas in urma lui p
	p=v[x];
	while(p!=NULL&&k==0)
	{
		if(p->info==b)	
			k=1;
		r=p;
		p=p->next;
	}
	if(k==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]
		{
			NOD *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
		}
	}
}

void search_value()                                // cautam elementul b in lista v[x]
{
	int k=0;
	p=v[x];                                     
	while(p!=NULL&&k==0)
	{
		if(p->info==b)                               // daca gasim elementul b in lista v[x],k devine 1 si se iese din while
			k=1;
		p=p->next;                              // p pointeaza catre urmatorul element al liste v[x]
	}
	fprintf(out,"%d\n",k);                          // scriem in fisier valoarea lui k,1 daca s-a gasit in lista v[x],0 in caz contrar
}

int main()
{
	int N,i,k;                                     // N reprezinta numarul de comenzi din fisierul de intrare
	in=fopen("hashuri.in","r");
	out=fopen("hashuri.out","w");
	fscanf(in,"%d",&N);
	for(i=0;i<m;i++)                                       // initializam hash-ul reprezentat de vectorul v cu NULL in fiecare pozitie
		v[i]=NULL;
	for(i=1;i<=N;i++)
	{
		fscanf(in,"%d %d",&a,&b);                        // a reprezinta tipul comenzii,b numarul citit
		x=hash(b);                                             // x reprezinta pozitia in cadrul hash-ului,v[x] fiind lista asociata
		if(a==1)
			insert();
		else
			if(a==2)
				delete_value();
			else
				if(a==3)
					search_value();
	}
	fclose(in);
	fclose(out);
	return 0;
}