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