/*------------------------------------------------------------------------*/ /* */ /* BINIMP.CPP */ /* */ /* Copyright (c) 1993, 1994 Borland International */ /* All Rights Reserved */ /* */ /*------------------------------------------------------------------------*/ #if !defined( CLASSLIB_BINIMP_H ) #include #endif TBinarySearchTreeBase::TBinarySearchTreeBase() : Root(0), ItemsInContainer(0) { } int TBinarySearchTreeBase::InsertNode( BinNode *node ) { BinNode *Current = Root; BinNode *Parent = 0; while( Current ) { Parent = Current; Current = LessThan( node, Current ) ? Current->Left : Current->Right; } if( Parent == 0 ) Root = node; else { if( LessThan( node, Parent ) ) Parent->Left = node; else Parent->Right = node; } ItemsInContainer++; return 1; } int TBinarySearchTreeBase::RemoveNode( BinNode *node, int del ) { BinNode *Current = Root; BinNode *Parent = 0; while( Current ) { if( EqualTo( node, Current ) ) return RemNode( Current, Parent, del ); else { Parent = Current; Current = LessThan( node, Current ) ? Current->Left : Current->Right; } } return 0; } TBinarySearchTreeBase::BinNode *TBinarySearchTreeBase::FindNode( BinNode *node ) { BinNode *Current = Root; while( Current ) { if( EqualTo( node, Current ) ) return Current; else Current = LessThan( node, Current ) ? Current->Left : Current->Right; } return 0; } int TBinarySearchTreeBase::RemNode( BinNode *node, BinNode *parent, int del ) { // See R. Sedgewick, "Algorithms, 2nd edition", // Addison-Wesley 1988, p.210. BinNode *Original = node; if( Original->Right == 0 ) node = node->Left; else if( Original->Right->Left ) { BinNode *Current = Original->Right; while( Current->Left->Left ) Current = Current->Left; node = Current->Left; Current->Left = node->Right; node->Left = Original->Left; node->Right = Original->Right; } else { node = node->Right; node->Left = Original->Left; } if( parent == 0 ) Root = node; else if( LessThan( Original, parent ) ) parent->Left = node; else parent->Right = node; DeleteNode( Original, del ); ItemsInContainer--; return 1; } class TBinaryTreeKiller : public TBinaryTreeInternalIteratorBase { public: TBinaryTreeKiller( TBinarySearchTreeBase& tree, int del ) : TBinaryTreeInternalIteratorBase( tree, TBinarySearchTreeBase::PostOrder ), Del(del) {} private: virtual void Apply( TBinarySearchTreeBase::BinNode _FAR *node, TBinarySearchTreeBase::BinNode _FAR *parent ); int Del; TBinaryTreeKiller( const TBinaryTreeKiller& ); const TBinaryTreeKiller& operator = ( const TBinaryTreeKiller& ); }; void TBinaryTreeKiller::Apply( TBinarySearchTreeBase::BinNode _FAR *node, TBinarySearchTreeBase::BinNode _FAR *parent ) { Tree().RemNode( node, parent, Del ); } void TBinarySearchTreeBase::Flush( int del ) { if( Root != 0 ) TBinaryTreeKiller( *this, del ).Iterate(); } void TBinaryTreeInternalIteratorBase::Iterate() { TBinarySearchTreeBase::BinNode _FAR *Current = Node; TBinarySearchTreeBase::BinNode _FAR *Prev = 0; TBinarySearchTreeBase::BinNode _FAR *Next = 0; step2: if( Order == TBinarySearchTreeBase::PreOrder ) Apply( Current, 0 ); Next = Current->Left; if( Next != 0 ) { Current->Left = Prev; Prev = Current; Current = Next; goto step2; } step4: if( Order == TBinarySearchTreeBase::InOrder ) Apply( Current, 0 ); Next = Current->Right; if( Next != 0 ) { Current->Right = Prev; Prev = Current; Current = Next; goto step2; } step6: if( Prev == 0 ) { if( Order == TBinarySearchTreeBase::PostOrder ) Apply( Current, 0 ); return; } if( Tree().LessThan( Current, Prev ) ) { TBinarySearchTreeBase::BinNode _FAR *Temp = Current; Next = Prev->Left; Prev->Left = Current; Current = Prev; Prev = Next; if( Order == TBinarySearchTreeBase::PostOrder ) Apply( Temp, Current ); goto step4; } else { TBinarySearchTreeBase::BinNode _FAR *Temp = Current; Next = Prev->Right; Prev->Right = Current; Current = Prev; Prev = Next; if( Order == TBinarySearchTreeBase::PostOrder ) Apply( Temp, Current ); goto step6; } } TBinaryTreeExternalIteratorBase::TBinaryTreeExternalIteratorBase( TBinarySearchTreeBase& tree, TBinarySearchTreeBase::IteratorOrder order ) : Stack( new TStackAsList ), Tree(&tree), Current( tree.Root ), Order( order ) { Restart(); } TBinaryTreeExternalIteratorBase::~TBinaryTreeExternalIteratorBase() { delete Stack; } void TBinaryTreeExternalIteratorBase::Restart() { Stack->Flush(); Current = Tree->Root; LeftVisited = RightVisited = 0; Processed = 0; } TBinarySearchTreeBase::BinNode *TBinaryTreeExternalIteratorBase::Next() { if( Current == 0 ) return 0; for(;;) { if( Order == TBinarySearchTreeBase::PreOrder && !Processed ) { Processed = 1; return Current; } if( Current->Left != 0 && !LeftVisited ) { Stack->Push( Current ); Current = Current->Left; LeftVisited = RightVisited = 0; Processed = 0; } else if( Current->Right != 0 && !RightVisited ) { TBinarySearchTreeBase::BinNode *Res = 0; if( Order == TBinarySearchTreeBase::InOrder ) Res = Current; Stack->Push( Current ); Current = Current->Right; LeftVisited = RightVisited = 0; Processed = 0; if( Res != 0 ) return Res; } else { if( Stack->IsEmpty() ) { if( Processed == 0 ) { Processed = 1; } else { Current = 0; } return Current; } else { TBinarySearchTreeBase::BinNode *Res; switch( Order ) { case TBinarySearchTreeBase::PreOrder: // This node has already been // processed, so we have further to go. Res = 0; // This node's parent has // already been processed Processed = 1; break; case TBinarySearchTreeBase::InOrder: if( IsInOrder() ) { // This node needs to be processed. Res = Current; } else { // Node has already been processed. Res = 0; } // If we're the right-hand child, our parent // has already been processed. Processed = Stack->Top()->Right == Current; break; case TBinarySearchTreeBase::PostOrder: // This node needs to be processed. Res = Current; // This node's parent has not been processed. Processed = 0; break; } LeftVisited = 1; RightVisited = Stack->Top()->Right == Current; Current = Stack->Pop(); if( Res != 0 ) return Res; } } } }