#include "AliITSIntMap.h"
#include "AliITSIntMapNode.h"
#include <TMath.h>
#include <TError.h>
AliITSIntMap::AliITSIntMap():
fNrEntries(0),
fRoot(NULL),
fFastAccess(kFALSE),
fFastAccessSerialize(kFALSE),
fFastAccessArray(NULL),
fDummyIndex(0)
{}
AliITSIntMap::AliITSIntMap(AliITSIntMapNode* root, UInt_t nrEntries):
fNrEntries(nrEntries),
fRoot(root),
fFastAccess(kFALSE),
fFastAccessSerialize(kFALSE),
fFastAccessArray(NULL),
fDummyIndex(0)
{}
AliITSIntMap::AliITSIntMap(const AliITSIntMap& imap):
fNrEntries(0),
fRoot(NULL),
fFastAccess(kFALSE),
fFastAccessSerialize(kFALSE),
fFastAccessArray(NULL),
fDummyIndex(0)
{
*this = imap;
}
AliITSIntMap::~AliITSIntMap() {
Clear();
}
AliITSIntMap& AliITSIntMap::operator=(const AliITSIntMap& imap) {
if (this!=&imap) {
this->Clear();
fRoot = CloneNode(imap.fRoot);
fFastAccess=kFALSE;
fFastAccessSerialize=kFALSE;
fFastAccessArray=NULL;
fDummyIndex=0;
}
return *this;
}
void AliITSIntMap::Clear() {
ClearFastAccess();
ClearNode(fRoot);
}
void AliITSIntMap::ClearNode(AliITSIntMapNode* &node) {
if (node==NULL) return;
ClearNode(node->Left());
ClearNode(node->Right());
delete node;
fNrEntries--;
node = NULL;
fFastAccess=kFALSE;
fFastAccessSerialize=kFALSE;
}
AliITSIntMap* AliITSIntMap::Clone() const {
AliITSIntMapNode* newRoot;
newRoot = CloneNode(fRoot);
AliITSIntMap* newMap = new AliITSIntMap(newRoot,fNrEntries);
return newMap;
}
AliITSIntMapNode* AliITSIntMap::CloneNode(AliITSIntMapNode* node) const {
if (node==NULL) return NULL;
else return new AliITSIntMapNode(node->Key(),node->Val(),CloneNode(node->Left()),CloneNode(node->Right()));
}
Bool_t AliITSIntMap::Insert(Int_t key, Int_t val) {
UInt_t entriesBefore = fNrEntries;
InsertNode(key,val,fRoot,0);
if (fNrEntries>entriesBefore) return kTRUE;
else return kFALSE;
}
void AliITSIntMap::InsertNode(Int_t key, Int_t val, AliITSIntMapNode* &node, UInt_t height) {
height++;
if (node==NULL) {
node = new AliITSIntMapNode(key,val,NULL,NULL);
fNrEntries++;
fFastAccess=kFALSE;
fFastAccessSerialize=kFALSE;
UInt_t balanceHeight = (UInt_t) (TMath::Log(fNrEntries+1)/TMath::Log(2)+1);
if ( (height-balanceHeight)*(height-balanceHeight) > fNrEntries ) {
Balance();
}
}
else if (key < node->Key()) {
InsertNode(key,val,node->Left(),height);
}
else if (key > node->Key()) {
InsertNode(key,val,node->Right(),height);
}
else {
}
}
Bool_t AliITSIntMap::Remove(Int_t key) {
UInt_t entriesBefore = fNrEntries;
RemoveNode(key,fRoot);
if (fNrEntries<entriesBefore) return kTRUE;
else return kFALSE;
}
void AliITSIntMap::RemoveNode(Int_t key, AliITSIntMapNode* &node) {
if (node == NULL) return;
if (key < node->Key()) {
RemoveNode(key,node->Left());
}
else if (key > node->Key()) {
RemoveNode(key,node->Right());
}
else if (node->Left()!=NULL && node->Right()!=NULL) {
if (fNrEntries%2==0) {
AliITSIntMapNode* moveNode = FindMinNode(node->Right());
node->SetKey(moveNode->Key());
node->SetVal(moveNode->Val());
RemoveNode(moveNode->Key(),node->Right());
}
else {
AliITSIntMapNode* moveNode = FindMaxNode(node->Left());
node->SetKey(moveNode->Key());
node->SetVal(moveNode->Val());
RemoveNode(moveNode->Key(),node->Left());
}
}
else {
AliITSIntMapNode* oldNode = node;
node = (node->Left()!=NULL) ? node->Left() : node->Right();
fNrEntries--;
delete oldNode;
fFastAccess=kFALSE;
fFastAccessSerialize=kFALSE;
}
}
Bool_t AliITSIntMap::Pop(Int_t& key, Int_t& val) {
if (fRoot!=NULL) {
key = fRoot->Key();
val = fRoot->Val();
return Remove(key);
}
else return kFALSE;
}
AliITSIntMapNode* AliITSIntMap::FindMinNode(AliITSIntMapNode* node) const {
if (node==NULL) return NULL;
else if (node->Left()==NULL) return node;
else return FindMinNode(node->Left());
}
AliITSIntMapNode* AliITSIntMap::FindMaxNode(AliITSIntMapNode* node) const {
if (node==NULL) return NULL;
else if (node->Right()==NULL) return node;
else return FindMaxNode(node->Right());
}
AliITSIntMapNode* AliITSIntMap::Find(Int_t key) const {
return FindNode(key,fRoot,0);
}
AliITSIntMapNode* AliITSIntMap::FindNode(Int_t key, AliITSIntMapNode* node, UInt_t height) const {
if (node==NULL) return NULL;
height++;
if (key<node->Key()) return FindNode(key,node->Left(),height);
else if (key>node->Key()) return FindNode(key,node->Right(),height);
else {
return node;
}
}
Int_t AliITSIntMap::GetVal(Int_t key) const {
AliITSIntMapNode* node = Find(key);
if (node!=NULL) {
return node->Val();
}
else {
Warning("AliITSIntMap::GetVal","Node with key %d not found in map. Returning -999.",key);
return -999;
}
}
void AliITSIntMap::Balance() {
if (fNrEntries==0) return;
if (!fFastAccess) InitFastAccess();
fRoot = BalanceNode(0,fNrEntries-1);
}
AliITSIntMapNode* AliITSIntMap::BalanceNode(Int_t lowInd, Int_t highInd) {
if (lowInd>highInd) return NULL;
Int_t thisInd = lowInd+(highInd-lowInd)/2;
fFastAccessArray[thisInd]->Left() = BalanceNode(lowInd,thisInd-1);
fFastAccessArray[thisInd]->Right() = BalanceNode(thisInd+1,highInd);
return fFastAccessArray[thisInd];
}
void AliITSIntMap::ClearFastAccess(){
if (fFastAccessArray!=NULL) {
delete [] fFastAccessArray;
fFastAccessArray=NULL;
}
fFastAccess=kFALSE;
fFastAccessSerialize=kFALSE;
}
void AliITSIntMap::InitFastAccess(){
if (fFastAccess) return;
ClearFastAccess();
if (fNrEntries>0) {
fFastAccessArray = new AliITSIntMapNode*[fNrEntries];
fDummyIndex=0;
InitFastAccessNode(fRoot);
fFastAccess=kTRUE;
}
}
void AliITSIntMap::InitFastAccessNode(AliITSIntMapNode* node) {
if (node==NULL) return;
InitFastAccessNode(node->Left());
fFastAccessArray[fDummyIndex++] = node;
InitFastAccessNode(node->Right());
}
void AliITSIntMap::InitFastAccessSerialize(){
if (fFastAccessSerialize) return;
ClearFastAccess();
if (fNrEntries>0) {
fFastAccessArray = new AliITSIntMapNode*[fNrEntries];
fDummyIndex=0;
InitFastAccessSerializeNode(fRoot);
fFastAccessSerialize=kTRUE;
}
}
void AliITSIntMap::InitFastAccessSerializeNode(AliITSIntMapNode* node) {
if (node==NULL) return;
fFastAccessArray[fDummyIndex++] = node;
InitFastAccessSerializeNode(node->Left());
InitFastAccessSerializeNode(node->Right());
}
Int_t AliITSIntMap::GetKeyIndex(UInt_t index) {
if (index<fNrEntries) {
if (!fFastAccess && !fFastAccessSerialize) InitFastAccess();
return fFastAccessArray[index]->Key();
}
return -1;
}
Int_t AliITSIntMap::GetValIndex(UInt_t index) {
if (index<fNrEntries) {
if (!fFastAccess && !fFastAccessSerialize) InitFastAccess();
return fFastAccessArray[index]->Val();
}
return -1;
}
AliITSIntMapNode* AliITSIntMap::FindNodeIndex(UInt_t index, AliITSIntMapNode* node) const {
static UInt_t fTmpInd;
if (node==fRoot) fTmpInd=0;
if (node->Left()!=NULL) {
AliITSIntMapNode* tmpResult = FindNodeIndex(index,node->Left());
if (tmpResult != NULL) {
return tmpResult;
}
}
if (fTmpInd==index) return node;
fTmpInd++;
if (node->Right()!=NULL) {
AliITSIntMapNode* tmpResult = FindNodeIndex(index,node->Right());
if (tmpResult != NULL) {
return tmpResult;
}
}
return NULL;
}
void AliITSIntMap::PrintEntries() const {
printf("*** Map Entries: (key , value)***\n");
PrintNode(fRoot);
printf("*********************************\n");
}
void AliITSIntMap::PrintNode(AliITSIntMapNode* node) const {
if (node==NULL) return;
if (node->Left()!=NULL) PrintNode(node->Left());
printf("%d , %d\n",node->Key(),node->Val());
if (node->Right()!=NULL) PrintNode(node->Right());
}
UInt_t AliITSIntMap::GetTreeHeight() const {
return GetTreeHeightNode(fRoot);
}
UInt_t AliITSIntMap::GetTreeHeightNode(AliITSIntMapNode* node) const {
if (node==NULL) return 0;
UInt_t leftH = GetTreeHeightNode(node->Left());
UInt_t rightH = GetTreeHeightNode(node->Right());
if (leftH>=rightH) return leftH+1;
else return rightH+1;
}