主要完成维护一个min-heap or max-heap,如果push的个数超过heap的大小,则进行替换,依赖于compare函数。
其中min-heap需要定义 return a < b; max-heap: return a > b
在空间不够的情况下,min-heap保留最大的k个元素,max-heap相反。
code:
template<typename Type>
class LessThan
{
public:
bool operator()(const Type& first, const Type& second)
{
return first < second;
}
};
#ifndef _HEAP_H_
#define _HEAP_H_
#include "utility.h"
#include <string.h>
#define DEFAULT_BUFF_NUM 1000
namespace utility
{
//Compare, return a>b, 0,1,2,3 return a<b, 3,2,1,0
template<typename Type, typename Compare = LessThan<Type> >
class Heap
{
public:
Heap(int capacity = 0);
~Heap();
int push(const Type& type);
Type pop();
Type top();
int size();
int capacity();
bool empty();
private:
int ShiftUp();
int ShiftDown();
int Parent(int i);
int Left(int i);
int Right(int i);
private:
int mSize;
int mCapacity;
Type* mpHeap;
Compare mCompare;
};
template<typename Type, typename Compare>
int Heap<Type, Compare>::Parent(int i)
{
return int((i + 1) / 2) - 1;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::Left(int i)
{
return 2 * (i + 1) - 1;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::Right(int i)
{
return 2 * (i + 1);
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::ShiftUp()
{
// sucks
int i = mSize - 1;
while (i > 0)
{
int parent = Parent(i);
// need to modify
if (!mCompare(mpHeap[parent], mpHeap[i]))
{
Swap(mpHeap[parent], mpHeap[i]);
}
else
{
break;
}
i = parent;
}
return 0;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::ShiftDown()
{
// sucks
int i = 0;
while (i < mSize)
{
int left = Left(i);
int right = Right(i);
int modify = -1;
if ((right < mSize))
{
if (mCompare(mpHeap[left], mpHeap[right]))
{
modify = left;
}
else
{
modify = right;
}
}
else if (left < mSize)
{
modify = left;
}
if (modify < 0)
{
break;
}
if (!mCompare(mpHeap[i], mpHeap[modify]))
{
Swap(mpHeap[i], mpHeap[modify]);
}
else
{
break;
}
i = modify;
}
return 0;
}
template<typename Type, typename Compare>
Heap<Type, Compare>::Heap(int capactiy):
mSize(0),
mCapacity(capactiy),
mpHeap(NULL)
{
if (mCapacity <= 0)
{
mCapacity = DEFAULT_BUFF_NUM;
}
mpHeap = new Type[mCapacity];
memset(mpHeap, 0, mCapacity * sizeof(Type));
}
template<typename Type, typename Compare>
Heap<Type, Compare>::~Heap()
{
delete[] mpHeap;
mpHeap = NULL;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::push(const Type& type)
{
if (mSize < mCapacity)
{
mpHeap[mSize] = type;
++mSize;
ShiftUp();
}
else
{
// small element on the top
if (!mCompare(type, mpHeap[0]))
{
mpHeap[0] = type;
ShiftDown();
}
}
return 0;
}
template<typename Type, typename Compare>
Type Heap<Type, Compare>::top()
{
return mpHeap[0];
}
template<typename Type, typename Compare>
Type Heap<Type, Compare>::pop()
{
Type type = mpHeap[0];
if (mSize == 1)
{
--mSize;
return type;
}
mpHeap[0] = mpHeap[mSize - 1];
--mSize;
ShiftDown();
return type;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::size()
{
return mSize;
}
template<typename Type, typename Compare>
int Heap<Type, Compare>::capacity()
{
return mCapacity;
}
template<typename Type, typename Compare>
bool Heap<Type, Compare>::empty()
{
return mSize <= 0;
}
}
#endif