Added a couple of 'operator new()' definitions.
Started adding Array and BinaryHeap
This commit is contained in:
		
							
								
								
									
										460
									
								
								qse/include/qse/cmn/Array.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								qse/include/qse/cmn/Array.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,460 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _QSE_CMN_ARRAY_HPP_ | ||||||
|  | #define _QSE_CMN_ARRAY_HPP_ | ||||||
|  |  | ||||||
|  | #include <qse/Types.hpp> | ||||||
|  | #include <qse/cmn/Mpool.hpp> | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | struct ArrayResizer | ||||||
|  | { | ||||||
|  | 	qse_size_t operator() (qse_size_t current) const | ||||||
|  | 	{ | ||||||
|  | 		return (current < 5000)?   (current + current): | ||||||
|  | 		       (current < 50000)?  (current + (current / 2)): | ||||||
|  | 		       (current < 100000)? (current + (current / 4)): | ||||||
|  | 		       (current < 150000)? (current + (current / 8)): | ||||||
|  | 		                           (current + (current / 16)); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T, typename RESIZER = ArrayResizer> | ||||||
|  | class Array: public Mmged | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	typedef Array<T,RESIZER> SelfType; | ||||||
|  |  | ||||||
|  | 	enum  | ||||||
|  | 	{ | ||||||
|  | 		DEFAULT_CAPACITY = 128, | ||||||
|  | 		INVALID_INDEX = ~(qse_size_t)0 | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Array (Mmgr* mmgr = QSE_NULL, | ||||||
|  | 	            qse_size_t capacity = DEFAULT_CAPACITY,  | ||||||
|  | 	            qse_size_t mpb_size = 0): | ||||||
|  | 		Mmged (mmgr), | ||||||
|  | 		mp (mmgr, QSE_SIZEOF(T), mpb_size) | ||||||
|  | 	{ | ||||||
|  | 		if (capacity <= 0)  | ||||||
|  | 		{ | ||||||
|  | 			this->buffer = QSE_NULL; | ||||||
|  | 			this->capacity = 0; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			//this->buffer = new T[capacity]; | ||||||
|  | 			this->buffer = (T*)::operator new (capacity * QSE_SIZEOF(*this->buffer), &this->mp); | ||||||
|  | 			this->capacity = capacity; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this->count  = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	Array (const SelfType& array) | ||||||
|  | 	{ | ||||||
|  | 		if (array.buffer == QSE_NULL)  | ||||||
|  | 		{ | ||||||
|  | 			this->buffer = QSE_NULL; | ||||||
|  | 			this->capacity = 0; | ||||||
|  | 			this->grow_factor = array.grow_factor; | ||||||
|  | 			this->count  = 0; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			T* tmp = QSE_NULL; | ||||||
|  | 			QSE_ASSERT (array.capacity > 0 && array.grow_factor > 0); | ||||||
|  |  | ||||||
|  | 			try {   | ||||||
|  | 				tmp = new T[array.capacity]; | ||||||
|  | 				for (qse_size_t i = 0; i < array.this->count; i++) { | ||||||
|  | 					tmp[i] = array.buffer[i]; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			catch (...) { | ||||||
|  | 				// just in case where the assignment throws an  | ||||||
|  | 				// exception. when T is a class type, the operator =  | ||||||
|  | 				// for the class may throw an exception. | ||||||
|  | 				if (tmp != QSE_NULL) delete[] tmp; | ||||||
|  | 				throw; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			this->buffer = tmp; | ||||||
|  | 			this->capacity = array.capacity; | ||||||
|  | 			this->grow_factor = array.grow_factor; | ||||||
|  | 			this->count  = array.this->count; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	~Array () | ||||||
|  | 	{ | ||||||
|  | 		if (this->buffer) | ||||||
|  | 		{ | ||||||
|  | 			for (qse_size_t i = this->count; i > 0; ) | ||||||
|  | 			{ | ||||||
|  | 				--i; | ||||||
|  | 				this->buffer[i].~T (); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			::operator delete (this->buffer, &this->mp); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	SelfType& operator= (const SelfType& array) | ||||||
|  | 	{ | ||||||
|  | 		setSize (array.this->count); | ||||||
|  | 		for (qse_size_t i = 0; i < array.this->count; i++) { | ||||||
|  | 			this->buffer[i] = array.buffer[i]; | ||||||
|  | 		} | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	Array<T>& operator+= (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		addDatum (value); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 	Array<T>& operator+ (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		Array<T> array (*this); | ||||||
|  | 		array.addDatum (value); | ||||||
|  | 		return array; | ||||||
|  | 	} | ||||||
|  | 	*/ | ||||||
|  |  | ||||||
|  | 	bool isEmpty () const | ||||||
|  | 	{ | ||||||
|  | 		return this->count == 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getSize () const | ||||||
|  | 	{ | ||||||
|  | 		return this->count; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getCapacity () const | ||||||
|  | 	{ | ||||||
|  | 		return this->capacity; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	operator T* () | ||||||
|  | 	{ | ||||||
|  | 		return this->buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	operator const T* () const | ||||||
|  | 	{ | ||||||
|  | 		return this->buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T* getBuffer () | ||||||
|  | 	{ | ||||||
|  | 		return this->buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const T* getBuffer () const | ||||||
|  | 	{ | ||||||
|  | 		return this->buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& operator[] (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->count); | ||||||
|  | 		return this->buffer[index]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const T& operator[] (qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->count); | ||||||
|  | 		return this->buffer[index]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& get (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->count); | ||||||
|  | 		return this->buffer[index]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const T& get (qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->count); | ||||||
|  | 		return this->buffer[index]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->count); | ||||||
|  | 		this->buffer[index] = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	void set_item (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		if (index >= this->count) | ||||||
|  | 			new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value); | ||||||
|  | 		else | ||||||
|  | 			this->buffer[index] = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	qse_size_t insert (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		if (index >= this->capacity)  | ||||||
|  | 		{ | ||||||
|  | 			qse_size_t new_capa = this->resizer (this->capacity); | ||||||
|  |  | ||||||
|  | 			if (index < new_capa) | ||||||
|  | 				this->setCapacity (new_capa); | ||||||
|  | 			else | ||||||
|  | 				this->setCapacity (index + 1); | ||||||
|  | 		} | ||||||
|  | 		else if (this->count >= this->capacity)  | ||||||
|  | 		{ | ||||||
|  | 			qse_size_t new_capa = this->resizer (this->capacity); | ||||||
|  | 			this->setCapacity (new_capa); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for (qse_size_t i = this->count; i > index; i--)  | ||||||
|  | 		{ | ||||||
|  | 			//this->buffer[i] = this->buffer[i - 1]; | ||||||
|  | 			this->set_item (i, this->buffer[i - 1]); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		//this->buffer[index] = value; | ||||||
|  | 		this->set_item (index, value); | ||||||
|  | 		if (index > this->count) this->count = index + 1; | ||||||
|  | 		else this->count++; | ||||||
|  |  | ||||||
|  | 		return index; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	void remove (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | 		this->remove (index, index); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void remove (qse_size_t from_index, qse_size_t to_index) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (from_index < this->count); | ||||||
|  | 		QSE_ASSERT (to_index < this->count); | ||||||
|  |  | ||||||
|  | 		qse_size_t j = from_index; | ||||||
|  | 		qse_size_t i = to_index + 1; | ||||||
|  | 		while (i < this->count)  | ||||||
|  | 		{ | ||||||
|  | 			this->buffer[j++] = this->buffer[i++]; | ||||||
|  | 		} | ||||||
|  | 		this->count -= to_index - from_index + 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	qse_size_t addDatum (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return insert (this->count, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t removeDatum (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t i = 0, sz = this->size(); | ||||||
|  | 		while (i < this->count)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == this->buffer[i])  | ||||||
|  | 			{ | ||||||
|  | 				remove (i); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			i++; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return sz - this->size(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t removeDatums (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t i = 0, sz = this->size(); | ||||||
|  |  | ||||||
|  | 		while (i < this->count)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == this->buffer[i]) remove (i); | ||||||
|  | 			else i++; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return sz - this->size(); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	void clear () | ||||||
|  | 	{ | ||||||
|  | 		setSize (0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void trimToSize () | ||||||
|  | 	{ | ||||||
|  | 		setCapacity (this->size); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void setSize (qse_size_t size) | ||||||
|  | 	{ | ||||||
|  | 		if (size > this->capacity) this->setCapacity (size); | ||||||
|  | 		QSE_ASSERT (size <= this->capacity); | ||||||
|  | 		this->count = size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void setCapacity (qse_size_t capacity) | ||||||
|  | 	{ | ||||||
|  | 		if (capacity <= 0)  | ||||||
|  | 		{ | ||||||
|  | 			if (this->buffer != QSE_NULL)  | ||||||
|  | 				delete[] this->buffer; | ||||||
|  | 			this->buffer = QSE_NULL; | ||||||
|  | 			this->capacity = 0; | ||||||
|  | 			this->count  = 0; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			T* tmp = QSE_NULL; | ||||||
|  | 			qse_size_t cnt = this->count; | ||||||
|  |  | ||||||
|  | 			try  | ||||||
|  | 			{ | ||||||
|  | 				tmp = new T[capacity]; | ||||||
|  | 				if (cnt > capacity) cnt = capacity; | ||||||
|  | 				for (qse_size_t i = 0; i < cnt; i++)  | ||||||
|  | 				{ | ||||||
|  | 					tmp[i] = this->buffer[i]; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			catch (...)  | ||||||
|  | 			{ | ||||||
|  | 				if (tmp != QSE_NULL) delete[] tmp; | ||||||
|  | 				throw; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (this->buffer != QSE_NULL)  | ||||||
|  | 				delete[] this->buffer; | ||||||
|  | 			this->buffer = tmp; | ||||||
|  | 			this->capacity = capacity; | ||||||
|  | 			this->count = cnt; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	qse_size_t indexOf (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		for (qse_size_t i = 0; i < this->count; i++)  | ||||||
|  | 		{ | ||||||
|  | 			if (this->buffer[i] == value) return i; | ||||||
|  | 		} | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	qse_size_t indexOf (const T& value, qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		for (qse_size_t i = index; i < this->count; i++)  | ||||||
|  | 		{ | ||||||
|  | 			if (this->buffer[i] == value) return i; | ||||||
|  | 		} | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	qse_size_t lastIndexOf (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		for (qse_size_t i = this->count; i > 0; )  | ||||||
|  | 		{ | ||||||
|  | 			if (this->buffer[--i] == value) return i; | ||||||
|  | 		}	 | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	qse_size_t lastIndexOf (const T& value, qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		for (qse_size_t i = index + 1; i > 0; )  | ||||||
|  | 		{ | ||||||
|  | 			if (this->buffer[--i] == value) return i; | ||||||
|  | 		} | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	void rotate (int dir, qse_size_t n) | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t first, last, cnt, index, nk; | ||||||
|  | 		T c; | ||||||
|  |  | ||||||
|  | 		if (dir == 0) return this->count; | ||||||
|  | 		if ((n %= this->count) == 0) return this->count; | ||||||
|  |  | ||||||
|  | 		if (dir > 0) n = this->count - n; | ||||||
|  | 		first = 0; nk = this->count - n; cnt = 0;  | ||||||
|  |  | ||||||
|  | 		while (cnt < n)  | ||||||
|  | 		{ | ||||||
|  | 			last = first + nk; | ||||||
|  | 			index = first; | ||||||
|  | 			c = this->buffer[first]; | ||||||
|  | 			while (1)  | ||||||
|  | 			{ | ||||||
|  | 				cnt++; | ||||||
|  | 				while (index < nk)  | ||||||
|  | 				{ | ||||||
|  | 					this->buffer[index] = this->buffer[index + n]; | ||||||
|  | 					index += n; | ||||||
|  | 				} | ||||||
|  | 				if (index == last) break; | ||||||
|  | 				this->buffer[index] = this->buffer[index - nk]; | ||||||
|  | 				index -= nk; | ||||||
|  | 			} | ||||||
|  | 			this->buffer[last] = c; first++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	Mpool      mp; | ||||||
|  | 	RESIZER    resizer; | ||||||
|  |  | ||||||
|  | 	qse_size_t count; | ||||||
|  | 	qse_size_t capacity; | ||||||
|  | 	T* buffer; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										360
									
								
								qse/include/qse/cmn/BinaryHeap.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								qse/include/qse/cmn/BinaryHeap.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,360 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _QSE_CMN_BINARYHEAP_HPP_ | ||||||
|  | #define _QSE_CMN_BINARYHEAP_HPP_ | ||||||
|  |  | ||||||
|  | /// | ||||||
|  | /// This file provides an array-based binary heap. | ||||||
|  | /// In the heap, each node is greater than or equal to its BinaryHeap | ||||||
|  | /// | ||||||
|  | /// #include <qse/cmn/BinaryHeap.hpp> | ||||||
|  | /// #include <stdio.h> | ||||||
|  | /// | ||||||
|  | /// struct IntComparator | ||||||
|  | /// { | ||||||
|  | ///         bool operator() (int v1, int v2) const | ||||||
|  | ///         { | ||||||
|  | ///                 //return !(v1 > v2); | ||||||
|  | ///                 return v1 > v2; | ||||||
|  | ///         } | ||||||
|  | /// }; | ||||||
|  | ///  | ||||||
|  | /// int main (int argc, char* argv[]) | ||||||
|  | /// { | ||||||
|  | ///         QSE::BinaryHeap<int,IntComparator> heap; | ||||||
|  | ///  | ||||||
|  | ///         heap.insert (70); | ||||||
|  | ///         heap.insert (90); | ||||||
|  | ///         heap.insert (10); | ||||||
|  | ///         heap.insert (5); | ||||||
|  | ///         heap.insert (88); | ||||||
|  | ///         heap.insert (87); | ||||||
|  | ///         heap.insert (300); | ||||||
|  | ///         heap.insert (91); | ||||||
|  | ///         heap.insert (100); | ||||||
|  | ///         heap.insert (200); | ||||||
|  | ///  | ||||||
|  | ///         while (heap.getSize() > 0) | ||||||
|  | ///         { | ||||||
|  | ///                 printf ("%d\n", heap.getRootValue()); | ||||||
|  | ///                 heap.remove (0); | ||||||
|  | ///         } | ||||||
|  | ///  | ||||||
|  | ///         return 0; | ||||||
|  | /// } | ||||||
|  | ///  | ||||||
|  |  | ||||||
|  | #include <qse/Types.hpp> | ||||||
|  | #include <qse/cmn/Mpool.hpp> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct BinaryHeapComparator | ||||||
|  | { | ||||||
|  | 	// this can be used to build a max heap | ||||||
|  | 	bool operator() (const T& v1, const T& v2) const | ||||||
|  | 	{ | ||||||
|  | 		return v1 > v2; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<typename T> | ||||||
|  | struct BinaryHeapAssigner | ||||||
|  | { | ||||||
|  | 	// The assignment proxy is used to get the value informed of its position | ||||||
|  | 	// within the heap. This default implmentation, however, doesn't utilize | ||||||
|  | 	// the position (index). | ||||||
|  | 	T& operator() (T& v1, const T& v2, xp_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		v1 = v2; | ||||||
|  | 		return v1; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct BinaryHeapResizer | ||||||
|  | { | ||||||
|  | 	qse_size_t operator() (qse_size_t current) const | ||||||
|  | 	{ | ||||||
|  | 		return (current < 5000)?   (current + current): | ||||||
|  | 		       (current < 50000)?  (current + (current / 2)): | ||||||
|  | 		       (current < 100000)? (current + (current / 4)): | ||||||
|  | 		       (current < 150000)? (current + (current / 8)): | ||||||
|  | 		                           (current + (current / 16)); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #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 ASSIGNER = BinaryHeapAssigner<T>, RESIZER = TeeeHeapResizer > | ||||||
|  | class BinaryHeap: public Mmged | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	typedef BinaryHeap<T,COMPARATOR,ASSIGNER,RESIZER> SelfType; | ||||||
|  |  | ||||||
|  | 	enum | ||||||
|  | 	{ | ||||||
|  | 		DEFAULT_CAPACITY = 10, | ||||||
|  | 		MIN_CAPACITY = 1 | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	BinaryHeap (Mmgr* mmgr = QSE_NULL, | ||||||
|  | 	            qse_size_t capacity = DEFAULT_CAPACITY,  | ||||||
|  | 	            qse_size_t mpb_size = 0): | ||||||
|  | 		Mmged (mmgr), | ||||||
|  | 		mp (mmgr, QSE_SIZEOF(Node), mpb_size) | ||||||
|  | 	{ | ||||||
|  | 		if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY; | ||||||
|  | 		this->capacity = capacity; | ||||||
|  | 		this->count = 0; | ||||||
|  |  | ||||||
|  | 		this->buffer = (T*)::operator new (this->capacity * QSE_SIZEOF(*this->buffer), &this->mp); | ||||||
|  | 		for (qse_size_t i = 0; i < this->capacity; i++) | ||||||
|  | 		{ | ||||||
|  | 			 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	BinaryHeap (const SelfType& heap): | ||||||
|  | 		Mmged (heap.getMmgr()), | ||||||
|  | 		mp (heap.getMmgr(), heap.mp.getDatumSize(), heap.mp.getBlockSize()), | ||||||
|  | 		capacity (heap.capacity), count (0) | ||||||
|  | 	{ | ||||||
|  | 		// TODO: copy data items. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	~BinaryHeap () | ||||||
|  | 	{ | ||||||
|  | 		for (qse_size_t i = this->count; i > 0; ) | ||||||
|  | 		{ | ||||||
|  | 			--i; | ||||||
|  | 			this->buffer[i].~T (); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		::operator delete (this->buffer, &this->mp); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	SelfType& operator= (const SelfType& heap) | ||||||
|  | 	{ | ||||||
|  | 		this->clear (); | ||||||
|  | 		// TODO: copy data items | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	~BinaryHeap | ||||||
|  | 	Mpool& getMpool () | ||||||
|  | 	{ | ||||||
|  | 		return this->mp; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const Mpool& getMpool () const | ||||||
|  | 	{ | ||||||
|  | 		return this->mp; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getCapacity () const | ||||||
|  | 	{ | ||||||
|  | 		return this->capacity; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getSize () const | ||||||
|  | 	{ | ||||||
|  | 		return this->count; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool isEmpty () const | ||||||
|  | 	{ | ||||||
|  | 		return this->count <= 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  |  | ||||||
|  | 	Node* insert (const T& value) | ||||||
|  | 	{ | ||||||
|  | #if 0 | ||||||
|  | 		qse_size_t index = this->data_count; | ||||||
|  |  | ||||||
|  | 		// add the item at the back of the array | ||||||
|  | 		// i don't use Tree<T>::insert() for this->assign(). | ||||||
|  | 		//Tree<T>::insert (index, value); | ||||||
|  | 		Tree<T>::setSize (index + 1); | ||||||
|  | 		this->assign (this->data_buffer[index], value, index); | ||||||
|  |  | ||||||
|  | 		// move the item up to the top if it's greater than the up item	 | ||||||
|  | 		return sift_up (index); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	qse_size_t update (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		T old = this->data_buffer[index]; | ||||||
|  |  | ||||||
|  | 		//this->data_buffer[index] = value; | ||||||
|  | 		this->assign (this->data_buffer[index], value, index); | ||||||
|  |  | ||||||
|  | 		return (this->greater_than (value, old))? sift_up (index): sift_down (index); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	void remove_node (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->data_count); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 		// copy the last item to the position to remove  | ||||||
|  | 		// note that this->assign() isn't called for temporary assignment. | ||||||
|  | 		T old = this->data_buffer[index]; | ||||||
|  |  | ||||||
|  | 		//this->data_buffer[index] = this->data_buffer[this->data_count - 1]; | ||||||
|  | 		this->assign (this->data_buffer[index], this->data_buffer[this->data_count - 1], index); | ||||||
|  |  | ||||||
|  | 		// delete the last item | ||||||
|  | 		Tree<T>::remove (this->data_count - 1); | ||||||
|  | 		 | ||||||
|  | 		// relocate the item | ||||||
|  | 		(this->greater_than (this->data_buffer[index], old))? sift_up (index): sift_down (index); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void remove () | ||||||
|  | 	{ | ||||||
|  | 		/* TODO: remove root node */ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void clear () | ||||||
|  | 	{ | ||||||
|  | 		while (this->root->notNil()) this->remove_node (this->root); | ||||||
|  | 		QSE_ASSERT (this->root = this->nil); | ||||||
|  | 		QSE_ASSERT (this->node_count == 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	Node* sift_up (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | #if 0 | ||||||
|  | 		qse_size_t up; | ||||||
|  |  | ||||||
|  | 		up = QSE_ARRAY_HEAP_PARENT (index); | ||||||
|  | 		if (index > 0 && this->greater_than (this->data_buffer[index], this->data_buffer[up])) | ||||||
|  | 		{ | ||||||
|  | 			// note that this->assign() isn't called for temporary assignment. | ||||||
|  | 			T item = this->data_buffer[index]; | ||||||
|  |  | ||||||
|  | 			do  | ||||||
|  | 			{ | ||||||
|  | 				//this->data_buffer[index] = this->data_buffer[up]; | ||||||
|  | 				this->assign (this->data_buffer[index], this->data_buffer[up], index); | ||||||
|  |  | ||||||
|  | 				index = up;	 | ||||||
|  | 				up = QSE_ARRAY_HEAP_PARENT (up); | ||||||
|  | 			} | ||||||
|  | 			while (index > 0 && this->greater_than (item, this->data_buffer[up])); | ||||||
|  |  | ||||||
|  | 			//this->data_buffer[index] = item; | ||||||
|  | 			this->assign (this->data_buffer[index], item, index); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return index; | ||||||
|  | #endif | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* sift_down (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | #if 0 | ||||||
|  | 		qse_size_t half_data_count = this->data_count / 2; | ||||||
|  | 		 | ||||||
|  | 		if (index < half_data_count) | ||||||
|  | 		{ | ||||||
|  | 			// if at least 1 child is under the 'index' position | ||||||
|  | 			// perform sifting | ||||||
|  |  | ||||||
|  | 			// note that this->assign() isn't called for temporary assignment. | ||||||
|  | 			T item = this->data_buffer[index]; | ||||||
|  | 			T item = this->data_buffer[index]; | ||||||
|  |  | ||||||
|  | 			do | ||||||
|  | 			{ | ||||||
|  | 				qse_size_t left, right, greater; | ||||||
|  | 	 | ||||||
|  | 				left = QSE_ARRAY_HEAP_LEFT (index); | ||||||
|  | 				right = QSE_ARRAY_HEAP_RIGHT (index); | ||||||
|  | 	 | ||||||
|  | 				// choose the larger one between 2 BinaryHeap  | ||||||
|  | 				if (right < this->data_count &&  | ||||||
|  | 				    this->greater_than (this->data_buffer[right], this->data_buffer[left])) | ||||||
|  | 				{ | ||||||
|  | 					// if the right child exists and  | ||||||
|  | 					// the right item is greater than the left item | ||||||
|  | 					greater = right; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					greater = left; | ||||||
|  | 				} | ||||||
|  | 	 | ||||||
|  | 				if (this->greater_than (item, this->data_buffer[greater])) break; | ||||||
|  | 	 | ||||||
|  | 				//this->data_buffer[index] = this->data_buffer[greater]; | ||||||
|  | 				this->assign (this->data_buffer[index], this->data_buffer[greater], index); | ||||||
|  | 				index = greater; | ||||||
|  | 			} | ||||||
|  | 			while (index < half_data_count); | ||||||
|  |  | ||||||
|  | 			//this->data_buffer[index] = item; | ||||||
|  | 			this->assign (this->data_buffer[index], item, index); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return index; | ||||||
|  | #endif | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	Mpool      mp; | ||||||
|  | 	COMPARATOR greater_than; | ||||||
|  | 	ASSIGNER   assigner; | ||||||
|  | 	RESIZER    resizer; | ||||||
|  |  | ||||||
|  | 	qse_size_t capacity; | ||||||
|  | 	qse_size_t count; | ||||||
|  | 	T* buffer; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @ -53,6 +53,7 @@ if ENABLE_CXX | |||||||
| pkginclude_HEADERS += \ | pkginclude_HEADERS += \ | ||||||
| 	Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | 	Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | ||||||
| 	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | 	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | ||||||
| 	RedBlackTree.hpp RedBlackTable.hpp | 	RedBlackTree.hpp RedBlackTable.hpp \ | ||||||
|  | 	Array.hpp BinaryHeap.hpp | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | |||||||
| @ -53,7 +53,8 @@ host_triplet = @host@ | |||||||
| @ENABLE_CXX_TRUE@am__append_1 = \ | @ENABLE_CXX_TRUE@am__append_1 = \ | ||||||
| @ENABLE_CXX_TRUE@	Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | @ENABLE_CXX_TRUE@	Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | @ENABLE_CXX_TRUE@	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	RedBlackTree.hpp RedBlackTable.hpp | @ENABLE_CXX_TRUE@	RedBlackTree.hpp RedBlackTable.hpp \ | ||||||
|  | @ENABLE_CXX_TRUE@	Array.hpp BinaryHeap.hpp | ||||||
|  |  | ||||||
| subdir = include/qse/cmn | subdir = include/qse/cmn | ||||||
| DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ | DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ | ||||||
| @ -93,7 +94,8 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dir.h dll.h \ | |||||||
| 	sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ | 	sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ | ||||||
| 	utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | 	utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | ||||||
| 	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp \ | 	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp \ | ||||||
| 	HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp | 	HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp Array.hpp \ | ||||||
|  | 	BinaryHeap.hpp | ||||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||||
| am__vpath_adj = case $$p in \ | am__vpath_adj = case $$p in \ | ||||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||||
|  | |||||||
| @ -179,6 +179,8 @@ QSE_END_NAMESPACE(QSE) | |||||||
| void* operator new (qse_size_t size, QSE::Mmgr* mmgr); | void* operator new (qse_size_t size, QSE::Mmgr* mmgr); | ||||||
| void operator delete (void* ptr, QSE::Mmgr* mmgr); | void operator delete (void* ptr, QSE::Mmgr* mmgr); | ||||||
|  |  | ||||||
|  | void* operator new (qse_size_t size, QSE::Mmgr* mmgr, void* existing_ptr); | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| // i found no way to delete an array allocated with | // i found no way to delete an array allocated with | ||||||
| // the placement new operator. if the array element is an instance | // the placement new operator. if the array element is an instance | ||||||
|  | |||||||
| @ -117,5 +117,6 @@ QSE_END_NAMESPACE(QSE) | |||||||
| void* operator new (qse_size_t size, QSE::Mpool* mp); | void* operator new (qse_size_t size, QSE::Mpool* mp); | ||||||
| void operator delete (void* ptr, QSE::Mpool* mp); | void operator delete (void* ptr, QSE::Mpool* mp); | ||||||
|  |  | ||||||
|  | void* operator new (qse_size_t size, QSE::Mpool* mp, void* existing_ptr); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | |||||||
| @ -55,19 +55,19 @@ public: | |||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	Color color; | 	Color color; | ||||||
| 	SelfType* parent; | 	SelfType* up; | ||||||
| 	SelfType* left; // left child | 	SelfType* left; // left child | ||||||
| 	SelfType* right; // right child | 	SelfType* right; // right child | ||||||
|  |  | ||||||
| 	RedBlackTreeNode(): color (BLACK), parent (this), left (this), right (this) | 	RedBlackTreeNode(): color (BLACK), up (this), left (this), right (this) | ||||||
| 	{ | 	{ | ||||||
| 		// no initialization on 'value' in this constructor. | 		// no initialization on 'value' in this constructor. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right): | 	RedBlackTreeNode(const T& value, Color color, SelfType* up, SelfType* left, SelfType* right): | ||||||
| 		value (value), color (color), parent (parent), left (left), right (right) | 		value (value), color (color), up (up), left (left), right (right) | ||||||
| 	{ | 	{ | ||||||
| 		QSE_ASSERT (parent != this); | 		QSE_ASSERT (up != this); | ||||||
| 		QSE_ASSERT (left != this); | 		QSE_ASSERT (left != this); | ||||||
| 		QSE_ASSERT (right != this); | 		QSE_ASSERT (right != this); | ||||||
| 	} | 	} | ||||||
| @ -79,7 +79,7 @@ public: | |||||||
|  |  | ||||||
| 	bool isNil () const | 	bool isNil () const | ||||||
| 	{ | 	{ | ||||||
| 		return this->parent == this; // && this->left == this && this->right == this; | 		return this->up == this; // && this->left == this && this->right == this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool notNil () const | 	bool notNil () const | ||||||
| @ -90,28 +90,21 @@ public: | |||||||
| 	bool isBlack () const  { return this->color == BLACK; } | 	bool isBlack () const  { return this->color == BLACK; } | ||||||
| 	bool isRed () const { return this->color == RED; } | 	bool isRed () const { return this->color == RED; } | ||||||
|  |  | ||||||
| 	SelfType* getParent () { return this->parent; } | 	SelfType* getUpNode () { return this->up; } | ||||||
| 	const SelfType* getParent () const { return this->parent; } | 	const SelfType* getUpNode () const { return this->up; } | ||||||
| 	SelfType* getParentNode () { return this->parent; } |  | ||||||
| 	const SelfType* getParentNode () const { return this->parent; } |  | ||||||
| 	 | 	 | ||||||
| 	SelfType* getLeft () { return this->left; } |  | ||||||
| 	const SelfType* getLeft () const { return this->left; } |  | ||||||
| 	SelfType* getLeftNode () { return this->left; } | 	SelfType* getLeftNode () { return this->left; } | ||||||
| 	const SelfType* getLeftNode () const { return this->left; } | 	const SelfType* getLeftNode () const { return this->left; } | ||||||
|  |  | ||||||
| 	SelfType* getRight () { return this->right; } |  | ||||||
| 	const SelfType* getRight () const { return this->right; } |  | ||||||
| 	SelfType* getRightNode () { return this->right; } | 	SelfType* getRightNode () { return this->right; } | ||||||
| 	const SelfType* getRightNode () const { return this->right; } | 	const SelfType* getRightNode () const { return this->right; } | ||||||
|  |  | ||||||
| 	//void setBlack () { this->color = BLACK; } | 	//void setBlack () { this->color = BLACK; } | ||||||
| 	//void setRed () { this->color = RED; } | 	//void setRed () { this->color = RED; } | ||||||
| 	//void setParent (SelfType* node) { this->parent = node; } | 	//void setUpNode (SelfType* node) { this->up = node; } | ||||||
| 	//void setLeft (SelfType* node) { this->left = node; } | 	//void setLeftNode (SelfType* node) { this->left = node; } | ||||||
| 	//void setRight (SelfType* node) { this->right = node; } | 	//void setRightNode (SelfType* node) { this->right = node; } | ||||||
|  |  | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| @ -153,16 +146,16 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		QSE_ASSERT (root != QSE_NULL); | 		QSE_ASSERT (root != QSE_NULL); | ||||||
|  |  | ||||||
| 		this->previous = root->getParent(); | 		this->previous = root->getUpNode(); | ||||||
| 		if (mode == DESCENDING) | 		if (mode == DESCENDING) | ||||||
| 		{ | 		{ | ||||||
| 			this->get_left = &Node::getRight; | 			this->get_left = &Node::getRightNode; | ||||||
| 			this->get_right = &Node::getLeft; | 			this->get_right = &Node::getLeftNode; | ||||||
| 		} | 		} | ||||||
| 		else  | 		else  | ||||||
| 		{ | 		{ | ||||||
| 			this->get_left = &Node::getLeft; | 			this->get_left = &Node::getLeftNode; | ||||||
| 			this->get_right = &Node::getRight; | 			this->get_right = &Node::getRightNode; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		this->__move_to_next_node (); | 		this->__move_to_next_node (); | ||||||
| @ -175,9 +168,9 @@ protected: | |||||||
|  |  | ||||||
| 		while (this->current->notNil()) | 		while (this->current->notNil()) | ||||||
| 		{ | 		{ | ||||||
| 			if (this->previous == this->current->getParent()) | 			if (this->previous == this->current->getUpNode()) | ||||||
| 			{ | 			{ | ||||||
| 				/* the previous node is the parent of the current node. | 				/* the previous node is the up 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->*this->get_left)()->notNil()) | 				if ((this->current->*this->get_left)()->notNil()) | ||||||
| 				{ | 				{ | ||||||
| @ -201,9 +194,9 @@ protected: | |||||||
| 			{ | 			{ | ||||||
| 				/* 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->*this->get_right)()); | 				QSE_ASSERT (this->previous == (this->current->*this->get_right)()); | ||||||
| 				/* just move up to the parent */ | 				/* just move up to the up */ | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getParent(); | 				this->current = this->current->getUpNode(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -220,9 +213,9 @@ protected: | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				/* otherwise, move up to the parent */ | 				/* otherwise, move up to the up */ | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getParent(); | 				this->current = this->current->getUpNode(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (pending_action == 2) | 		else if (pending_action == 2) | ||||||
| @ -235,9 +228,9 @@ protected: | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				/* otherwise, move up to the parent */ | 				/* otherwise, move up to the up */ | ||||||
| 				this->previous = this->current; | 				this->previous = this->current; | ||||||
| 				this->current = this->current->getParent(); | 				this->current = this->current->getUpNode(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -338,7 +331,7 @@ public: | |||||||
| 		this->root = this->nil; | 		this->root = this->nil; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	RedBlackTree (const RedBlackTree& rbt):  | 	RedBlackTree (const SelfType& rbt):  | ||||||
| 		Mmged (rbt.getMmgr()), | 		Mmged (rbt.getMmgr()), | ||||||
| 		mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()), | 		mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()), | ||||||
| 		node_count (0) | 		node_count (0) | ||||||
| @ -365,7 +358,7 @@ public: | |||||||
| 		this->dispose_node (this->nil); | 		this->dispose_node (this->nil); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	RedBlackTree& operator= (const RedBlackTree& rbt) | 	SelfType& operator= (const SelfType& rbt) | ||||||
| 	{ | 	{ | ||||||
| 		this->clear (); | 		this->clear (); | ||||||
|  |  | ||||||
| @ -400,14 +393,16 @@ public: | |||||||
| 		return this->node_count <= 0; | 		return this->node_count <= 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/// The getRootNode() function gets the pointer to the root node. | ||||||
|  | 	/// If no node exists in the tree, it returns #QSE_NULL. | ||||||
| 	Node* getRootNode () | 	Node* getRootNode () | ||||||
| 	{ | 	{ | ||||||
| 		return this->root; | 		return this->root->isNil()? QSE_NULL: this->root; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	const Node* getRootNode () const | 	const Node* getRootNode () const | ||||||
| 	{ | 	{ | ||||||
| 		return this->root; | 		return this->root->isNil()? QSE_NULL: this->root; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| @ -463,7 +458,7 @@ protected: | |||||||
| 		 * left child(x). move the pivot's right child(y) to the pivot's original | 		 * left child(x). move the pivot's right child(y) to the pivot's original | ||||||
| 		 * position. as 'c1' is between 'y' and 'pivot', move it to the right | 		 * position. as 'c1' is between 'y' and 'pivot', move it to the right | ||||||
| 		 * of the new pivot position. | 		 * of the new pivot position. | ||||||
| 		 *       parent                   parent | 		 *       up                   up | ||||||
| 		 *        | | (left or right?)      | | | 		 *        | | (left or right?)      | | | ||||||
| 		 *       pivot                      y | 		 *       pivot                      y | ||||||
| 		 *       /  \                     /  \ | 		 *       /  \                     /  \ | ||||||
| @ -477,7 +472,7 @@ protected: | |||||||
| 		 * position. as 'c2' is between 'x' and 'pivot', move it to the left | 		 * position. as 'c2' is between 'x' and 'pivot', move it to the left | ||||||
| 		 * of the new pivot position. | 		 * of the new pivot position. | ||||||
| 		 * | 		 * | ||||||
| 		 *       parent                   parent | 		 *       up                   up | ||||||
| 		 *        | | (left or right?)      | | | 		 *        | | (left or right?)      | | | ||||||
| 		 *       pivot                      x | 		 *       pivot                      x | ||||||
| 		 *       /  \                     /  \ | 		 *       /  \                     /  \ | ||||||
| @ -487,15 +482,15 @@ protected: | |||||||
| 		 * | 		 * | ||||||
| 		 * | 		 * | ||||||
| 		 * the actual implementation here resolves the pivot's relationship to | 		 * the actual implementation here resolves the pivot's relationship to | ||||||
| 		 * its parent by comparaing pointers as it is not known if the pivot pair | 		 * its up by comparaing pointers as it is not known if the pivot pair | ||||||
| 		 * is the left child or the right child of its parent, | 		 * is the left child or the right child of its up, | ||||||
| 		 */ | 		 */ | ||||||
|  |  | ||||||
| 		Node* parent, * z, * c; | 		Node* up, * z, * c; | ||||||
|  |  | ||||||
| 		QSE_ASSERT (pivot != QSE_NULL); | 		QSE_ASSERT (pivot != QSE_NULL); | ||||||
|  |  | ||||||
| 		parent = pivot->parent; | 		up = pivot->up; | ||||||
| 		if (leftwise) | 		if (leftwise) | ||||||
| 		{ | 		{ | ||||||
| 			// y for leftwise rotation | 			// y for leftwise rotation | ||||||
| @ -511,17 +506,17 @@ protected: | |||||||
| 			c = z->right; | 			c = z->right; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		z->parent = parent; | 		z->up = up; | ||||||
| 		if (parent->notNil()) | 		if (up->notNil()) | ||||||
| 		{ | 		{ | ||||||
| 			if (parent->left == pivot) | 			if (up->left == pivot) | ||||||
| 			{ | 			{ | ||||||
| 				parent->left = z; | 				up->left = z; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				QSE_ASSERT (parent->right == pivot); | 				QSE_ASSERT (up->right == pivot); | ||||||
| 				parent->right = z; | 				up->right = z; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -541,8 +536,8 @@ protected: | |||||||
| 			pivot->left = c; | 			pivot->left = c; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (pivot->notNil()) pivot->parent = z; | 		if (pivot->notNil()) pivot->up = z; | ||||||
| 		if (c->notNil()) c->parent = pivot; | 		if (c->notNil()) c->up = pivot; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void rotate_left (Node* pivot) | 	void rotate_left (Node* pivot) | ||||||
| @ -562,12 +557,12 @@ protected: | |||||||
| 			Node* tmp, * tmp2, * x_par, * x_grand_par; | 			Node* tmp, * tmp2, * x_par, * x_grand_par; | ||||||
| 			bool leftwise; | 			bool leftwise; | ||||||
|  |  | ||||||
| 			x_par = node->parent; | 			x_par = node->up; | ||||||
| 			if (x_par->color == Node::BLACK) break; | 			if (x_par->color == Node::BLACK) break; | ||||||
|  |  | ||||||
| 			QSE_ASSERT (x_par->parent->notNil()); | 			QSE_ASSERT (x_par->up->notNil()); | ||||||
|  |  | ||||||
| 			x_grand_par = x_par->parent; | 			x_grand_par = x_par->up; | ||||||
| 			if (x_par == x_grand_par->left) | 			if (x_par == x_grand_par->left) | ||||||
| 			{ | 			{ | ||||||
| 				tmp = x_grand_par->right; | 				tmp = x_grand_par->right; | ||||||
| @ -594,8 +589,8 @@ protected: | |||||||
| 				{ | 				{ | ||||||
| 					node = x_par; | 					node = x_par; | ||||||
| 					this->rotate (node, leftwise); | 					this->rotate (node, leftwise); | ||||||
| 					x_par = node->parent; | 					x_par = node->up; | ||||||
| 					x_grand_par = x_par->parent; | 					x_grand_par = x_par->up; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				x_par->color = Node::BLACK; | 				x_par->color = Node::BLACK; | ||||||
| @ -627,7 +622,7 @@ protected: | |||||||
| 				{ | 				{ | ||||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | 					if (tmp->notNil()) tmp->color = Node::RED; | ||||||
| 					node = par; | 					node = par; | ||||||
| 					par = node->parent; | 					par = node->up; | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| @ -666,7 +661,7 @@ protected: | |||||||
| 				{ | 				{ | ||||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | 					if (tmp->notNil()) tmp->color = Node::RED; | ||||||
| 					node = par; | 					node = par; | ||||||
| 					par = node->parent; | 					par = node->up; | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| @ -711,8 +706,8 @@ protected: | |||||||
|  |  | ||||||
| 		x = (y->left->isNil())? y->right: y->left; | 		x = (y->left->isNil())? y->right: y->left; | ||||||
|  |  | ||||||
| 		par = y->parent; | 		par = y->up; | ||||||
| 		if (x->notNil()) x->parent = par; | 		if (x->notNil()) x->up = par; | ||||||
|  |  | ||||||
| 		if (par->notNil()) // if (par) | 		if (par->notNil()) // if (par) | ||||||
| 		{ | 		{ | ||||||
| @ -738,23 +733,23 @@ protected: | |||||||
| 			if (y->color == Node::BLACK && x->notNil()) | 			if (y->color == Node::BLACK && x->notNil()) | ||||||
| 				this->rebalance_for_removal (x, par); | 				this->rebalance_for_removal (x, par); | ||||||
|  |  | ||||||
| 			if (node->parent->notNil()) //if (node->parent) | 			if (node->up->notNil()) //if (node->up) | ||||||
| 			{ | 			{ | ||||||
| 				if (node->parent->left == node) node->parent->left = y; | 				if (node->up->left == node) node->up->left = y; | ||||||
| 				if (node->parent->right == node) node->parent->right = y; | 				if (node->up->right == node) node->up->right = y; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				this->root = y; | 				this->root = y; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			y->parent = node->parent; | 			y->up = node->up; | ||||||
| 			y->left = node->left; | 			y->left = node->left; | ||||||
| 			y->right = node->right; | 			y->right = node->right; | ||||||
| 			y->color = node->color; | 			y->color = node->color; | ||||||
|  |  | ||||||
| 			if (node->left->parent == node) node->left->parent = y; | 			if (node->left->up == node) node->left->up = y; | ||||||
| 			if (node->right->parent == node) node->right->parent = y; | 			if (node->right->up == node) node->right->up = y; | ||||||
|  |  | ||||||
| 			this->dispose_node (node); | 			this->dispose_node (node); | ||||||
| 		} | 		} | ||||||
| @ -800,7 +795,6 @@ public: | |||||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum); | 		return this->heterofind_node<MT,MCOMPARATOR> (datum); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	template <typename MT, typename MCOMPARATOR> | 	template <typename MT, typename MCOMPARATOR> | ||||||
| 	T* heterofindValue(const MT& datum) | 	T* heterofindValue(const MT& datum) | ||||||
| 	{ | 	{ | ||||||
| @ -839,6 +833,20 @@ public: | |||||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum); | 		return this->heterofind_node<MT,MCOMPARATOR> (datum); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/// The inject() function inserts a \a datum if no existing datum | ||||||
|  | 	/// is found to be equal using the comparator. The \a mode argument | ||||||
|  | 	/// determines what action to take when an equal datum is found. | ||||||
|  | 	/// - -1: failure | ||||||
|  | 	/// -  0: do nothing | ||||||
|  | 	/// -  1: overwrite the existing datum | ||||||
|  | 	/// | ||||||
|  | 	/// if \a injected is not #QSE_NULL, it is set to true when \a datum | ||||||
|  | 	/// has been inserted newly and false when an equal datum has been | ||||||
|  | 	/// found. | ||||||
|  | 	/// | ||||||
|  | 	/// The function returns the poniter to the node inserted or  | ||||||
|  | 	/// affected. It return #QSE_NULL if mode is set to -1 and a duplicate | ||||||
|  | 	/// item has been found. | ||||||
| 	Node* inject (const T& datum, int mode, bool* injected = QSE_NULL) | 	Node* inject (const T& datum, int mode, bool* injected = QSE_NULL) | ||||||
| 	{ | 	{ | ||||||
| 		Node* x_cur = this->root; | 		Node* x_cur = this->root; | ||||||
| @ -881,7 +889,7 @@ public: | |||||||
| 				x_par->left = x_new; | 				x_par->left = x_new; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			x_new->parent = x_par; | 			x_new->up = x_par; | ||||||
| 			this->rebalance_for_injection (x_new); | 			this->rebalance_for_injection (x_new); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | |||||||
| @ -80,6 +80,13 @@ void operator delete (void* ptr, QSE::Mmgr* mmgr) | |||||||
| 	mmgr->dispose (ptr); | 	mmgr->dispose (ptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void* operator new (qse_size_t size, QSE::Mmgr* mmgr, void* existing_ptr) | ||||||
|  | { | ||||||
|  | 	// mmgr unused. i put it in the parameter list to make this function | ||||||
|  | 	// less conflicting with the stock ::operator new() that doesn't allocate. | ||||||
|  | 	return existing_ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr) | void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr) | ||||||
| { | { | ||||||
|  | |||||||
| @ -190,3 +190,8 @@ void operator delete (void* ptr, QSE::Mpool* mp) | |||||||
| 	if (mp->isEnabled()) mp->dispose (ptr); | 	if (mp->isEnabled()) mp->dispose (ptr); | ||||||
| 	else ::operator delete (ptr, mp->getMmgr()); | 	else ::operator delete (ptr, mp->getMmgr()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void* operator new (qse_size_t size, QSE::Mpool* mp, void* existing_ptr) | ||||||
|  | { | ||||||
|  | 	return existing_ptr; | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user