Pagini recente » Cod sursa (job #923438) | Cod sursa (job #3123403) | Cod sursa (job #3184353) | Cod sursa (job #3266961) | Cod sursa (job #1864185)
#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;
int keyCapacity;
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 keyCapacity
public:
Heap(int maxSize, bool keepTrackOfKeys = 0, int maxKey=-1, bool (*compFunction)(const type&, const type&)=NULL)
{
if (maxKey == -1)
maxKey = maxSize;
keyCapacity = maxKey;
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[keyCapacity+1];
}
catch (std::bad_alloc&)
{
throw;
// ???
}
for (int i = 0; i <= capacity; ++i)
heapToKey[i] = -1;
for (int i = 0; i <= keyCapacity; ++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;
}
bool isKeyInHeap(int key)
{
if ((!trackKeys) || (key < 0) || (key > keyCapacity))
return 1;
return keyToHeap[key] != -1;
}
// 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;
try
{
newV = new type[n+1]; // indexing from 1
if (trackKeys)
newHeapToKey = new int[n+1];
}
catch (std::bad_alloc&)
{
return 1; // operation failed, but the old vectors remain unchanged
}
capacity = n;
for (int i = 0; i <= numElem; ++i)
newV[i] = v[i];
if (trackKeys)
{
for (int i = 0; i <= numElem; ++i)
newHeapToKey[i] = heapToKey[i];
for (int i = numElem+1; i <= capacity; ++i)
newHeapToKey[i] = -1;
}
delete [] v;
v = newV;
if (trackKeys)
{
delete [] heapToKey;
heapToKey = newHeapToKey;
}
return 0;
}
// n must be greater or equal to keyCapacity
bool setKeyCapacity(int n)
{
if (!trackKeys)
return 1; // keyCapacity is irrelevant if not using keys
if (n < keyCapacity)
return 1; // possible data loss if operation is executed
int *newKeyToHeap = NULL;
try
{
newKeyToHeap = new int[n+1];
}
catch (std::bad_alloc&)
{
return 1; // operation failed, but the old vector remains unchanged
}
for (int i = 0; i <= keyCapacity; ++i)
newKeyToHeap[i] = keyToHeap[i];
for (int i = keyCapacity+1; i <= n; ++i)
newKeyToHeap[i] = -1;
keyCapacity = n;
delete [] keyToHeap;
keyToHeap = newKeyToHeap;
return 0;
}
bool push(const type &x, int key = -1) // key shouldn't be already in the heap and key should be between 0 and keyCapacity
{
if (numElem == capacity)
// return 1; // no more space
if (setCapacity(capacity+1000)) // adding some more space to make room
return 1;
if (key >= keyCapacity)
if (setKeyCapacity(key)) // must add space in order to be able to handle larger keys
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;
}