00001 #ifndef MMANN_GLIBNODE_H
00002 #define MMANN_GLIBNODE_H
00003
00011
00016 template <class Data, class ConfigData>
00017 class GLIBTreeNode
00018 {
00019 public:
00020
00022 GLIBTreeNode(Data* data);
00023
00025 virtual ~GLIBTreeNode();
00026
00030 static void DeleteAllGLIBTreeNodes(GLIBTreeNode<Data, ConfigData>* Node, DeleteTreeDataEnum DeleteTreeData);
00031
00039 static GLIBTreeNode<Data, ConfigData>* Insert(GLIBTreeNode<Data, ConfigData>* Node, ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00040 Data* NodeData, bool* Inserted);
00041
00048 static GLIBTreeNode<Data, ConfigData>* Remove(GLIBTreeNode<Data, ConfigData>* Node, ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00049 Data* NodeData);
00050
00057 static Data* Lookup(GLIBTreeNode<Data, ConfigData>* Node, ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00058 Data* NodeData);
00059
00066 static Data* Search(GLIBTreeNode<Data, ConfigData>* Node, ACompareNodesAlgorithm<Data, ConfigData>* Compare, Data* NodeData);
00067
00072 static int GetHeight(GLIBTreeNode<Data, ConfigData>* Node);
00073
00078 static int GetNodeCount(GLIBTreeNode<Data, ConfigData>* Node);
00079
00080 protected:
00081
00086 static GLIBTreeNode<Data, ConfigData>* Balance(GLIBTreeNode<Data, ConfigData>* Node);
00087
00093 static GLIBTreeNode<Data, ConfigData>* RemoveLeftmost(GLIBTreeNode<Data, ConfigData>* Node, GLIBTreeNode<Data, ConfigData>** Leftmost);
00094
00100 static GLIBTreeNode<Data, ConfigData>* RestoreLeftBalance(GLIBTreeNode<Data, ConfigData>* Node, int OldBalance);
00101
00107 static GLIBTreeNode<Data, ConfigData>* RestoreRightBalance(GLIBTreeNode<Data, ConfigData>* Node, int OldBalance);
00108
00113 static GLIBTreeNode<Data, ConfigData>* RotateLeft(GLIBTreeNode<Data, ConfigData>* Node);
00114
00119 static GLIBTreeNode<Data, ConfigData>* RotateRight(GLIBTreeNode<Data, ConfigData>* Node);
00120
00122 GLIBTreeNode<Data, ConfigData>* m_Left;
00123
00125 GLIBTreeNode<Data, ConfigData>* m_Right;
00126
00128 Data* m_Data;
00129
00131 signed char m_Balance;
00132
00133 };
00134
00135 template <class Data, class ConfigData>
00136 GLIBTreeNode<Data, ConfigData>::GLIBTreeNode(Data* data)
00137 {
00138 m_Left = m_Right = NULL;
00139 m_Balance = 0;
00140 m_Data = data;
00141 }
00142
00143 template <class Data, class ConfigData>
00144 GLIBTreeNode<Data, ConfigData>::~GLIBTreeNode()
00145 {
00146 }
00147
00148 template <class Data, class ConfigData>
00149 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::Insert(GLIBTreeNode<Data, ConfigData>* Node,
00150 ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00151 Data* NodeData, bool* Inserted)
00152 {
00153 int OldBalance;
00154 int CompareValue;
00155
00156 if (Node == NULL)
00157 {
00158 *Inserted = true;
00159 return new GLIBTreeNode<Data, ConfigData>(NodeData);
00160 }
00161
00162 CompareValue = (*Compare).Compare(Node->m_Data, NodeData, NULL);
00163 if (CompareValue == 0)
00164 {
00165 *Inserted = false;
00166 Node->m_Data = NodeData;
00167 return Node;
00168 }
00169
00170 if (CompareValue < 0)
00171 {
00172 if (Node->m_Left != NULL)
00173 {
00174 OldBalance = Node->m_Left->m_Balance;
00175 Node->m_Left = Insert(Node->m_Left, Compare, NodeData, Inserted);
00176 if ((OldBalance != Node->m_Left->m_Balance) && Node->m_Left->m_Balance)
00177 Node->m_Balance -= 1;
00178 }
00179 else
00180 {
00181 *Inserted = true;
00182 Node->m_Left = new GLIBTreeNode<Data, ConfigData>(NodeData);
00183 Node->m_Balance -= 1;
00184 }
00185 }
00186 else if (CompareValue > 0)
00187 {
00188 if (Node->m_Right != NULL)
00189 {
00190 OldBalance = Node->m_Right->m_Balance;
00191 Node->m_Right = Insert(Node->m_Right, Compare, NodeData, Inserted);
00192 if ((OldBalance != Node->m_Right->m_Balance) && Node->m_Right->m_Balance)
00193 Node->m_Balance += 1;
00194 }
00195 else
00196 {
00197 *Inserted = true;
00198 Node->m_Right = new GLIBTreeNode<Data, ConfigData>(NodeData);
00199 Node->m_Balance += 1;
00200 }
00201 }
00202
00203 if ((*Inserted) && ((Node->m_Balance < -1) || (Node->m_Balance > 1)))
00204 {
00205 Node = Balance(Node);
00206 }
00207
00208 return Node;
00209 }
00210
00211 template <class Data, class ConfigData>
00212 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::Remove(GLIBTreeNode<Data, ConfigData>* Node,
00213 ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00214 Data* NodeData)
00215 {
00216 if (Node == NULL)
00217 return NULL;
00218
00219 GLIBTreeNode<Data, ConfigData>* NewRoot;
00220 int OldBalance;
00221 int CompareValue;
00222
00223 CompareValue = (*Compare).Compare(Node->m_Data, NodeData, NULL);
00224 if (CompareValue == 0)
00225 {
00226 if (Node->m_Right == NULL)
00227 {
00228 NewRoot = Node->m_Left;
00229 }
00230 else
00231 {
00232 OldBalance = Node->m_Right->m_Balance;
00233 Node->m_Right = RemoveLeftmost(Node->m_Right, &NewRoot);
00234 NewRoot->m_Left = Node->m_Left;
00235 NewRoot->m_Right = Node->m_Right;
00236 NewRoot->m_Balance = Node->m_Balance;
00237 NewRoot = RestoreRightBalance(NewRoot, OldBalance);
00238 }
00239
00240 delete Node;
00241 return NewRoot;
00242 }
00243 else if (CompareValue < 0)
00244 {
00245 if (Node->m_Left != NULL)
00246 {
00247 OldBalance = Node->m_Left->m_Balance;
00248 Node->m_Left = Remove(Node->m_Left, Compare, NodeData);
00249 Node = RestoreLeftBalance(Node, OldBalance);
00250 }
00251 }
00252 else if (CompareValue > 0)
00253 {
00254 if (Node->m_Right != NULL)
00255 {
00256 OldBalance = Node->m_Right->m_Balance;
00257 Node->m_Right = Remove(Node->m_Right, Compare, NodeData);
00258 Node = RestoreRightBalance(Node, OldBalance);
00259 }
00260 }
00261
00262 return Node;
00263 }
00264
00265 template <class Data, class ConfigData>
00266 Data* GLIBTreeNode<Data, ConfigData>::Lookup(GLIBTreeNode<Data, ConfigData>* Node,
00267 ACompareNodesAlgorithm<Data, ConfigData>* Compare,
00268 Data* NodeData)
00269 {
00270 if (Node == NULL)
00271 return NULL;
00272
00273 int CompareValue = (*Compare).Compare(Node->m_Data, NodeData, NULL);
00274 if (CompareValue == 0)
00275 return Node->m_Data;
00276
00277 if (CompareValue < 0)
00278 {
00279 if (Node->m_Left != NULL)
00280 return Lookup((GLIBTreeNode<Data, ConfigData>*)Node->m_Left, Compare, NodeData);
00281 }
00282 else if (CompareValue > 0)
00283 {
00284 if (Node->m_Right != NULL)
00285 return Lookup((GLIBTreeNode<Data, ConfigData>*)Node->m_Right, Compare, NodeData);
00286 }
00287
00288 return NULL;
00289 }
00290
00291 template <class Data, class ConfigData>
00292 Data* GLIBTreeNode<Data, ConfigData>::Search(GLIBTreeNode<Data, ConfigData>* Node, ACompareNodesAlgorithm<Data, ConfigData>* Compare, Data* NodeData)
00293 {
00294 if (Node == NULL)
00295 return NULL;
00296
00297 int Direction;
00298
00299 do
00300 {
00301 Direction = (*Compare).Compare(Node->m_Data, NodeData, NULL);
00302 if (Direction == 0)
00303 return Node->m_Data;
00304
00305 if (Direction < 0)
00306 Node = Node->m_Left;
00307 else if (Direction > 0)
00308 Node = Node->m_Right;
00309 }
00310 while ((Node != NULL) && (Direction != 0));
00311
00312 return NULL;
00313 }
00314
00315 template <class Data, class ConfigData>
00316 int GLIBTreeNode<Data, ConfigData>::GetHeight(GLIBTreeNode<Data, ConfigData>* Node)
00317 {
00318 if (Node != NULL)
00319 {
00320 int LeftHeight = 0,
00321 RightHeight = 0;
00322
00323 if (Node->m_Left != NULL)
00324 LeftHeight = GetHeight(Node->m_Left);
00325
00326 if (Node->m_Right != NULL)
00327 RightHeight = GetHeight(Node->m_Right);
00328
00329 return ((LeftHeight > RightHeight) ? LeftHeight : RightHeight) + 1;
00330 }
00331
00332 return 0;
00333 }
00334
00335 template <class Data, class ConfigData>
00336 int GLIBTreeNode<Data, ConfigData>::GetNodeCount(GLIBTreeNode<Data, ConfigData>* Node)
00337 {
00338 int Count = 1;
00339
00340 if (Node->m_Left)
00341 Count += GetNodeCount(Node->m_Left);
00342 if (Node->m_Right)
00343 Count += GetNodeCount(Node->m_Right);
00344
00345 return Count;
00346 }
00347
00348 template <class Data, class ConfigData>
00349 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::Balance(GLIBTreeNode<Data, ConfigData>* Node)
00350 {
00351 if (Node->m_Balance < -1)
00352 {
00353 if (Node->m_Left->m_Balance > 0)
00354 Node->m_Left = RotateLeft(Node->m_Left);
00355 Node = RotateRight(Node);
00356 }
00357 else if (Node->m_Balance > 1)
00358 {
00359 if (Node->m_Right->m_Balance < 0)
00360 Node->m_Right = RotateRight(Node->m_Right);
00361 Node = RotateLeft(Node);
00362 }
00363
00364 return Node;
00365 }
00366
00367 template <class Data, class ConfigData>
00368 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::RemoveLeftmost(GLIBTreeNode<Data, ConfigData>* Node, GLIBTreeNode<Data, ConfigData>** Leftmost)
00369 {
00370 if (Node->m_Left == NULL)
00371 {
00372 *Leftmost = Node;
00373 return Node->m_Right;
00374 }
00375
00376 int OldBalance = Node->m_Left->m_Balance;
00377 Node->m_Left = RemoveLeftmost(Node->m_Left, Leftmost);
00378 return RestoreLeftBalance(Node, OldBalance);
00379 }
00380
00381 template <class Data, class ConfigData>
00382 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::RestoreLeftBalance(GLIBTreeNode<Data, ConfigData>* Node, int OldBalance)
00383 {
00384 if (Node->m_Left == NULL)
00385 Node->m_Balance += 1;
00386 else if ((Node->m_Left->m_Balance != OldBalance) && (Node->m_Left->m_Balance == 0))
00387 Node->m_Balance += 1;
00388
00389 if (Node->m_Balance > 1)
00390 return Balance(Node);
00391
00392 return Node;
00393 }
00394
00395 template <class Data, class ConfigData>
00396 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::RestoreRightBalance(GLIBTreeNode<Data, ConfigData>* Node, int OldBalance)
00397 {
00398 if (Node->m_Right == NULL)
00399 Node->m_Balance -= 1;
00400 else if ((Node->m_Right->m_Balance != OldBalance) && (Node->m_Right->m_Balance == 0))
00401 Node->m_Balance -= 1;
00402
00403 if (Node->m_Balance < -1)
00404 return Balance(Node);
00405
00406 return Node;
00407 }
00408
00409 template <class Data, class ConfigData>
00410 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::RotateLeft(GLIBTreeNode<Data, ConfigData>* Node)
00411 {
00412 GLIBTreeNode<Data, ConfigData> *Left = (GLIBTreeNode<Data, ConfigData>*)Node->m_Left,
00413 *Right = (GLIBTreeNode<Data, ConfigData>*)Node->m_Right;
00414
00415 Node->m_Right = Right->m_Left;
00416 Right->m_Left = Node;
00417
00418 int aBalance = Node->m_Balance,
00419 bBalance = Right->m_Balance;
00420
00421 if (bBalance <= 0)
00422 {
00423 if (aBalance >= 1)
00424 Right->m_Balance = bBalance - 1;
00425 else
00426 Right->m_Balance = aBalance + bBalance - 2;
00427 Node->m_Balance = aBalance - 1;
00428 }
00429 else
00430 {
00431 if (aBalance <= bBalance)
00432 Right->m_Balance = aBalance - 2;
00433 else
00434 Right->m_Balance = bBalance - 1;
00435 Node->m_Balance = aBalance - bBalance - 1;
00436 }
00437
00438 return Right;
00439 }
00440
00441 template <class Data, class ConfigData>
00442 GLIBTreeNode<Data, ConfigData>* GLIBTreeNode<Data, ConfigData>::RotateRight(GLIBTreeNode<Data, ConfigData>* Node)
00443 {
00444 GLIBTreeNode<Data, ConfigData> *Left = (GLIBTreeNode<Data, ConfigData>*)Node->m_Left;
00445 Node->m_Left = Left->m_Right;
00446 Left->m_Right = Node;
00447
00448 int aBalance = Node->m_Balance,
00449 bBalance = Left->m_Balance;
00450
00451 if (bBalance <= 0)
00452 {
00453 if (bBalance > aBalance)
00454 Left->m_Balance = bBalance + 1;
00455 else
00456 Left->m_Balance = aBalance + 2;
00457 Node->m_Balance = aBalance - bBalance + 1;
00458 }
00459 else
00460 {
00461 if (aBalance <= -1)
00462 Left->m_Balance = bBalance + 1;
00463 else
00464 Left->m_Balance = aBalance + bBalance + 2;
00465 Node->m_Balance = aBalance + 1;
00466 }
00467
00468 return Left;
00469 }
00470
00471 template <class Data, class ConfigData>
00472 void GLIBTreeNode<Data, ConfigData>::DeleteAllGLIBTreeNodes(GLIBTreeNode<Data, ConfigData>* Node, DeleteTreeDataEnum DeleteTreeData)
00473 {
00474 if (Node->m_Left != NULL)
00475 DeleteAllGLIBTreeNodes(Node->m_Left, DeleteTreeData);
00476 if (Node->m_Right != NULL)
00477 DeleteAllGLIBTreeNodes(Node->m_Right, DeleteTreeData);
00478
00479 switch(DeleteTreeData)
00480 {
00481 case NO_DELETE_TREE_ITEM:
00482 break;
00483 case DELETE_TREE_ITEM:
00484 delete Node->m_Data;
00485 break;
00486 case DELETE_TREE_ITEM_ARRAY:
00487 delete [] Node->m_Data;
00488 break;
00489 default:
00490
00491 assert(false);
00492 }
00493
00494 delete Node;
00495 }
00496
00497 #endif