#ifndef _KOK_MAXHEEP_H_
#define _KOK_MAXHEEP_H_
#pragma once
#include "Alloc.h"
namespace KOK
{
template <class Value, class Compare, class Alloc = KOK::alloc>
class CMaxHeep
{
template <class NodeValue>
struct CMaxHeepNode
{
typedef CMaxHeepNode<NodeValue>* LinkType;
LinkType pParent;
LinkType pLeft;
LinkType pRight;
NodeValue value;
};
public:
typedef Value ValueType;
typedef Value* Pointer;
typedef Value& Reference;
typedef const Value* ConstPointer;
typedef const Value& ConstReference;
typedef size_t SizeType;
typedef ptrdiff_t DiffType;
protected:
typedef CMaxHeepNode<Value> Node;
typedef CMaxHeepNode<Value>* LinkType;
typedef KOK::CAllocAdapter<Node, Alloc> NodeAlloc;
protected:
LinkType pRoot;
Compare keyCompare;
int count;
int fullCount;
int depth;
protected:
void DeleteNode(LinkType& pNode)
{
Destroy(&pNode->value);
PutNode(pNode);
pNode = NULL;
}
LinkType CreateNode(ConstReference value)
{
LinkType pNode = GetNode();
pNode->pLeft = pNode->pRight = pNode->pParent = NULL;
Construct(&pNode->value, value);
return pNode;
}
LinkType GetNode() { return NodeAlloc::Allocate();}
void PutNode(LinkType pNode) { NodeAlloc::Deallocate(pNode); }
inline void Init() { pRoot = NULL; count = 0; fullCount = 0; depth = 0; }
inline LinkType& Root() { return pRoot; }
inline LinkType& Left(LinkType& pNode) const { return pNode->pLeft; }
inline LinkType& Right(LinkType& pNode) const { return pNode->pRight; }
inline LinkType& Parent(LinkType& pNode) const { return pNode->pParent; }
void MaintainUp(LinkType pNode);
void MaintainDown(LinkType pNode);
LinkType PushHeepAux(ConstReference value)
{
count++;
if(count > fullCount)
{
fullCount += 1<<depth;
depth++;
}
if(Root() == NULL)
{
Root() = CreateNode(value);
return Root();
}
int i = depth;
LinkType pNode = Root();
while(--i)
{
if(i == 1)
{
if((count>>(i-1))& 1)
{
Right(pNode) = CreateNode(value);
Right(pNode)->pParent = pNode;
return Right(pNode);
}
else
{
Left(pNode) = CreateNode(value);
Left(pNode)->pParent = pNode;
return Left(pNode);
}
}
if((count>>(i-1))& 1)
pNode = Right(pNode);
else
pNode = Left(pNode);
}
}
LinkType PopHeepAux()
{
int i = depth;
LinkType pNode = Root();
while(--i)
{
if(i == 1)
{
if((count>>(i-1))& 1)
{
LinkType pTemp = pNode;
pNode = Right(pNode);
Right(pTemp) = NULL;
break;
}
else
{
LinkType pTemp = pNode;
pNode = Left(pNode);
Left(pTemp) = NULL;
break;
}
}
if((count>>(i-1))& 1)
pNode = Right(pNode);
else
pNode = Left(pNode);
}
count--;
if(count <= fullCount - (1<<(depth - 1)))
{
depth--;
fullCount -= 1<<depth;
}
return pNode;
}
void ClearAux(LinkType& pNode);
public:
CMaxHeep() { Init(); }
~CMaxHeep() { Clear(); }
inline bool Empty() const { return count == 0;}
inline Reference Top() const { return pRoot->value; }
inline int GetSize() const { return count; }
void PopHeep();
void PushHeep(ConstReference value);
void Clear();
};
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::MaintainUp(LinkType pNode)
{
bool flag = false;
ValueType tempValue = pNode->value;
while(Parent(pNode) != NULL && !flag )
{
LinkType pTemp = Parent(pNode);
if(keyCompare(pNode->value, pTemp->value))
flag = true;
else
{
pNode->value = pTemp->value;
pNode = pTemp;
}
}
pNode->value = tempValue;
}
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::MaintainDown(LinkType pNode)
{
bool flag = false;
ValueType tempValue = pNode->value;
while(!flag && Left(pNode) != NULL)
{
LinkType pTemp = Left(pNode);
if(Right(pNode) != NULL)
{
if(keyCompare(Left(pNode)->value, Right(pNode)->value))
{
pTemp = Right(pNode);
}
}
if(keyCompare(pTemp->value, pNode->value))
flag = true;
else
{
pNode->value = pTemp->value;
pNode = pTemp;
}
}
pNode->value = tempValue;
}
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::PushHeep(ConstReference value)
{
LinkType pLast = PushHeepAux(value);
MaintainUp(pLast);
}
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::PopHeep()
{
if(Empty())
return;
LinkType pLast = PopHeepAux();
Root()->value = pLast->value;
DeleteNode(pLast);
if(!Empty())
MaintainDown(Root());
else
Root() = NULL;
}
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::ClearAux(LinkType& pNode)
{
if(pNode->pLeft != NULL)
ClearAux(pNode->pLeft);
if(pNode->pRight != NULL)
ClearAux(pNode->pRight);
DeleteNode(pNode);
}
template <class Value, class Compare, class Alloc>
void CMaxHeep<Value, Compare, Alloc>::Clear()
{
if(Empty())
return;
ClearAux(Root());
Init();
}
}
#endif