added RedBlackTree::remove()
partially added RedBlackTree::getIterator()
This commit is contained in:
		| @ -80,7 +80,8 @@ protected: | ||||
| }; | ||||
|  | ||||
| template <typename T, typename EQUALER, typename NODE, typename GET_T> | ||||
| class LinkedListIterator { | ||||
| class LinkedListIterator  | ||||
| { | ||||
| public: | ||||
| 	friend class LinkedList<T,EQUALER>; | ||||
| 	typedef NODE Node; | ||||
|  | ||||
| @ -49,29 +49,25 @@ public: | ||||
| 		BLACK | ||||
| 	}; | ||||
|  | ||||
| 	enum Child | ||||
| 	{ | ||||
| 		LEFT, | ||||
| 		RIGHT | ||||
| 	}; | ||||
|  | ||||
| 	T value; // you can use this variable or accessor functions below | ||||
|  | ||||
| protected: | ||||
| 	Color color; | ||||
| 	SelfType* parent; | ||||
| 	SelfType* child[2]; // left and right | ||||
| 	SelfType* left; // left child | ||||
| 	SelfType* right; // right child | ||||
|  | ||||
| 	RedBlackTreeNode() | ||||
| 	RedBlackTreeNode(): color (BLACK), parent (this), left (this), right (this) | ||||
| 	{ | ||||
| 		// no initialization. make sure to initialize member variables later | ||||
| 		// no initialization on 'value' in this constructor. | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right): | ||||
| 		value (value), color (color), parent (parent) | ||||
| 		value (value), color (color), parent (parent), left (left), right (right) | ||||
| 	{ | ||||
| 		this->child[LEFT] = left; | ||||
| 		this->child[RIGHT] = right; | ||||
| 		QSE_ASSERT (parent != this); | ||||
| 		QSE_ASSERT (left != this); | ||||
| 		QSE_ASSERT (right != this); | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| @ -79,31 +75,36 @@ public: | ||||
| 	const T& getValue () const { return this->value; } | ||||
| 	void setValue (const T& v) { this->value = v; } | ||||
|  | ||||
| 	bool isNil () const | ||||
| 	{ | ||||
| 		return this->parent == this; // && this->left == this && this->right == this; | ||||
| 	} | ||||
|  | ||||
| 	bool notNil () const | ||||
| 	{ | ||||
| 		return !this->isNil (); | ||||
| 	} | ||||
|  | ||||
| 	bool isBlack () const  { return this->color == BLACK; } | ||||
| 	bool isRed () const { return this->color == RED; } | ||||
| 	void setBlack () { this->color = BLACK; } | ||||
| 	void setRed () { this->color = RED; } | ||||
|  | ||||
| 	SelfType* getParent () { return this->parent; } | ||||
| 	const SelfType* getParent () const { return this->parent; } | ||||
|  | ||||
| 	SelfType* getLeft () { return this->child[LEFT]; } | ||||
| 	const SelfType* getLeft () const { return this->child[LEFT]; } | ||||
| 	SelfType* getLeft () { return this->left; } | ||||
| 	const SelfType* getLeft () const { return this->left; } | ||||
|  | ||||
| 	SelfType* getRight () { return this->child[RIGHT]; } | ||||
| 	const SelfType* getRight () const { return this->child[RIGHT]; } | ||||
| 	SelfType* getRight () { return this->right; } | ||||
| 	const SelfType* getRight () const { return this->right; } | ||||
|  | ||||
| 	SelfType* getChild (int idx) { return idx == 0? this->left: this->right; } | ||||
| #if 0 | ||||
| 	void setBlack () { this->color = BLACK; } | ||||
| 	void setRed () { this->color = RED; } | ||||
| 	void setParent (SelfType* node) { this->parent = node; } | ||||
| 	void setLeft (SelfType* node) { this->child[LEFT] = node; } | ||||
| 	void setRight (SelfType* node) { this->child[RIGHT] = node; } | ||||
|  | ||||
| 	void setAll (Color color, SelfType* parent, SelfType* left, SelfType* right) | ||||
| 	{ | ||||
| 		this->color = color; | ||||
| 		this->parent = parent; | ||||
| 		this->child[LEFT] = left; | ||||
| 		this->child[RIGHT] = right; | ||||
| 	} | ||||
| 	void setLeft (SelfType* node) { this->left = node; } | ||||
| 	void setRight (SelfType* node) { this->right = node; } | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| @ -116,12 +117,190 @@ struct RedBlackTreeComparator | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template <typename T, typename COMPARATOR, typename NODE, typename GET_T> | ||||
| class RedBlackTreeIterator | ||||
| { | ||||
| public: | ||||
| 	typedef NODE Node; | ||||
| 	typedef RedBlackTreeIterator<T,COMPARATOR,NODE,GET_T> SelfType; | ||||
|  | ||||
| 	RedBlackTreeIterator (): current (QSE_NULL), previous (QSE_NULL), next_action (0) {} | ||||
| 	RedBlackTreeIterator (Node* root): current (root)  | ||||
| 	{ | ||||
| 		this->previous = root->getParent(); | ||||
| 		this->__get_next_node (); | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	void __get_next_node () | ||||
| 	{ | ||||
| 		int l = 1, r = 0;  // TODO: | ||||
|  | ||||
| 		while (/*this->current &&*/ this->current->notNil()) | ||||
| 		{ | ||||
| 			if (this->previous == this->current->getParent()) | ||||
| 			{ | ||||
| 				/* the previous node is the parent of the current node. | ||||
| 				 * it indicates that we're going down to the getChild(l) */ | ||||
| 				if (this->current->getChild(l)->notNil()) | ||||
| 				{ | ||||
| 					/* go to the getChild(l) child */ | ||||
| 					this->previous = this->current; | ||||
| 					this->current = this->current->getChild(l); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					this->next_action = 1; | ||||
| 					break; | ||||
| 					//if (walker (rbt, this->current, ctx) == QSE_RBT_WALK_STOP) break; | ||||
|  | ||||
| #if 0 | ||||
| 					if (this->current->getChild(r)->notNil()) | ||||
| 					{ | ||||
| 						/* go down to the right node if exists */ | ||||
| 						this->previous = this->current; | ||||
| 						this->current = this->current->getChild(r); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						/* otherwise, move up to the parent */ | ||||
| 						this->previous = this->current; | ||||
| 						this->current = this->current->getParent(); | ||||
| 					} | ||||
| #endif | ||||
| 				} | ||||
| 			} | ||||
| 			else if (this->previous == this->current->getChild(l)) | ||||
| 			{ | ||||
| 				/* the left child has been already traversed */ | ||||
|  | ||||
| 				this->next_action = 2; | ||||
| 				break; | ||||
| 				//if (walker (rbt, this->current, ctx) == QSE_RBT_WALK_STOP) break; | ||||
|  | ||||
| #if 0 | ||||
| 				if (this->current->getChild(r)->notNil()) | ||||
| 				{ | ||||
| 					/* go down to the right node if it exists */  | ||||
| 					this->previous = this->current; | ||||
| 					this->current = this->current->getChild(r); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					/* otherwise, move up to the parent */ | ||||
| 					this->previous = this->current; | ||||
| 					this->current = this->current->getParent(); | ||||
| 				} | ||||
| #endif | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* both the left child and the right child have been traversed */ | ||||
| 				QSE_ASSERT (this->previous == this->current->getChild(r)); | ||||
| 				/* just move up to the parent */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getParent(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void get_next_node () | ||||
| 	{ | ||||
| 		int l = 1, r = 0;  // TODO: | ||||
|  | ||||
| 		if (next_action ==  1) | ||||
| 		{ | ||||
| 			if (this->current->getChild(r)->notNil()) | ||||
| 			{ | ||||
| 				/* go down to the right node if exists */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getChild(r); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* otherwise, move up to the parent */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getParent(); | ||||
| 			} | ||||
| 		} | ||||
| 		else if (next_action == 2) | ||||
| 		{ | ||||
| 			if (this->current->getChild(r)->notNil()) | ||||
| 			{ | ||||
| 				/* go down to the right node if it exists */  | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getChild(r); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* otherwise, move up to the parent */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getParent(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		this->__get_next_node (); | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	SelfType& operator++ () // prefix increment | ||||
| 	{ | ||||
| 		this->get_next_node (); | ||||
| 		return *this; | ||||
| 	} | ||||
|  | ||||
| 	SelfType operator++ (int) // postfix increment | ||||
| 	{ | ||||
| 		SelfType saved (*this); | ||||
| 		this->get_next_node (); | ||||
| 		return saved; | ||||
| 	} | ||||
|  | ||||
| 	bool isLegit() const | ||||
| 	{ | ||||
| 		return current->notNil(); | ||||
| 	} | ||||
|  | ||||
| 	GET_T& operator* () // dereference | ||||
| 	{ | ||||
| 		return this->current->getValue(); | ||||
| 	} | ||||
|  | ||||
| 	GET_T& getValue () | ||||
| 	{ | ||||
| 		return this->current->getValue(); | ||||
| 	} | ||||
|  | ||||
| 	// no setValue(). | ||||
|  | ||||
| 	Node* getNode () | ||||
| 	{ | ||||
| 		return this->current; | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	Node* current; | ||||
| 	Node* previous; | ||||
| 	int next_action; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /// | ||||
| /// | ||||
| ///   A node is either red or black. | ||||
| ///   The root is black. | ||||
| ///   All leaves (NIL) are black. (All leaves are same color as the root.) | ||||
| ///   Every red node must have two black child nodes. | ||||
| ///   Every path from a given node to any of its descendant NIL nodes contains the same number of black nodes. | ||||
| /// | ||||
| template <typename T, typename COMPARATOR = RedBlackTreeComparator<T> > | ||||
| class RedBlackTree: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef RedBlackTree<T,COMPARATOR> SelfType; | ||||
| 	typedef RedBlackTreeNode<T,COMPARATOR> Node; | ||||
| 	typedef RedBlackTreeIterator<T,COMPARATOR,Node,T> Iterator; | ||||
| 	typedef RedBlackTreeIterator<T,COMPARATOR,const Node,const T> ConstIterator; | ||||
|  | ||||
| 	typedef RedBlackTreeComparator<T> DefaultComparator; | ||||
|  | ||||
| @ -129,7 +308,7 @@ public: | ||||
| 	{ | ||||
| 		// initialize nil | ||||
| 		this->nil = new(&this->mp) Node(); | ||||
| 		this->nil->setAll (Node::BLACK, this->nil, this->nil, this->nil); | ||||
| //		this->nil->setAll (Node::BLACK, this->nil, this->nil, this->nil); | ||||
|  | ||||
| 		// set root to nil | ||||
| 		this->root = this->nil; | ||||
| @ -137,10 +316,13 @@ public: | ||||
|  | ||||
| 	RedBlackTree (const RedBlackTree& rbt) | ||||
| 	{ | ||||
| 		/* TODO */ | ||||
| 	} | ||||
|  | ||||
| 	~RedBlackTree () | ||||
| 	{ | ||||
| 		this->clear (); | ||||
| 		this->dispose_node (this->nil); | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTree& operator= (const RedBlackTree& rbt) | ||||
| @ -169,16 +351,6 @@ public: | ||||
| 		return this->node_count <= 0; | ||||
| 	} | ||||
|  | ||||
| 	bool isNil (Node* node) const | ||||
| 	{ | ||||
| 		return node == this->nil; | ||||
| 	} | ||||
|  | ||||
| 	bool notNil (Node* node) const | ||||
| 	{ | ||||
| 		return node != this->nil; | ||||
| 	} | ||||
|  | ||||
| 	Node* getRoot () | ||||
| 	{ | ||||
| 		return this->root; | ||||
| @ -190,18 +362,26 @@ public: | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	void dispose_node (Node* node) | ||||
| 	{ | ||||
| 		//call the destructor | ||||
| 		node->~Node ();  | ||||
| 		// free the memory | ||||
| 		::operator delete (node, &this->mp); | ||||
| 	} | ||||
|  | ||||
| 	Node* find_node (const T& datum) const | ||||
| 	{ | ||||
| 		Node* node = this->root; | ||||
|  | ||||
| 		// normal binary tree search | ||||
| 		while (notNil (node)) | ||||
| 		while (node->notNil()) | ||||
| 		{ | ||||
| 			int n = this->comparator (datum, node->value); | ||||
| 			if (n == 0) return node; | ||||
|  | ||||
| 			if (n > 0) node = node->getRight(); | ||||
| 			else /* if (n < 0) */ node = node->getLeft(); | ||||
| 			if (n > 0) node = node->right; | ||||
| 			else /* if (n < 0) */ node = node->left; | ||||
| 		} | ||||
|  | ||||
| 		return QSE_NULL; | ||||
| @ -247,33 +427,33 @@ protected: | ||||
|  | ||||
| 		QSE_ASSERT (pivot != QSE_NULL); | ||||
|  | ||||
| 		parent = pivot->getParent(); | ||||
| 		parent = pivot->parent; | ||||
| 		if (leftwise) | ||||
| 		{ | ||||
| 			// y for leftwise rotation | ||||
| 			z = pivot->getRight(); | ||||
| 			z = pivot->right; | ||||
| 			// c1 for leftwise rotation | ||||
| 			c = z->getLeft(); | ||||
| 			c = z->left; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// x for rightwise rotation | ||||
| 			z = pivot->getLeft(); | ||||
| 			z = pivot->left; | ||||
| 			// c2 for rightwise rotation | ||||
| 			c = z->getRight(); | ||||
| 			c = z->right; | ||||
| 		} | ||||
|  | ||||
| 		z->setParent (parent); | ||||
| 		if (notNil (parent)) | ||||
| 		z->parent = parent; | ||||
| 		if (parent->notNil()) | ||||
| 		{ | ||||
| 			if (parent->getLeft() == pivot) | ||||
| 			if (parent->left == pivot) | ||||
| 			{ | ||||
| 				parent->setLeft (z); | ||||
| 				parent->left = z; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				QSE_ASSERT (parent->getRight() == pivot); | ||||
| 				parent->setRight (z); | ||||
| 				QSE_ASSERT (parent->right == pivot); | ||||
| 				parent->right = z; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| @ -284,51 +464,61 @@ protected: | ||||
|  | ||||
| 		if (leftwise) | ||||
| 		{ | ||||
| 			z->setLeft (pivot); | ||||
| 			pivot->setRight (c); | ||||
| 			z->left = pivot; | ||||
| 			pivot->right = c; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			z->setRight (pivot); | ||||
| 			pivot->setLeft (c); | ||||
| 			z->right = pivot; | ||||
| 			pivot->left = c; | ||||
| 		} | ||||
|  | ||||
| 		if (notNil(pivot)) pivot->setParent (z); | ||||
| 		if (notNil(c)) c->setParent (pivot); | ||||
| 		if (pivot->notNil()) pivot->parent = z; | ||||
| 		if (c->notNil()) c->parent = pivot; | ||||
| 	} | ||||
|  | ||||
| 	void adjust (Node* node) | ||||
| 	void rotate_left (Node* pivot) | ||||
| 	{ | ||||
| 		this->rotate (pivot, true); | ||||
| 	} | ||||
|  | ||||
| 	void rotate_right (Node* pivot) | ||||
| 	{ | ||||
| 		this->rotate (pivot, false); | ||||
| 	} | ||||
|  | ||||
| 	void rebalance_for_injection (Node* node) | ||||
| 	{ | ||||
| 		while (node != this->root) | ||||
| 		{ | ||||
| 			Node* tmp, * tmp2, * x_par, * x_par_par; | ||||
| 			Node* tmp, * tmp2, * x_par, * x_grand_par; | ||||
| 			bool leftwise; | ||||
|  | ||||
| 			x_par = node->getParent (); | ||||
| 			if (x_par->isBlack()) break; | ||||
| 			x_par = node->parent; | ||||
| 			if (x_par->color == Node::BLACK) break; | ||||
|  | ||||
| 			QSE_ASSERT (notNil (x_par->parent)); | ||||
| 			QSE_ASSERT (x_par->parent->notNil()); | ||||
|  | ||||
| 			x_par_par = x_par->getParent (); | ||||
| 			if (x_par == x_par_par->getLeft ())  | ||||
| 			x_grand_par = x_par->parent; | ||||
| 			if (x_par == x_grand_par->left) | ||||
| 			{ | ||||
| 				tmp = x_par_par->getRight (); | ||||
| 				tmp2 = x_par->getRight (); | ||||
| 				tmp = x_grand_par->right; | ||||
| 				tmp2 = x_par->right; | ||||
| 				leftwise = true; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				tmp = x_par_par->getLeft (); | ||||
| 				tmp2 = x_par->getLeft (); | ||||
| 				tmp = x_grand_par->left; | ||||
| 				tmp2 = x_par->left; | ||||
| 				leftwise = false; | ||||
| 			} | ||||
|  | ||||
| 			if (tmp->isRed ()) | ||||
| 			if (tmp->color == Node::RED) | ||||
| 			{ | ||||
| 				x_par->setBlack (); | ||||
| 				tmp->setBlack (); | ||||
| 				x_par_par->setRed (); | ||||
| 				node = x_par_par; | ||||
| 				x_par->color = Node::BLACK; | ||||
| 				tmp->color = Node::BLACK; | ||||
| 				x_grand_par->color = Node::RED; | ||||
| 				node = x_grand_par; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| @ -336,17 +526,173 @@ protected: | ||||
| 				{ | ||||
| 					node = x_par; | ||||
| 					this->rotate (node, leftwise); | ||||
| 					x_par = node->getParent(); | ||||
| 					x_par_par = x_par->getParent(); | ||||
| 					x_par = node->parent; | ||||
| 					x_grand_par = x_par->parent; | ||||
| 				} | ||||
|  | ||||
| 				x_par->setBlack(); | ||||
| 				x_par_par->setRed(); | ||||
| 				this->rotate (x_par_par, !leftwise); | ||||
| 				x_par->color = Node::BLACK; | ||||
| 				x_grand_par->color = Node::RED; | ||||
| 				this->rotate (x_grand_par, !leftwise); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void rebalance_for_removal (Node* node, Node* par) | ||||
| 	{ | ||||
| 		while (node != this->root && node->color == Node::BLACK) | ||||
| 		{ | ||||
| 			Node* tmp; | ||||
|  | ||||
| 			if (node == par->left) | ||||
| 			{ | ||||
| 				tmp = par->right; | ||||
| 				if (tmp->color == Node::RED) | ||||
| 				{ | ||||
| 					tmp->color = Node::BLACK; | ||||
| 					par->color = Node::RED; | ||||
| 					this->rotate_left (par); | ||||
| 					tmp = par->right; | ||||
| 				} | ||||
|  | ||||
| 				if (tmp->left->color == Node::BLACK && | ||||
| 				    tmp->right->color == Node::BLACK) | ||||
| 				{ | ||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | ||||
| 					node = par; | ||||
| 					par = node->parent; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					if (tmp->right->color == Node::BLACK) | ||||
| 					{ | ||||
| 						if (tmp->left->notNil()) | ||||
| 							tmp->left->color = Node::BLACK; | ||||
| 						tmp->color = Node::RED; | ||||
| 						this->rotate_right (tmp); | ||||
| 						tmp = par->right; | ||||
| 					} | ||||
|  | ||||
| 					tmp->color = par->color; | ||||
| 					if (par->notNil()) par->color = Node::BLACK; | ||||
| 					if (tmp->right->color == Node::RED) | ||||
| 						tmp->right->color = Node::BLACK; | ||||
|  | ||||
| 					this->rotate_left (par); | ||||
| 					node = this->root; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				QSE_ASSERT (node == par->right); | ||||
| 				tmp = par->left; | ||||
| 				if (tmp->color == Node::RED) | ||||
| 				{ | ||||
| 					tmp->color = Node::BLACK; | ||||
| 					par->color = Node::RED; | ||||
| 					this->rotate_right (par); | ||||
| 					tmp = par->left; | ||||
| 				} | ||||
|  | ||||
| 				if (tmp->left->color == Node::BLACK && | ||||
| 				    tmp->right->color == Node::BLACK) | ||||
| 				{ | ||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | ||||
| 					node = par; | ||||
| 					par = node->parent; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					if (tmp->left->color == Node::BLACK) | ||||
| 					{ | ||||
| 						if (tmp->right->notNil()) | ||||
| 							tmp->right->color = Node::BLACK; | ||||
| 						tmp->color = Node::RED; | ||||
| 						this->rotate_left (tmp); | ||||
| 						tmp = par->left; | ||||
| 					} | ||||
| 					tmp->color = par->color; | ||||
| 					if (par->notNil()) par->color = Node::BLACK; | ||||
| 					if (tmp->left->color == Node::RED) | ||||
| 						tmp->left->color = Node::BLACK; | ||||
|  | ||||
| 					this->rotate_right (par); | ||||
| 					node = this->root; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		node->color = Node::BLACK; | ||||
| 	} | ||||
|  | ||||
| 	void remove_node (Node* node) | ||||
| 	{ | ||||
| 		Node* x, * y, * par; | ||||
|  | ||||
| 		QSE_ASSERT (node && node->notNil()); | ||||
|  | ||||
| 		if (node->left->isNil() || node->right->isNil()) | ||||
| 		{ | ||||
| 			y = node; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* find a successor with NIL as a child */ | ||||
| 			y = node->right; | ||||
| 			while (y->left->notNil()) y = y->left; | ||||
| 		} | ||||
|  | ||||
| 		x = (y->left->isNil())? y->right: y->left; | ||||
|  | ||||
| 		par = y->parent; | ||||
| 		if (x->notNil()) x->parent = par; | ||||
|  | ||||
| 		if (par->notNil()) // if (par) | ||||
| 		{ | ||||
| 			if (y == par->left) | ||||
| 				par->left = x; | ||||
| 			else | ||||
| 				par->right = x; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			this->root = x; | ||||
| 		} | ||||
|  | ||||
| 		if (y == node) | ||||
| 		{ | ||||
| 			if (y->color == Node::BLACK && x->notNil()) | ||||
| 				this->rebalance_for_removal (x, par);  | ||||
|  | ||||
| 			this->dispose_node (y); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (y->color == Node::BLACK && x->notNil()) | ||||
| 				this->rebalance_for_removal (x, par); | ||||
|  | ||||
| 			if (node->parent->notNil()) //if (node->parent) | ||||
| 			{ | ||||
| 				if (node->parent->left == node) node->parent->left = y; | ||||
| 				if (node->parent->right == node) node->parent->right = y; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				this->root = y; | ||||
| 			} | ||||
|  | ||||
| 			y->parent = node->parent; | ||||
| 			y->left = node->left; | ||||
| 			y->right = node->right; | ||||
| 			y->color = node->color; | ||||
|  | ||||
| 			if (node->left->parent == node) node->left->parent = y; | ||||
| 			if (node->right->parent == node) node->right->parent = y; | ||||
|  | ||||
| 			this->dispose_node (node); | ||||
| 		} | ||||
|  | ||||
| 		this->node_count--; | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	Node* search (const T& datum) | ||||
| @ -364,41 +710,27 @@ public: | ||||
| 		Node* x_cur = this->root; | ||||
| 		Node* x_par = this->nil; | ||||
|  | ||||
| 		while (notNil (x_cur)) | ||||
| 		while (x_cur->notNil()) | ||||
| 		{ | ||||
| 			int n = this->comparator (datum, x_cur->value); | ||||
| 			if (n == 0) | ||||
| 			{ | ||||
| 			#if 0 | ||||
| 				switch (opt) | ||||
| 				{ | ||||
| 					case UPSERT: | ||||
| 					case UPDATE: | ||||
| 						return change_pair_val (rbt, x_cur, vptr, vlen); | ||||
|  | ||||
| 					case ENSERT: | ||||
| 						/* return existing pair */ | ||||
| 				if (injected) *injected = false; | ||||
| 				if (mode <= -1) return QSE_NULL; // return failure | ||||
| 				if (mode >= 1) x_cur->value = datum; | ||||
| 				return x_cur; | ||||
|  | ||||
| 					case INSERT: | ||||
| 						/* return failure */ | ||||
| 						return QSE_NULL; | ||||
| 				} | ||||
| 			#endif | ||||
| 			} | ||||
|  | ||||
| 			x_par = x_cur; | ||||
|  | ||||
| 			if (n > 0) x_cur = x_cur->getRight (); | ||||
| 			else /* if (n < 0) */ x_cur = x_cur->getLeft (); | ||||
| 			if (n > 0) x_cur = x_cur->right; | ||||
| 			else /* if (n < 0) */ x_cur = x_cur->left; | ||||
| 		} | ||||
|  | ||||
| 		//if (opt == UPDATE) return QSE_NULL; | ||||
|  | ||||
| 		Node* x_new = new(&this->mp) Node (datum, Node::RED, this->nil, this->nil, this->nil); | ||||
| 		if (isNil (x_par)) | ||||
| 		if (x_par->isNil()) | ||||
| 		{ | ||||
| 			QSE_ASSERT (isNil (this->root)); | ||||
| 			QSE_ASSERT (this->root->isNil()); | ||||
| 			this->root = x_new; | ||||
| 		} | ||||
| 		else | ||||
| @ -406,22 +738,23 @@ public: | ||||
| 			int n = this->comparator (datum, x_par->value); | ||||
| 			if (n > 0) | ||||
| 			{ | ||||
| 				QSE_ASSERT (isNil (x_par->getRight ())); | ||||
| 				x_par->setRight (x_new); | ||||
| 				QSE_ASSERT (x_par->right->isNil()); | ||||
| 				x_par->right = x_new; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				QSE_ASSERT (isNil (x_par->getLeft ())); | ||||
| 				x_par->setLeft (x_new); | ||||
| 				QSE_ASSERT (x_par->left->isNil()); | ||||
| 				x_par->left = x_new; | ||||
| 			} | ||||
|  | ||||
| 			x_new->setParent (x_par); | ||||
| 			this->adjust (x_new); | ||||
| 			x_new->parent = x_par; | ||||
| 			this->rebalance_for_injection (x_new); | ||||
| 		} | ||||
|  | ||||
| 		this->root->setBlack (); | ||||
| 		this->root->color = Node::BLACK; | ||||
| 		this->node_count++; | ||||
|  | ||||
| 		if (injected) *injected = true; // indicate that a new node has been injected | ||||
| 		return x_new; | ||||
| 	} | ||||
|  | ||||
| @ -440,20 +773,37 @@ public: | ||||
| 		return this->inject (datum, 1, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| #if 0 | ||||
| 	Node* update (const T& datum) | ||||
| 	{ | ||||
| 		Node* node = this->find_node (datum); | ||||
| 		if (node) node->value = datum; | ||||
| 		return node; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	int remove (const T& datum) | ||||
| 	{ | ||||
| 		Node* node = this->find_node (datum); | ||||
| 		if (node == QSE_NULL) return -1; | ||||
|  | ||||
| 		this->remove_node (node); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	void clear (bool clear_mpool = false) | ||||
| 	{ | ||||
| 		while (this->root->notNil()) this->remove_node (this->root); | ||||
| 	} | ||||
|  | ||||
| 	Iterator getIterator () const | ||||
| 	{ | ||||
| 		return Iterator (this->root); | ||||
| 	} | ||||
|  | ||||
| 	void dump (Node* node) | ||||
| 	{ | ||||
| 		printf ("%d %d\n", node->value.getX(), node->value.getY()); | ||||
| 		if (notNil(node->getLeft())) dump (node->getLeft()); | ||||
| 		if (notNil(node->getRight())) dump (node->getRight()); | ||||
| 		if (node->left->notNil()) this->dump (node->left); | ||||
| 		if (node->right->notNil()) this->dump (node->right); | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
|  | ||||
		Reference in New Issue
	
	Block a user