Cod sursa(job #1864136)

Utilizator Stefanescu_MihaiStefanescu Mihai-Nicolae Stefanescu_Mihai Data 31 ianuarie 2017 15:34:48
Problema Heapuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 6.06 kb
#include <fstream>

template <class type>
class Heap	//	all functions returning 0 on success, 1 on failure
{
protected:
	type *v;	//	indexing from 1
	int *heapToKey;
	int *keyToHeap;
	int numElem;
	int capacity;
	bool trackKeys;
	
	bool (*comp)(const type&, const type&);
	static bool basicMinComp(const type &a, const type &b)
	{
		return a < b;
	}
	//	compFunction(a, b) returns 1 if the first arg should be placed closer to the top than the second; defaults to basic '<' operator
	//	if using keys, each key must be unique to a pushed node and each key must be lower or equal to the heap's capacity
public:
	Heap(int maxSize, bool keepTrackOfKeys = 0, bool (*compFunction)(const type&, const type&)=NULL)
	{
		if (compFunction == NULL)
			comp = this->basicMinComp;
		else
			comp = compFunction;
		trackKeys = keepTrackOfKeys;
		numElem = 0;
		capacity = maxSize;
		v = NULL;
		heapToKey = NULL;
		keyToHeap = NULL;
		try
		{
			v = new type[capacity+1];
		}
		catch (std::bad_alloc&)
		{
			throw;
			//	???
		}
		if (trackKeys)
		{
			try
			{
				heapToKey = new int[capacity+1];
				keyToHeap = new int[capacity+1];
				
			}
			catch (std::bad_alloc&)
			{
				throw;
				//	???
			}
			for (int i = 0; i <= capacity; ++i)
				heapToKey[i] = keyToHeap[i] = -1;
		}

	}
	~Heap()
	{
		if (v)
			delete [] v;
		if (heapToKey)
			delete [] heapToKey;
		if (keyToHeap)
			delete [] keyToHeap;
	}

	bool isTrackingKeys()
	{
		return trackKeys;
	}
	bool isEmpty()
	{
		return numElem <= 0;
	}
	int getNumElems()
	{
		return numElem;
	}

	//	n must be greater or equal to the number of elements currently in the heap
	bool setCapacity(int n)
	{
		if (n < numElem)
			return 1;	//	data loss if operation is executed

		type *newV;
		int *newHeapToKey = NULL, *newKeyToHeap = NULL;
		try
		{
			newV = new type[n+1];	//	indexing from 1
			if (trackKeys)
			{
				newHeapToKey = new int[capacity+1];
				newKeyToHeap = new int[capacity+1];
			}
		}
		catch (std::bad_alloc&)
		{
			return 1;	//	operation failed, but the old vectors remain unchanged
		}
		for (int i = 0; i <= numElem; ++i)
			newV[i] = v[i];
		if (trackKeys)
			for (int i = 0; i <= numElem; ++i)
			{
				newHeapToKey[i] = heapToKey[i];
				newKeyToHeap[i] = keyToHeap[i];
			}
		delete [] v;
		v = newV;
		if (trackKeys)
		{
			delete [] heapToKey;
			delete [] keyToHeap;
			heapToKey = newHeapToKey;
			keyToHeap = newKeyToHeap;
		}
		return 0;
	}

	bool push(const type &x, int key = -1)	//	key shouldn't be already in the heap
	{
		if (numElem == capacity)
		//	return 1;	//	no more space
			if (setCapacity(capacity+1000))	//	adding some more space to make room
				return 1;
		v[++numElem] = x;
		if (trackKeys && (key != -1))
		{
			if (keyToHeap[key] != -1)
			{
				//	key already in the heap; erroneous behaviour if continuing
				remove(numElem);	//	removing the recently added value to undo to the state prior to the function call
				return 1;
			}
			heapToKey[numElem] = key;
			keyToHeap[key] = numElem;
		}
		tryUp(numElem);

		return 0;
	}
	bool removeByKey(int key)
	{
		if ((!trackKeys) || (keyToHeap[key] == -1))
			return 1;	//	key not pushed in the heap
		return remove(keyToHeap[key]);
	}
	bool pop(type *popped, int *keyPopped=NULL, bool removeAfterPop=1)
	{
		if (numElem == 0)
			return 1;	//	nothing to pop
		if (popped)
			*popped = v[1];
		if (keyPopped && trackKeys)
			*keyPopped = heapToKey[1];
		if (removeAfterPop)
			remove(1);
		return 0;
	}
	bool getValueAtKey(type *value, int key)
	{
		if ((!trackKeys) || (keyToHeap[key] == -1))
			return 1;	//	key not pushed in the heap
		*value = v[keyToHeap[key]];
		return 0;
	}
	bool updateElementByKey(const type &newX, int key)
	{
		if ((!trackKeys) || (keyToHeap[key] == -1))
			return 1;	//	key not pushed in the heap
		return updateElement(keyToHeap[key], newX);
	}
protected:
	void swap(int index1, int index2)
	{
		type t = v[index1];
		v[index1] = v[index2];
		v[index2] = t;
		if (trackKeys)
		{
			int iT = heapToKey[index1];
			heapToKey[index1] = heapToKey[index2];
			heapToKey[index2] = iT;
			keyToHeap[heapToKey[index1]] = index1;
			keyToHeap[heapToKey[index2]] = index2;
		}
	}
	void tryUp(int index)
	{
		while ((index > 1) && (comp(v[index], v[index/2])))
		{
			swap(index, index/2);
			index /= 2;
		}
	}
	void tryDown(int index)
	{
		int tryIndex = 1;
		while (tryIndex != 0)
		{
			int dIndex = 2*index;
			tryIndex = 0;
			if (dIndex <= numElem)
			{
				if (dIndex+1 <= numElem)
				{
					if (comp(v[dIndex], v[dIndex+1]))
						tryIndex = dIndex;
					else
						tryIndex = dIndex+1;
				}
				else
					tryIndex = dIndex;
			}

			if ((tryIndex != 0) && comp(v[tryIndex], v[index]))
			{
				swap(index, tryIndex);
				index = tryIndex;
			}
			else
				tryIndex = 0;
		}
	}
	//	parameter /index/ is an index of v
	bool remove(int index)
	{
		if (index > numElem)
			return 1;
		swap(index, numElem--);
		keyToHeap[heapToKey[numElem+1]] = -1;
		heapToKey[numElem+1] = -1;
		if (comp(v[index], v[numElem+1]))
			tryUp(index);
		else
			tryDown(index);
		return 0;
	}
	//	parameter /index/ is an index of v
	bool updateElement(int index, const type &newX)
	{
		if (index > numElem)
			return 1;
		type oldValue = v[index];
		v[index] = newX;
		if (comp(oldValue, newX))
			tryDown(index);
		else
			tryUp(index);
		return 0;
	}
};

#define fileIn "heapuri.in"
#define fileOut "heapuri.out"

int main()
{
	std::ifstream sIn(fileIn);
	std::ofstream sOut(fileOut);
	
	Heap<int> heap(200000, 1);
	int n, i;
	int p, x;

	sIn >> n;
	int added = 0;
	for (i = 0; i < n; ++i)
	{
		sIn >> p;
		switch (p)
		{
			case 1:
			{
				sIn >> x;
				heap.push(x, ++added);
				break;
			}
			case 2:
			{
				sIn >> x;
				heap.removeByKey(x);
				break;
			}
			case 3:
			{
				int minValue;
				heap.pop(&minValue, NULL, false);
				sOut << minValue << '\n';
				break;
			}
			default:
			{
				//	??? invalid input
			}
		}
	}
	

	return 0;
}