added POSITIONER to Array and BinaryHeap
This commit is contained in:
		| @ -34,6 +34,15 @@ | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| template <typename T> | ||||
| struct ArrayPositioner | ||||
| { | ||||
| 	void operator() (T& v, qse_size_t index) const | ||||
| 	{ | ||||
| 		// do nothing | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct ArrayResizer | ||||
| { | ||||
| 	qse_size_t operator() (qse_size_t current) const | ||||
| @ -51,12 +60,13 @@ struct ArrayResizer | ||||
| /// | ||||
| /// The Array class provides a dynamically resized array. | ||||
| ///  | ||||
| template <typename T, typename RESIZER = ArrayResizer > | ||||
| template <typename T, typename POSITIONER = ArrayPositioner<T>, typename RESIZER = ArrayResizer > | ||||
| class Array: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef Array<T,RESIZER> SelfType; | ||||
| 	typedef Array<T,POSITIONER,RESIZER> SelfType; | ||||
|  | ||||
| 	typedef ArrayPositioner<T> DefaultPositioner; | ||||
| 	typedef ArrayResizer DefaultResizer; | ||||
|  | ||||
| 	enum  | ||||
| @ -128,6 +138,7 @@ protected: | ||||
| 			{ | ||||
| 				// copy-construct each element. | ||||
| 				new((QSE::Mmgr*)QSE_NULL, &tmp[index]) T(srcbuf[index]); | ||||
| 				this->positioner (tmp[index], index); | ||||
| 			} | ||||
| 		} | ||||
| 		catch (...)  | ||||
| @ -137,6 +148,7 @@ protected: | ||||
| 			while (index > 0) | ||||
| 			{ | ||||
| 				--index; | ||||
| 				this->positioner (tmp[index], INVALID_INDEX); | ||||
| 				tmp[index].~T (); | ||||
| 			} | ||||
| 			::operator delete (tmp, this->getMmgr()); | ||||
| @ -153,11 +165,13 @@ protected: | ||||
| 			// no value exists in the given position. | ||||
| 			// i can copy-construct the value. | ||||
| 			new((QSE::Mmgr*)QSE_NULL, &this->buffer[index]) T(value); | ||||
| 			this->positioner (this->buffer[index], index); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// there is an old value in the position. | ||||
| 			this->buffer[index] = value; | ||||
| 			this->positioner (this->buffer[index], index); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -168,6 +182,7 @@ protected: | ||||
| 		for (qse_size_t i = this->count; i > 0; ) | ||||
| 		{ | ||||
| 			--i; | ||||
| 			this->positioner (this->buffer[i], INVALID_INDEX); | ||||
| 			this->buffer[i].~T (); | ||||
| 		} | ||||
| 	 | ||||
| @ -232,11 +247,14 @@ public: | ||||
| 		return INVALID_INDEX; | ||||
| 	} | ||||
|  | ||||
| 	T& operator[] (qse_size_t index) | ||||
| 	{ | ||||
| 		QSE_ASSERT (index < this->count); | ||||
| 		return this->buffer[index]; | ||||
| 	} | ||||
| 	// i don't want expose a non-const accessor as i don't like | ||||
| 	// a proper update procesure to be skipped.  | ||||
| 	// use setValueAt() or update() to modify the existing element. | ||||
| 	//T& operator[] (qse_size_t index) | ||||
| 	//{ | ||||
| 	//	QSE_ASSERT (index < this->count); | ||||
| 	//	return this->buffer[index]; | ||||
| 	//} | ||||
|  | ||||
| 	const T& operator[] (qse_size_t index) const | ||||
| 	{ | ||||
| @ -244,11 +262,14 @@ public: | ||||
| 		return this->buffer[index]; | ||||
| 	} | ||||
|  | ||||
| 	T& getValueAt (qse_size_t index) | ||||
| 	{ | ||||
| 		QSE_ASSERT (index < this->count); | ||||
| 		return this->buffer[index]; | ||||
| 	} | ||||
| 	// i don't want expose a non-const accessor as i don't like | ||||
| 	// a proper update procesure to be skipped.  | ||||
| 	// use setValueAt() or update() to modify the existing element. | ||||
| 	//T& getValueAt (qse_size_t index) | ||||
| 	//{ | ||||
| 	//	QSE_ASSERT (index < this->count); | ||||
| 	//	return this->buffer[index]; | ||||
| 	//} | ||||
|  | ||||
| 	const T& getValueAt (qse_size_t index) const | ||||
| 	{ | ||||
| @ -258,7 +279,7 @@ public: | ||||
|  | ||||
| 	void setValueAt (qse_size_t index, const T& value) | ||||
| 	{ | ||||
| 		this->insert (index, value); | ||||
| 		this->update (index, value); | ||||
| 	} | ||||
|  | ||||
| 	qse_size_t insert (qse_size_t index, const T& value) | ||||
| @ -298,6 +319,7 @@ public: | ||||
| 			for (qse_size_t i = this->count; i < index; i++) | ||||
| 			{ | ||||
| 				new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T(); | ||||
| 				this->positioner (this->buffer[i], i); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -309,6 +331,14 @@ public: | ||||
| 		return index; | ||||
| 	} | ||||
|  | ||||
| 	qse_size_t update (qse_size_t index, const T& value) | ||||
| 	{ | ||||
| 		QSE_ASSERT (index < this->count); | ||||
| 		this->buffer[index] = value; | ||||
| 		this->positioner (this->buffer[index], index); | ||||
| 		return index; | ||||
| 	} | ||||
|  | ||||
| 	void remove (qse_size_t index) | ||||
| 	{ | ||||
| 		this->remove (index, index); | ||||
| @ -325,13 +355,27 @@ public: | ||||
| 		// replace deleted elements by surviving elements at the back | ||||
| 		while (i < this->count)  | ||||
| 		{ | ||||
| 			// which is better?  | ||||
| 			//  1. destruct followed by copy construct | ||||
| 			//  2. operator assignment. | ||||
|  | ||||
| 			// 1. destruct followed by copy construct | ||||
| 			//this->positioner (this->buffer[j], INVALID_INDEX); | ||||
| 			//this->buffer[j].~T(); | ||||
| 			//new((QSE::Mmgr*)QSE_NULL, &this->buffer[j]) T(this->buffer[i]); | ||||
| 			//this->positioner (this->buffer[j], j); | ||||
|  | ||||
| 			// 2. operator assignment | ||||
| 			this->buffer[j] = this->buffer[i]; | ||||
| 			this->positioner (this->buffer[j], j); | ||||
|  | ||||
| 			j++; i++; | ||||
| 		} | ||||
|  | ||||
| 		// call the destructor of deleted elements. | ||||
| 		while (j < this->count) | ||||
| 		{ | ||||
| 			this->positioner (this->buffer[j], INVALID_INDEX); | ||||
| 			this->buffer[j].~T (); | ||||
| 			j++; | ||||
| 		} | ||||
| @ -381,6 +425,7 @@ public: | ||||
| 			for (qse_size_t i = size; i < this->count; ++i) | ||||
| 			{ | ||||
| 				// call the destructor of the items  | ||||
| 				this->positioner (this->buffer[i], INVALID_INDEX); | ||||
| 				this->buffer[i].~T (); | ||||
| 			} | ||||
|  | ||||
| @ -393,6 +438,7 @@ public: | ||||
| 			{ | ||||
| 				// use the default contructor to set the value. | ||||
| 				new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T(); | ||||
| 				this->positioner (this->buffer[i], i); | ||||
| 			} | ||||
|  | ||||
| 			this->count = size; | ||||
| @ -497,18 +543,24 @@ public: | ||||
| 				while (index < nk)  | ||||
| 				{ | ||||
| 					this->buffer[index] = this->buffer[index + n]; | ||||
| 					this->positioner (this->buffer[index], index); | ||||
| 					index += n; | ||||
| 				} | ||||
| 				if (index == last) break; | ||||
|  | ||||
| 				this->buffer[index] = this->buffer[index - nk]; | ||||
| 				this->positioner (this->buffer[index], index); | ||||
| 				index -= nk; | ||||
| 			} | ||||
|  | ||||
| 			this->buffer[last] = c; | ||||
| 			this->positioner (this->buffer[last], last); | ||||
| 			first++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	POSITIONER positioner; | ||||
| 	RESIZER    resizer; | ||||
|  | ||||
| 	qse_size_t count; | ||||
|  | ||||
| @ -85,20 +85,30 @@ struct BinaryHeapComparator | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct BinaryHeapPositioner | ||||
| { | ||||
| 	void operator() (T& v, qse_size_t index) const | ||||
| 	{ | ||||
| 		// do nothing | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| typedef ArrayResizer BinaryHeapResizer; | ||||
|  | ||||
| #define QSE_BINARY_HEAP_UP(x)     (((x) - 1) / 2) | ||||
| #define QSE_BINARY_HEAP_LEFT(x)   ((x) * 2 + 1) | ||||
| #define QSE_BINARY_HEAP_RIGHT(x)  ((x) * 2 + 2) | ||||
|  | ||||
| template <typename T, typename COMPARATOR = BinaryHeapComparator<T>, typename RESIZER = BinaryHeapResizer > | ||||
| class BinaryHeap: protected Array<T,RESIZER> | ||||
| template <typename T, typename COMPARATOR = BinaryHeapComparator<T>, typename POSITIONER = BinaryHeapPositioner<T>, typename RESIZER = BinaryHeapResizer > | ||||
| class BinaryHeap: protected Array<T,POSITIONER,RESIZER> | ||||
| { | ||||
| public: | ||||
| 	typedef BinaryHeap<T,COMPARATOR,RESIZER> SelfType; | ||||
| 	typedef Array<T,RESIZER> ParentType; | ||||
| 	typedef BinaryHeap<T,COMPARATOR,POSITIONER,RESIZER> SelfType; | ||||
| 	typedef Array<T,POSITIONER,RESIZER> ParentType; | ||||
|  | ||||
| 	typedef BinaryHeapComparator<T> DefaultComparator; | ||||
| 	typedef BinaryHeapPositioner<T> DefaultPositioner; | ||||
| 	typedef BinaryHeapResizer DefaultResizer; | ||||
|  | ||||
| 	enum | ||||
| @ -156,9 +166,9 @@ public: | ||||
|  | ||||
| 	qse_size_t update (qse_size_t index, const T& value) | ||||
| 	{ | ||||
| 		T old = this->data_buffer[index]; | ||||
| 		T old = this->buffer[index]; | ||||
|  | ||||
| 		this->buffer[index] = value; | ||||
| 		ParentType::update (index, value); | ||||
|  | ||||
| 		return (this->greater_than(value, old))? this->sift_up(index): this->sift_down(index); | ||||
| 	} | ||||
| @ -170,7 +180,7 @@ public: | ||||
| 		// copy the last item to the position to remove  | ||||
| 		T old = this->buffer[index]; | ||||
|  | ||||
| 		this->buffer[index] = this->buffer[this->count - 1]; | ||||
| 		ParentType::update (index, this->buffer[this->count - 1]); | ||||
|  | ||||
| 		// delete the last item | ||||
| 		ParentType::remove (this->count - 1); | ||||
| @ -179,13 +189,6 @@ public: | ||||
| 		(this->greater_than (this->buffer[index], old))? this->sift_up(index): this->sift_down(index); | ||||
| 	} | ||||
|  | ||||
| 	void clear () | ||||
| 	{ | ||||
| 		while (this->root->notNil()) this->remove_node (this->root); | ||||
| 		QSE_ASSERT (this->root = this->nil); | ||||
| 		QSE_ASSERT (this->node_count == 0); | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	qse_size_t sift_up (qse_size_t index) | ||||
| 	{ | ||||
| @ -198,14 +201,14 @@ protected: | ||||
|  | ||||
| 			do  | ||||
| 			{ | ||||
| 				this->buffer[index] = this->buffer[up]; | ||||
| 				ParentType::setValueAt (index, this->buffer[up]); | ||||
|  | ||||
| 				index = up; | ||||
| 				up = QSE_BINARY_HEAP_UP(up); | ||||
| 			} | ||||
| 			while (index > 0 && this->greater_than(item, this->buffer[up])); | ||||
|  | ||||
| 			this->buffer[index] = item; | ||||
| 			ParentType::setValueAt (index, item); | ||||
| 		} | ||||
|  | ||||
| 		return index; | ||||
| @ -244,12 +247,12 @@ protected: | ||||
|  | ||||
| 				if (this->greater_than(item, this->buffer[greater])) break; | ||||
|  | ||||
| 				this->buffer[index] = this->buffer[greater]; | ||||
| 				ParentType::setValueAt (index, this->buffer[greater]); | ||||
| 				index = greater; | ||||
| 			} | ||||
| 			while (index < half_data_count); | ||||
|  | ||||
| 			this->buffer[index] = item; | ||||
| 			ParentType::setValueAt (index, item); | ||||
| 		} | ||||
|  | ||||
| 		return index; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user