enhanced RedBlackTree's iterator
This commit is contained in:
		| @ -49,6 +49,8 @@ public: | |||||||
| 		BLACK | 		BLACK | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	// You must take extreme care not to screw up the whole tree by | ||||||
|  | 	// overriding the 'value' variable with a randome value. | ||||||
| 	T value; // you can use this variable or accessor functions below | 	T value; // you can use this variable or accessor functions below | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| @ -92,19 +94,18 @@ public: | |||||||
| 	const SelfType* getParent () const { return this->parent; } | 	const SelfType* getParent () const { return this->parent; } | ||||||
|  |  | ||||||
| 	SelfType* getLeft () { return this->left; } | 	SelfType* getLeft () { return this->left; } | ||||||
| 	const SelfType* getLeft () const { return this->left; } | 	const SelfType* getLeftConst () const { return this->left; } | ||||||
|  |  | ||||||
| 	SelfType* getRight () { return this->right; } | 	SelfType* getRight () { return this->right; } | ||||||
| 	const SelfType* getRight () const { return this->right; } | 	const SelfType* getRightConst () const { return this->right; } | ||||||
|  |  | ||||||
|  | 	//void setBlack () { this->color = BLACK; } | ||||||
|  | 	//void setRed () { this->color = RED; } | ||||||
|  | 	//void setParent (SelfType* node) { this->parent = node; } | ||||||
|  | 	//void setLeft (SelfType* node) { this->left = node; } | ||||||
|  | 	//void setRight (SelfType* node) { this->right = node; } | ||||||
|  |  | ||||||
|  |  | ||||||
| 	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->left = node; } |  | ||||||
| 	void setRight (SelfType* node) { this->right = node; } |  | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| @ -117,86 +118,79 @@ struct RedBlackTreeComparator | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename T, typename COMPARATOR, typename NODE, typename GET_T> | template <typename T, typename COMPARATOR, typename GET_NODE, typename GET_T> | ||||||
| class RedBlackTreeIterator | class RedBlackTreeIterator | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	typedef NODE Node; | 	typedef RedBlackTreeNode<T,COMPARATOR> Node; | ||||||
| 	typedef RedBlackTreeIterator<T,COMPARATOR,NODE,GET_T> SelfType; | 	typedef RedBlackTreeIterator<T,COMPARATOR,GET_NODE,GET_T> SelfType; | ||||||
| 	 | 	 | ||||||
| 	RedBlackTreeIterator (): current (QSE_NULL), previous (QSE_NULL), next_action (0) {} | 	typedef Node* (Node::*GetChild) (); | ||||||
| 	RedBlackTreeIterator (Node* root): current (root)  |  | ||||||
|  | 	enum Mode | ||||||
| 	{ | 	{ | ||||||
|  | 		ASCENDING, | ||||||
|  | 		DESCENDING | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	RedBlackTreeIterator ():  | ||||||
|  | 		pending_action (0), current (QSE_NULL), previous (QSE_NULL), | ||||||
|  | 		get_left (QSE_NULL), get_right (QSE_NULL)  | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	RedBlackTreeIterator (Node* root, Mode mode): pending_action (0), current (root) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (root != QSE_NULL); | ||||||
|  |  | ||||||
| 		this->previous = root->getParent(); | 		this->previous = root->getParent(); | ||||||
|  | 		if (mode == DESCENDING) | ||||||
|  | 		{ | ||||||
|  | 			this->get_left = &Node::getRight; | ||||||
|  | 			this->get_right = &Node::getLeft; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			this->get_left = &Node::getLeft; | ||||||
|  | 			this->get_right = &Node::getRight; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		this->__get_next_node (); | 		this->__get_next_node (); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	void __get_next_node () | 	void __get_next_node () | ||||||
| 	{ | 	{ | ||||||
| 		int l = 1, r = 0;  // TODO: | 		QSE_ASSERT (this->current != QSE_NULL); | ||||||
|  |  | ||||||
| 		while (/*this->current &&*/ this->current->notNil()) | 		while (this->current->notNil()) | ||||||
| 		{ | 		{ | ||||||
| 			if (this->previous == this->current->getParent()) | 			if (this->previous == this->current->getParent()) | ||||||
| 			{ | 			{ | ||||||
| 				/* the previous node is the parent of the current node. | 				/* the previous node is the parent of the current node. | ||||||
| 				 * it indicates that we're going down to the getChild(l) */ | 				 * it indicates that we're going down to the getChild(l) */ | ||||||
| 				if (this->current->getChild(l)->notNil()) | 				if ((this->current->*this->get_left)()->notNil()) | ||||||
| 				{ | 				{ | ||||||
| 					/* go to the getChild(l) child */ | 					/* go to the left child */ | ||||||
| 					this->previous = this->current; | 					this->previous = this->current; | ||||||
| 					this->current = this->current->getChild(l); | 					this->current = (this->current->*this->get_left)(); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| 					this->next_action = 1; | 					this->pending_action = 1; | ||||||
| 					break; | 					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)) | 			else if (this->previous == (this->current->*this->get_left)()) | ||||||
| 			{ | 			{ | ||||||
| 				/* the left child has been already traversed */ | 				/* the left child has been already traversed */ | ||||||
|  | 				this->pending_action = 2; | ||||||
| 				this->next_action = 2; |  | ||||||
| 				break; | 				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 | 			else | ||||||
| 			{ | 			{ | ||||||
| 				/* both the left child and the right child have been traversed */ | 				/* both the left child and the right child have been traversed */ | ||||||
| 				QSE_ASSERT (this->previous == this->current->getChild(r)); | 				QSE_ASSERT (this->previous == (this->current->*this->get_right)()); | ||||||
| 				/* just move up to the parent */ | 				/* just move up to the parent */ | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getParent(); | 				this->current = this->current->getParent(); | ||||||
| @ -206,15 +200,13 @@ protected: | |||||||
|  |  | ||||||
| 	void get_next_node () | 	void get_next_node () | ||||||
| 	{ | 	{ | ||||||
| 		int l = 1, r = 0;  // TODO: | 		if (pending_action ==  1) | ||||||
|  |  | ||||||
| 		if (next_action ==  1) |  | ||||||
| 		{ | 		{ | ||||||
| 			if (this->current->getChild(r)->notNil()) | 			if ((this->current->*this->get_right)()->notNil()) | ||||||
| 			{ | 			{ | ||||||
| 				/* go down to the right node if exists */ | 				/* go down to the right node if exists */ | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getChild(r); | 				this->current = (this->current->*this->get_right)(); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| @ -223,13 +215,13 @@ protected: | |||||||
| 				this->current = this->current->getParent(); | 				this->current = this->current->getParent(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (next_action == 2) | 		else if (pending_action == 2) | ||||||
| 		{ | 		{ | ||||||
| 			if (this->current->getChild(r)->notNil()) | 			if ((this->current->*this->get_right)()->notNil()) | ||||||
| 			{ | 			{ | ||||||
| 				/* go down to the right node if it exists */  | 				/* go down to the right node if it exists */  | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getChild(r); | 				this->current = (this->current->*this->get_right)(); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| @ -256,6 +248,8 @@ public: | |||||||
| 		return saved; | 		return saved; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// no operator-- | ||||||
|  |  | ||||||
| 	bool isLegit() const | 	bool isLegit() const | ||||||
| 	{ | 	{ | ||||||
| 		return current->notNil(); | 		return current->notNil(); | ||||||
| @ -273,15 +267,19 @@ public: | |||||||
|  |  | ||||||
| 	// no setValue(). | 	// no setValue(). | ||||||
|  |  | ||||||
| 	Node* getNode () | 	GET_NODE* getNode () | ||||||
| 	{ | 	{ | ||||||
| 		return this->current; | 		return this->current; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|  | 	int pending_action; | ||||||
| 	Node* current; | 	Node* current; | ||||||
| 	Node* previous; | 	Node* previous; | ||||||
| 	int next_action; | 	//Node* (Node::*get_left) (); | ||||||
|  | 	//Node* (Node::*get_right) (); | ||||||
|  | 	GetChild get_left; | ||||||
|  | 	GetChild get_right; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -306,9 +304,8 @@ public: | |||||||
|  |  | ||||||
| 	RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr),  mp (mmgr, QSE_SIZEOF(Node), mpb_size), node_count (0) | 	RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr),  mp (mmgr, QSE_SIZEOF(Node), mpb_size), node_count (0) | ||||||
| 	{ | 	{ | ||||||
| 		// initialize nil | 		// create a nil object | ||||||
| 		this->nil = new(&this->mp) Node(); | 		this->nil = new(&this->mp) Node(); | ||||||
| //		this->nil->setAll (Node::BLACK, this->nil, this->nil, this->nil); |  | ||||||
|  |  | ||||||
| 		// set root to nil | 		// set root to nil | ||||||
| 		this->root = this->nil; | 		this->root = this->nil; | ||||||
| @ -327,7 +324,10 @@ public: | |||||||
|  |  | ||||||
| 	RedBlackTree& operator= (const RedBlackTree& rbt) | 	RedBlackTree& operator= (const RedBlackTree& rbt) | ||||||
| 	{ | 	{ | ||||||
|  | 		this->clear (); | ||||||
|  |  | ||||||
| 		/* TODO */ | 		/* TODO */ | ||||||
|  |  | ||||||
| 		return *this; | 		return *this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -794,16 +794,14 @@ public: | |||||||
| 		while (this->root->notNil()) this->remove_node (this->root); | 		while (this->root->notNil()) this->remove_node (this->root); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Iterator getIterator () const | 	Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const | ||||||
| 	{ | 	{ | ||||||
| 		return Iterator (this->root); | 		return Iterator (this->root, mode); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void dump (Node* node) | 	ConstIterator getConstIterator (typename ConstIterator::Mode mode = ConstIterator::ASCENDING) const | ||||||
| 	{ | 	{ | ||||||
| 		printf ("%d %d\n", node->value.getX(), node->value.getY()); | 		return ConstIterator (this->root, mode); | ||||||
| 		if (node->left->notNil()) this->dump (node->left); |  | ||||||
| 		if (node->right->notNil()) this->dump (node->right); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| @ -813,7 +811,6 @@ protected: | |||||||
| 	qse_size_t node_count; | 	qse_size_t node_count; | ||||||
| 	Node*      nil; // internal node to present nil | 	Node*      nil; // internal node to present nil | ||||||
| 	Node*      root; // root node. | 	Node*      root; // root node. | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user