/*************************************************************************/ /* File : XBinaryTree.h */ /* Author : Aymeric Bard */ /* */ /* Virtools SDK */ /* Copyright (c) Virtools 2000, All Rights Reserved. */ /*************************************************************************/ #ifndef BINARYTREE_H #define BINARYTREE_H #include "XUtil.h" template class Compare { public: bool operator() (const T& iT1,const T& iT2) const {return (iT1 < iT2);} }; /************************************************ Summary: Not Yet Documented ************************************************/ template , bool TMulti = true> class XBTree { public: typedef T Type; typedef T* Pointer; typedef T& Reference; typedef const T& ConstReference; protected: enum Color {RED, BLACK}; struct Node { Node* parent; Node* left; Node* right; Color color; T value; }; public: class Iterator; // Const iterator class ConstIterator { public: ConstIterator(){} ConstIterator ( Node* iP):m_Node(iP) {} ConstIterator(const Iterator& iCopy) : m_Node(iCopy.m_Node) {} ConstReference operator*() const {return m_Node->value; } Type* operator->() const {return &m_Node->value; } ConstIterator& operator++() {XInc(); return (*this); } ConstIterator operator++(int) {ConstIterator _Tmp = *this; ++*this; return (_Tmp); } ConstIterator& operator--() {XDec(); return (*this); } ConstIterator operator--(int) {ConstIterator _Tmp = *this; --*this; return (_Tmp); } bool operator==(const ConstIterator& iX) const {return (m_Node == iX.m_Node); } bool operator!=(const ConstIterator& iX) const {return (!(*this == iX)); } protected: void XDec() { if (m_Node->color == RED && XParent(m_Node->parent) == m_Node) { m_Node = m_Node->right; } else { if (m_Node->left != m_Nil) { m_Node = XMax(m_Node->left); } else { Node* n; while (m_Node == XLeft(n = m_Node->parent)) m_Node = n; m_Node = n; } } } void XInc() { if (m_Node->right != m_Nil) { m_Node = XMin(m_Node->right); } else { Node* n; while (m_Node == XRight(n = m_Node->parent)) m_Node = n; if (m_Node->right != n) { m_Node = n; } } } Node* m_Node; }; friend class ConstIterator; // Non-Const Iterator class Iterator : public ConstIterator { public: Iterator() {} Iterator(Node* iNode) : ConstIterator(iNode) {} Reference operator*() const {return this->m_Node->value;} Iterator& operator++() { this->XInc(); return (*this); } Iterator operator++(int) { Iterator _Tmp = *this; ++*this; return (_Tmp); } Iterator& operator--() { this->XDec(); return (*this); } Iterator operator--(int) { Iterator _Tmp = *this; --*this; return (_Tmp); } bool operator==(const Iterator& iA) const {return (this->m_Node == iA.m_Node); } bool operator!=(const Iterator& iA) const {return (!(*this == iA)); } }; friend class Iterator; /// // Methods explicit XBTree(const TCmpFunc& iCmp = TCmpFunc()):m_KeyCompare(iCmp) { XInit(); } XBTree(const XBTree& iModel):m_KeyCompare(iModel.m_KeyCompare) { XInit(); XCopy(iModel); } ~XBTree() { Erase(Begin(), End()); XFreeNode(m_Head); // Nil Node management // TODO : thread safe ? -> lock resource if (--m_NilRefCount == 0) { XFreeNode(m_Nil); m_Nil = 0; } } const XBTree& operator = (const XBTree& iModel) { if (this != &iModel) { Erase(Begin(), End()); m_KeyCompare = iModel.m_KeyCompare; XCopy(iModel); } return *this; } /************************************************ Summary: Returns an iterator on the first element. ************************************************/ Iterator Begin() {return Iterator(this->XLMost());} /************************************************ Summary: Returns an iterator after the last element. ************************************************/ Iterator End() {return Iterator(m_Head); } /************************************************ Summary: Returns a const iterator on the first element. ************************************************/ ConstIterator Begin() const {return Iterator(this->XLmost());} /************************************************ Summary: Returns a const iterator after the last element. ************************************************/ ConstIterator End() const {return ConstIterator(m_Head); } /************************************************ Summary: Returns an iterator on the first element for a reverse iteration. ************************************************/ Iterator RBegin() {return (Size())?Iterator(--End()):Iterator(m_Nil);} /************************************************ Summary: Returns a const iterator after the last element for a reverse iteration. ************************************************/ Iterator REnd() {return (Size()>1)?Iterator(--Begin()):Iterator(--(--(Begin()))); } /************************************************ Summary: Returns a const iterator on the first element for a reverse iteration. ************************************************/ ConstIterator RBegin() const {return ConstIterator(End());} /************************************************ Summary: Returns a const iterator after the last element for a reverse iteration. ************************************************/ ConstIterator REnd() const {return ConstIterator(Begin()); } /************************************************ Summary: Returns the elements number. ************************************************/ unsigned int Size() const {return m_Size; } Iterator Insert(Iterator iT, ConstReference iValue) { if (Size() == 0) ; else if (iT == Begin()) { if (m_KeyCompare(iValue, iT.m_Node->value)) return (XInsert(m_Head, iT.m_Node, iValue)); } else if (iT == End()) { if (m_KeyCompare(XValue(XRMost()), iValue)) return XInsert(m_Nil, XRMost(), iValue); } else { Iterator i = iT; if (m_KeyCompare((--i).m_Node->value, iValue) && m_KeyCompare(iValue, iT.m_Node->value)) { if (i.m_Node->right == m_Nil) return XInsert(m_Nil, i.m_Node, iValue); else return XInsert(m_Head, iT.m_Node, iValue); } } return Insert(iValue); } Iterator Insert(ConstReference iValue) { Node* n = XRoot(); Node* nodeBefore = m_Head; bool ans = true; while (n != m_Nil) { nodeBefore = n; ans = m_KeyCompare(iValue,n->value); n = ans ? n->left : n->right; } if (TMulti) return XInsert(n,nodeBefore, iValue); Iterator it = Iterator(nodeBefore); if (!ans) ; else if (it == Begin()) return XInsert(n, nodeBefore, iValue); else --it; if (m_KeyCompare(*it, iValue)) return XInsert(n, nodeBefore, iValue); // already in the tree... maybe do a pair ???? return it; } Iterator PushBack(ConstReference iValue) {return Insert(iValue);} Iterator Erase(Iterator iT) { Node* x; Node* y = (iT++).m_Node; Node* z = y; if (XLeft(y) == m_Nil) x = XRight(y); else if (XRight(y) == m_Nil) x = XLeft(y); else y = XMin(XRight(y)), x = XRight(y); { // _Lockit _Lk; if (y != z) { XParent(XLeft(z)) = y; XLeft(y) = XLeft(z); if (y == XRight(z)) XParent(x) = y; else { XParent(x) = XParent(y); XLeft(XParent(y)) = x; XRight(y) = XRight(z); XParent(XRight(z)) = y; } if (XRoot() == z) { XRoot() = y; } else { if (XLeft(XParent(z)) == z) XLeft(XParent(z)) = y; else XRight(XParent(z)) = y; } XParent(y) = XParent(z); XSwap(XColor(y), XColor(z)); y = z; } else { XParent(x) = XParent(y); if (XRoot() == z) { XRoot() = x; } else { if (XLeft(XParent(z)) == z) { XLeft(XParent(z)) = x; } else { XRight(XParent(z)) = x; } } if (XLMost() != z) ; else { if (XRight(z) == m_Nil) { XLMost() = XParent(z); } else { XLMost() = XMin(x); } } if (XRMost() != z) ; else { if (XLeft(z) == m_Nil) { XRMost() = XParent(z); } else { XRMost() = XMax(x); } } } if (XColor(y) == BLACK) { while (x != XRoot() && XColor(x) == BLACK) { if (x == XLeft(XParent(x))) { Node* _W = XRight(XParent(x)); if (XColor(_W) == RED) { XColor(_W) = BLACK; XColor(XParent(x)) = RED; XLRotate(XParent(x)); _W = XRight(XParent(x)); } if (XColor(XLeft(_W)) == BLACK && XColor(XRight(_W)) == BLACK) { XColor(_W) = RED; x = XParent(x); } else { if (XColor(XRight(_W)) == BLACK) { XColor(XLeft(_W)) = BLACK; XColor(_W) = RED; XRRotate(_W);_W = XRight(XParent(x)); } XColor(_W) = XColor(XParent(x)); XColor(XParent(x)) = BLACK; XColor(XRight(_W)) = BLACK; XLRotate(XParent(x)); break; } } else { Node* _W = XLeft(XParent(x)); if (XColor(_W) == RED) { XColor(_W) = BLACK; XColor(XParent(x)) = RED; XRRotate(XParent(x)); _W = XLeft(XParent(x)); } if (XColor(XRight(_W)) == BLACK && XColor(XLeft(_W)) == BLACK) { XColor(_W) = RED; x = XParent(x); } else { if (XColor(XLeft(_W)) == BLACK) { XColor(XRight(_W)) = BLACK; XColor(_W) = RED; XLRotate(_W); _W = XLeft(XParent(x)); } XColor(_W) = XColor(XParent(x)); XColor(XParent(x)) = BLACK; XColor(XLeft(_W)) = BLACK; XRRotate(XParent(x)); break; } } XColor(x) = BLACK; } } } XDestval(&XValue(y)); XFreeNode(y); --m_Size; return (iT); } Iterator Erase(Iterator iFirst, Iterator iLast) { if (Size() == 0 || iFirst != Begin() || iLast != End()) { while (iFirst != iLast) { Erase(iFirst++); } return iFirst; } else { XErase(XRoot()); XRoot() = m_Nil; m_Size = 0; XLMost() = m_Head; XRMost() = m_Head; return Begin(); } } void Clear() { Erase(Begin(), End()); } Iterator Find(ConstReference iValue) { Iterator i(XLBound(iValue)); return ((i == End() || m_KeyCompare(iValue, i.m_Node->value))? End() : i); } ConstIterator Find(ConstReference iValue) const { ConstIterator i(XLBound(iValue)); return ((i == End() || m_KeyCompare(iValue, i.m_Node->value))? End() : i); } void Swap(XBTree& iTree) { Swap(m_KeyCompare, iTree.m_KeyCompare); if (this->m_Allocator == iTree.m_Allocator) { Swap(m_Head, iTree.m_Head); Swap(m_Size, iTree.m_Size); } else { XBTree _Ts = *this; *this = iTree; iTree = _Ts; } } protected: static Node*& XLeft(Node* iNode) {return ((Node*&)(*iNode).left); } static Node*& XParent(Node* iNode) {return ((Node*&)(*iNode).parent); } static Node*& XRight(Node* iNode) {return iNode->right; } static Color& XColor(Node* iNode) {return iNode->color; } static Reference XValue(Node* iNode){return ((Reference)(*iNode).value); } static Node* XMax(Node* iN) {while (iN->right != m_Nil) iN = iN->right; return iN; } static Node* XMin(Node* iN) {while (iN->left != m_Nil) iN = iN->left; return iN; } Node*& XRoot() const {return m_Head->parent;} Node*& XRMost() const {return m_Head->right;} Node*& XLMost() const {return m_Head->left;} void XLRotate(Node* iN) { Node* y = iN->right; iN->right = y->left; if (y->left != m_Nil) XParent(y->left) = iN; y->parent = iN->parent; if (iN == XRoot()) { XRoot() = y; } else { if (iN == XLeft(iN->parent)) { XLeft(iN->parent) = y; } else { XRight(iN->parent) = y; } } y->left = iN; iN->parent = y; } void XRRotate(Node* iN) { Node* y = iN->left; iN->left = y->right; if (y->right != m_Nil) XParent(y->right) = iN; y->parent = iN->parent; if (iN == XRoot()) XRoot() = y; else if (iN == XRight(iN->parent)) XRight(iN->parent) = y; else XLeft(iN->parent) = y; y->right = iN; iN->parent = y; } Node* XLBound(ConstReference iValue) const { Node* x = XRoot(); Node* y = m_Head; while (x != m_Nil) { if (m_KeyCompare(x->value, iValue)) { x = x->right; } else { y = x; x = x->left; } } return (y); } Node* XUBound(ConstReference iValue) const { Node* x = XRoot(); Node* y = m_Head; while (x != m_Nil) { if (m_KeyCompare(iValue, x->value)) { y = x, x = x->left; } else { x = x->right; } } return (y); } void XInit() { Node* tmp = XBuynode(0, BLACK); { // _Lockit _Lk; :: TODO Thread locking if (m_Nil == 0) { m_Nil = tmp; tmp = 0; m_Nil->left = 0; m_Nil->right = 0; } ++m_NilRefCount; } if (tmp != 0) { XFreeNode(tmp); } m_Head = XBuynode(m_Nil, RED); m_Size = 0; XLMost() = m_Head; XRMost() = m_Head; } void XErase(Node* iNode) { for (Node* n = iNode; n != m_Nil; iNode = n) { XErase(n->right); n = n->left; XDestval(&XValue(iNode)); XFreeNode(iNode); } } Iterator XInsert(Node* iNode, Node* iBefore, ConstReference iValue) { Node* z = XBuynode(iBefore, RED); z->left = m_Nil; z->right= m_Nil; XConsval(&z->value, iValue); ++m_Size; if (iBefore == m_Head || iNode != m_Nil || m_KeyCompare(iValue, iBefore->value)) { iBefore->left = z; if (iBefore == m_Head) { XRoot() = z; XRMost() = z; } else { if (iBefore == XLMost()) XLMost() = z; } } else { iBefore->right = z; if (iBefore == XRMost()) XRMost() = z; } for (iNode = z; iNode != XRoot() && XColor(iNode->parent) == RED; ) { if (iNode->parent == XLeft(XParent(iNode->parent))) { iBefore = XRight(XParent(iNode->parent)); if (iBefore->color == RED) { XColor(iNode->parent) = BLACK; iBefore->color = BLACK; XColor(XParent(iNode->parent)) = RED; iNode = XParent(iNode->parent); } else { if (iNode == XRight(iNode->parent)) { iNode = iNode->parent; XLRotate(iNode); } XColor(iNode->parent) = BLACK; XColor(XParent(iNode->parent)) = RED; XRRotate(XParent(iNode->parent)); } } else { iBefore = XLeft(XParent(iNode->parent)); if (iBefore->color == RED) { XColor(iNode->parent) = BLACK; iBefore->color = BLACK; XColor(XParent(iNode->parent)) = RED; iNode = XParent(iNode->parent); } else { if (iNode == XLeft(iNode->parent)) { iNode = iNode->parent; XRRotate(iNode); } XColor(iNode->parent) = BLACK; XColor(XParent(iNode->parent)) = RED; XLRotate(XParent(iNode->parent)); } } } XColor(XRoot()) = BLACK; return Iterator(z); } // // (De)Allocation methods Node* XBuynode(Node* iParent, Color iColor) { Node* n = new Node; n->parent = iParent; n->color = iColor; return n; } // Construction by placement new void XConsval(Pointer iP, ConstReference iValue) {new ((void*)iP) T(iValue); } void XDestval(Pointer iP) {(iP)->~T(); } void XFreeNode(Node* iN) {delete iN;} // Null reference static Node* m_Nil; static int m_NilRefCount; TCmpFunc m_KeyCompare; Node* m_Head; unsigned int m_Size; }; template typename XBTree::Node* XBTree::m_Nil = 0; template int XBTree::m_NilRefCount = 0; /************************************************ Summary: Not Yet Documented ************************************************/ template class XBinaryTreeNode { public: // Ctors XBinaryTreeNode() : m_Left(NULL),m_Right(NULL){} XBinaryTreeNode( const T & E ) : m_Data( E ), m_Left( NULL ),m_Right( NULL ) { } XBinaryTreeNode( const T & E,XBinaryTreeNode* L, XBinaryTreeNode* R ):m_Data(E),m_Left(L),m_Right(R) { } // Dtor ~XBinaryTreeNode() {} /// // Members // Data T m_Data; // Children XBinaryTreeNode* m_Left; XBinaryTreeNode* m_Right; }; template class XBinaryTree; /************************************************ Summary: Not Yet Documented ************************************************/ template class XBinaryTreeIt { typedef XBinaryTreeNode tNode; typedef XBinaryTree* tTree; typedef XBinaryTreeIt tIterator; public: // Ctors XBinaryTreeIt(const tNode* n, const tTree tree) : m_Tree(tree),m_Node(n){} XBinaryTreeIt(tNode* n=NULL):m_Node(n) {} // Dtor ~XBinaryTreeIt() {} // Operators int operator==(const tIterator& it) const { return m_Node == it.m_Node; } int operator!=(const tIterator& it) const { return m_Node != it.m_Node; } const T& operator*() { return (*m_Node).m_Data; } // T* operator*() { return &(m_Node->m_Data); } tIterator& operator++() { // Prefixe // TODO return *this; } tIterator operator++(int) { tIterator tmp = *this; ++*this; return tmp; } /// // Members // The Binary Tree tTree m_Tree; // Current Node tNode* m_Node; }; /************************************************ Summary: Not Yet Documented ************************************************/ template class XBinaryTree { typedef XBinaryTreeIt tIterator; typedef XBinaryTreeNode tNode; friend class XBinaryTreeIt; public: XBinaryTree() { m_Root = m_NullNode = new tNode; } ~XBinaryTree() { XRemove(m_Root); delete m_NullNode; } void Clear() { XRemove(m_Root); m_Root = m_NullNode; } int GetMemoryOccupation() const { // Childs + this + NullNode return XMemory(m_Root) + sizeof(XBinaryTree) + sizeof(tNode); } tIterator Begin() const { return End(); } tIterator End() const { return tIterator(m_NullNode); } // Infixed iteration void Iterate(void(*f)(const T&,void *),void* arg = NULL) const { XInfixe(m_Root,f,arg); } // Postfixed iteration void BackIterate(void(*f)(const T&,void *),void* arg = NULL) const { XPostfixe(m_Root,f,arg); } // Prefixed iteration void Prefixe(void(*f)(const T&,void *),void* arg = NULL) const { XPrefixe(m_Root,f,arg); } static int XCompare(const void *elem1, const void *elem2 ) { return (*(T*)elem2 - *(T*)elem1); } // Get The Smallest element T GetSmallest() const { if (m_Root == m_NullNode) return (T)0; return XGetSmallest(m_Root); } // Insert an element in the tree (return 0 if it was already there) int Insert(const T& o,VxSortFunc compare = XCompare) { m_NullNode->m_Data = o; tNode** parent = &m_Root; tNode* t = m_Root; while(compare(&t->m_Data,&o) != 0) { if(compare(&o,&t->m_Data)>0) { parent = &t->m_Left; t = t->m_Left; } else { parent = &t->m_Right; t = t->m_Right; } } // The value wasn't found, we insert it if(t == m_NullNode) { *parent = new tNode(o,m_NullNode,m_NullNode);; return 1; } // already in the tree return 0; } // Insert an element in the tree (return 0 if it was already there) int Remove(const T& o,VxSortFunc compare = XCompare) { m_NullNode->m_Data = o; tNode** parent = &m_Root; tNode* t = m_Root; while(compare(&t->m_Data,&o) != 0) { if (compare(&o,&t->m_Data)>0) { parent = &t->m_Left; t = t->m_Left; } else { parent = &t->m_Right; t = t->m_Right; } } // The value was found, we remove it if(t != m_NullNode) { // No left child ? if(t->m_Left == m_NullNode) { // if it's a leaf ? if (t->m_Right == m_NullNode) { delete t; *parent = m_NullNode; } else { // we reup the right tree in place *parent = t->m_Right; delete t; } } else { // There's a left child // No right Child if (t->m_Right == m_NullNode) { // we reup the left tree in place *parent = t->m_Left; delete t; } else { // we have to put the max of the left tree in place tNode* left = t->m_Left; parent = &t; while(left->m_Right != m_NullNode) { parent = &left; left = left->m_Right; } *parent = left->m_Left; t->m_Data = left->m_Data; delete left; } } return 1; } // already in the tree return 0; } // Search an element in the tree int Find(const T& o,VxSortFunc compare = XCompare) const { m_NullNode->m_Data = o; tNode* t = m_Root; while(compare(&t->m_Data,&o) != 0) { if (compare(&o,&t->m_Data)>0) { t = t->m_Left; } else { t = t->m_Right; } } return t != m_NullNode; } // Search an element in the tree T* FindPtr(const T& o,VxSortFunc compare = XCompare) const { m_NullNode->m_Data = o; tNode* t = m_Root; while(compare(&t->m_Data,&o) != 0) { if (compare(&o,&t->m_Data)>0) { t = t->m_Left; } else { t = t->m_Right; } } return (t != m_NullNode) ? &t->m_Data : NULL; } private: // Methods void XRemove(tNode* t) { if( t != m_NullNode) { XRemove( t->m_Left ); XRemove( t->m_Right ); delete t; } } int XMemory(tNode* t) { if( t != m_NullNode) { return XMemory( t->m_Left ) + XMemory( t->m_Right ) + sizeof(tNode); } else return 0; } // Get The Smallest element T XGetSmallest(tNode* t) const { if ((t->m_Left == m_NullNode) && (t->m_Right == m_NullNode)) return t->m_Data; if (t->m_Left != m_NullNode) return XGetSmallest(t->m_Left); if (t->m_Right!= m_NullNode) return XGetSmallest(t->m_Right); return t->m_Data; } void XInfixe(tNode* t,void(*f)(const T&,void *),void* arg) const { if( t != m_NullNode) { XInfixe(t->m_Left,f,arg); f(t->m_Data,arg); XInfixe(t->m_Right,f,arg); } } void XPrefixe(tNode* t,void(*f)(const T&,void *),void* arg) const { if( t != m_NullNode) { f(t->m_Data,arg); XPrefixe(t->m_Left,f,arg); XPrefixe(t->m_Right,f,arg); } } void XPostfixe(tNode* t,void(*f)(const T&,void *),void* arg) const { if( t != m_NullNode) { XPostfixe(t->m_Right,f,arg); f(t->m_Data,arg); XPostfixe(t->m_Left,f,arg); } } // Members // Root tNode* m_Root; // Null Node tNode* m_NullNode; }; #endif // BINARYTREE_H