Cod sursa(job #282003)

Utilizator tomescu_alinTomescu Alin tomescu_alin Data 16 martie 2009 18:46:12
Problema Hashuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 7.06 kb
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;

typedef unsigned char byte;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ulonglong;

#define NDEBUG

#ifdef NDEBUG
#define dbg	0 && (*((ostream *) 0))
#else
#define dbg clog
#endif

template<class T> class LinkedList;

template<class T>
class ListNode {
	public:
		ListNode(T data = T(), ListNode * next = 0)
			:	_data(data), _next(next) {
			
		}
		
		const ListNode<T> * next() const { return _next; }
		T data() const { return _data; }
	
	public:
		friend class LinkedList<T>;		
		
	private:
		T _data;
		ListNode * _next;
};

template<class T>
class LinkedList {
	public:
		LinkedList()
			:	_head(new ListNode<T>()), _tail(_head), _size(0)
		{}
		
	public:
		void append(T data) {
			ListNode<T> * newNode = new ListNode<T>(data);
			_tail->_next = newNode;
			_tail = newNode;
			_size++;
		}
		
		bool find(T data) const {
			ListNode<T> * traveler = _head->_next;
			
			
			while(traveler) {
				if(data == traveler->_data) {
					return true;
				}
				traveler = traveler->_next;
			}
			
			return false;
		}
		
		bool erase(T data) {
			ListNode<T> * traveler = _head->_next, * previous = _head;			
			
			while(traveler) {
				if(data == traveler->_data) {
					if(traveler == _tail) {
						_tail = previous;
					}
					previous->_next = traveler->_next;
					_size--;
					delete traveler;
					return true;
				}
				previous = traveler;
				traveler = traveler->_next;				
			}
			return false;
		}
		
		ulong size() const { return _size; }
		
	public:	
		friend ostream& operator << (ostream& out, const LinkedList<T>& list) {
			const ListNode<T> * traveler = list._head->next();
			
			out << "Linked list of size " << list._size << ": ";
			
			while(traveler) {
				out << traveler->data() << " ";
				traveler = traveler->next();
			}
			return out;
		}
		
	private:
		//ListNode<T> * getTravelerToEnd() { return _tail; }
		
	private:
		ListNode<T> * _head;
		ListNode<T> * _tail;
		ulong _size;
};

namespace Global {
	const ulong hashPrime1 = 600001;
	const ulong hashPrime2 = 393241;
	
	ulong random;
	
	LinkedList<ulong> hashList1[hashPrime1];
	LinkedList<ulong> hashList2[hashPrime2];
	
	inline ulong hashNumber(ulong number, ulong prime) {
		return (number * random) % prime;
	}
}

class HashTable {
	public:
		HashTable(LinkedList<ulong> * hashTable, ulong prime) 
			:	_hashTable(hashTable), _hashPrime(prime)
		{
		}
		
	public:
		//	Adds the value to the list, returns false if the value is already in the list, and false otherwise
		void add(ulong value) {
			ulong hash = Global::hashNumber(value, _hashPrime);
			if(!_hashTable[hash].find(value)) {
				_hashTable[hash].append(value);
			}
		}
		bool find(ulong value) {
			ulong hash = Global::hashNumber(value, _hashPrime);
			return _hashTable[hash].find(value);
		}
		bool erase(ulong value) {
			ulong hash = Global::hashNumber(value, _hashPrime);
			return _hashTable[hash].erase(value);
		}
		
		
	public:
		friend ostream& operator << (ostream& out, const HashTable& hashTable) {			
			out << "HashTable Modulo " << hashTable._hashPrime << endl;
			
			for(uint i = 0; i < hashTable._hashPrime; i++) {
				if(hashTable._hashTable[i].size()) {
					out << "List Modulo " << i << " | " << hashTable._hashTable[i] << endl;
				}
			}
			
			return out;
		}
		
		public:
			ulong getHashPrime() const { return _hashPrime; }
			LinkedList<ulong> * getLinkedList() { return _hashTable; }
		
	private:
		LinkedList<ulong> * _hashTable;
		ulong _hashPrime;
};

class DoubleHashTableManager {
	public:
		DoubleHashTableManager(HashTable& first, HashTable& second) 
			:	_first(first), _second(second)
		{
			_firstHashPrime = _first.getHashPrime();
			_firstHashTable = _first.getLinkedList();
			_secondHashPrime = _second.getHashPrime();
			_secondHashTable = _second.getLinkedList();
		}
		
	public:
		void add(ulong value) {
			ulong firstHash = Global::hashNumber(value, _firstHashPrime);
			ulong secondHash = Global::hashNumber(value, _secondHashPrime);
			
			
			if(!_firstHashTable[firstHash].find(value) && !_secondHashTable[secondHash].find(value)) {
				if(_firstHashTable[firstHash].size() < _secondHashTable[secondHash].size()) {
					_firstHashTable[firstHash].append(value);
				} else {
					_secondHashTable[secondHash].append(value);
				}
			}
		}
		bool find(ulong value) {
			ulong firstHash = Global::hashNumber(value, _firstHashPrime);
			ulong secondHash = Global::hashNumber(value, _secondHashPrime);
			
			if(_firstHashTable[firstHash].find(value))
				return true;			
			if(_secondHashTable[secondHash].find(value))
				return true;
			
			return false;
		}
		bool erase(ulong value) {
			ulong firstHash = Global::hashNumber(value, _firstHashPrime);
			ulong secondHash = Global::hashNumber(value, _secondHashPrime);
			
			if(_firstHashTable[firstHash].erase(value))
				return true;
			if(_secondHashTable[secondHash].erase(value))
				return true;
			
			return false;
		}
		
	private:
		HashTable& _first;
		HashTable& _second;
		
		LinkedList<ulong> * _firstHashTable, * _secondHashTable;		
		ulong _firstHashPrime, _secondHashPrime;
};
void testLinkedList() {
	LinkedList<ulong> newList;
	
	ulong vect[] = {4, 10, 5, 11};
	ulong size = sizeof(vect)/sizeof(vect[0]);
	for(uint i = 0; i < size; i++) {
		newList.append(vect[i]);
	}
	
	cout << newList << endl;
	
	for(uint i = 0; i < size; i++) {
		cout << "Found " << vect[i] << ": " << newList.find(vect[i]) << endl;
	}
	
	for(uint i = 0; i < size; i++) {
		ulong toFind = vect[i]*4;
		cout << "Found " << toFind << ": " << newList.find(toFind) << endl;
	}
	
	for(uint i = 0; i < size; i++) {
		if(vect[i]%2 == 1) {
			newList.erase(vect[i]);
		}
	}
	
	cout << newList << endl;
	
	for(uint i = 0; i < size; i++) {
		newList.append(vect[i]);
	}
	
	cout << newList << endl;
}

int main(int argc, char * argv[]) {
	#ifndef NDEBUG
		testLinkedList();		
	#endif
	
	srand(time(0));
	Global::random = rand() % 770;
	
	const char * inFile = "hashuri.in";
	const char * outFile = "hashuri.out";
	
	ifstream fin(inFile);
	ofstream fout(outFile);
	
	#ifndef NDEBUG
		if(!fin || !fout) {
			cerr << "Error opening one of \"" << inFile << "\" or \"" << outFile << "\"" << endl;
			return -1;
		}
	#endif
	
	ulong n, operation, param;
	fin >> n;
	
	HashTable hashTable1(Global::hashList1, Global::hashPrime1);
	HashTable hashTable2(Global::hashList2, Global::hashPrime2);
	DoubleHashTableManager hashTable(hashTable1, hashTable2);
	
	for(ulong i = 0; i < n; i++) {
		fin >> operation >> param;
		switch(operation) {
			case 1:
				hashTable.add(param);
				break;
			case 2:
				hashTable.erase(param);
				break;
			case 3:
				fout << static_cast<ulong>(hashTable.find(param)) << endl;
				break;
		}
	}
	
	fout.close();
	fin.close();
	
	return 0;

}