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 += \ | ||||
| 	Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ | ||||
| 	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | ||||
| 	RedBlackTree.hpp RedBlackTable.hpp | ||||
| 	RedBlackTree.hpp RedBlackTable.hpp \ | ||||
| 	Array.hpp BinaryHeap.hpp | ||||
| endif | ||||
|  | ||||
|  | ||||
| @ -53,7 +53,8 @@ host_triplet = @host@ | ||||
| @ENABLE_CXX_TRUE@am__append_1 = \ | ||||
| @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@	RedBlackTree.hpp RedBlackTable.hpp | ||||
| @ENABLE_CXX_TRUE@	RedBlackTree.hpp RedBlackTable.hpp \ | ||||
| @ENABLE_CXX_TRUE@	Array.hpp BinaryHeap.hpp | ||||
|  | ||||
| subdir = include/qse/cmn | ||||
| 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 \ | ||||
| 	utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.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 = case $$p in \ | ||||
|     $(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 delete (void* ptr, QSE::Mmgr* mmgr); | ||||
|  | ||||
| void* operator new (qse_size_t size, QSE::Mmgr* mmgr, void* existing_ptr); | ||||
|  | ||||
| #if 0 | ||||
| // i found no way to delete an array allocated with | ||||
| // 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 delete (void* ptr, QSE::Mpool* mp); | ||||
|  | ||||
| void* operator new (qse_size_t size, QSE::Mpool* mp, void* existing_ptr); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @ -55,19 +55,19 @@ public: | ||||
|  | ||||
| protected: | ||||
| 	Color color; | ||||
| 	SelfType* parent; | ||||
| 	SelfType* up; | ||||
| 	SelfType* left; // left 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. | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right): | ||||
| 		value (value), color (color), parent (parent), left (left), right (right) | ||||
| 	RedBlackTreeNode(const T& value, Color color, SelfType* up, SelfType* left, SelfType* 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 (right != this); | ||||
| 	} | ||||
| @ -79,7 +79,7 @@ public: | ||||
|  | ||||
| 	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 | ||||
| @ -90,28 +90,21 @@ public: | ||||
| 	bool isBlack () const  { return this->color == BLACK; } | ||||
| 	bool isRed () const { return this->color == RED; } | ||||
|  | ||||
| 	SelfType* getParent () { return this->parent; } | ||||
| 	const SelfType* getParent () const { return this->parent; } | ||||
| 	SelfType* getParentNode () { return this->parent; } | ||||
| 	const SelfType* getParentNode () const { return this->parent; } | ||||
| 	SelfType* getUpNode () { return this->up; } | ||||
| 	const SelfType* getUpNode () const { return this->up; } | ||||
|  | ||||
| 	 | ||||
| 	SelfType* getLeft () { return this->left; } | ||||
| 	const SelfType* getLeft () const { return this->left; } | ||||
| 	SelfType* getLeftNode () { 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; } | ||||
| 	const SelfType* getRightNode () 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; } | ||||
|  | ||||
|  | ||||
| 	//void setUpNode (SelfType* node) { this->up = node; } | ||||
| 	//void setLeftNode (SelfType* node) { this->left = node; } | ||||
| 	//void setRightNode (SelfType* node) { this->right = node; } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| @ -153,16 +146,16 @@ public: | ||||
| 	{ | ||||
| 		QSE_ASSERT (root != QSE_NULL); | ||||
|  | ||||
| 		this->previous = root->getParent(); | ||||
| 		this->previous = root->getUpNode(); | ||||
| 		if (mode == DESCENDING) | ||||
| 		{ | ||||
| 			this->get_left = &Node::getRight; | ||||
| 			this->get_right = &Node::getLeft; | ||||
| 			this->get_left = &Node::getRightNode; | ||||
| 			this->get_right = &Node::getLeftNode; | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			this->get_left = &Node::getLeft; | ||||
| 			this->get_right = &Node::getRight; | ||||
| 			this->get_left = &Node::getLeftNode; | ||||
| 			this->get_right = &Node::getRightNode; | ||||
| 		} | ||||
|  | ||||
| 		this->__move_to_next_node (); | ||||
| @ -175,9 +168,9 @@ protected: | ||||
|  | ||||
| 		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) */ | ||||
| 				if ((this->current->*this->get_left)()->notNil()) | ||||
| 				{ | ||||
| @ -201,9 +194,9 @@ protected: | ||||
| 			{ | ||||
| 				/* both the left child and the right child have been traversed */ | ||||
| 				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->current = this->current->getParent(); | ||||
| 				this->current = this->current->getUpNode(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @ -220,9 +213,9 @@ protected: | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* otherwise, move up to the parent */ | ||||
| 				/* otherwise, move up to the up */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getParent(); | ||||
| 				this->current = this->current->getUpNode(); | ||||
| 			} | ||||
| 		} | ||||
| 		else if (pending_action == 2) | ||||
| @ -235,9 +228,9 @@ protected: | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* otherwise, move up to the parent */ | ||||
| 				/* otherwise, move up to the up */ | ||||
| 				this->previous = this->current; | ||||
| 				this->current = this->current->getParent(); | ||||
| 				this->current = this->current->getUpNode(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -327,7 +320,7 @@ public: | ||||
| 	typedef RedBlackTreeComparator<T> DefaultComparator; | ||||
|  | ||||
| 	RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): | ||||
| 		Mmged(mmgr), | ||||
| 		Mmged (mmgr), | ||||
| 		mp (mmgr, QSE_SIZEOF(Node), mpb_size), | ||||
| 		node_count (0) | ||||
| 	{ | ||||
| @ -338,8 +331,8 @@ public: | ||||
| 		this->root = this->nil; | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTree (const RedBlackTree& rbt):  | ||||
| 		Mmged(rbt.getMmgr()), | ||||
| 	RedBlackTree (const SelfType& rbt):  | ||||
| 		Mmged (rbt.getMmgr()), | ||||
| 		mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()), | ||||
| 		node_count (0) | ||||
| 	{ | ||||
| @ -365,7 +358,7 @@ public: | ||||
| 		this->dispose_node (this->nil); | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTree& operator= (const RedBlackTree& rbt) | ||||
| 	SelfType& operator= (const SelfType& rbt) | ||||
| 	{ | ||||
| 		this->clear (); | ||||
|  | ||||
| @ -400,14 +393,16 @@ public: | ||||
| 		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 () | ||||
| 	{ | ||||
| 		return this->root; | ||||
| 		return this->root->isNil()? QSE_NULL: this->root; | ||||
| 	} | ||||
|  | ||||
| 	const Node* getRootNode () const | ||||
| 	{ | ||||
| 		return this->root; | ||||
| 		return this->root->isNil()? QSE_NULL: this->root; | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| @ -463,7 +458,7 @@ protected: | ||||
| 		 * 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 | ||||
| 		 * of the new pivot position. | ||||
| 		 *       parent                   parent | ||||
| 		 *       up                   up | ||||
| 		 *        | | (left or right?)      | | | ||||
| 		 *       pivot                      y | ||||
| 		 *       /  \                     /  \ | ||||
| @ -477,7 +472,7 @@ protected: | ||||
| 		 * position. as 'c2' is between 'x' and 'pivot', move it to the left | ||||
| 		 * of the new pivot position. | ||||
| 		 * | ||||
| 		 *       parent                   parent | ||||
| 		 *       up                   up | ||||
| 		 *        | | (left or right?)      | | | ||||
| 		 *       pivot                      x | ||||
| 		 *       /  \                     /  \ | ||||
| @ -487,15 +482,15 @@ protected: | ||||
| 		 * | ||||
| 		 * | ||||
| 		 * the actual implementation here resolves the pivot's relationship to | ||||
| 		 * its parent by comparaing pointers as it is not known if the pivot pair | ||||
| 		 * is the left child or the right child of its parent, | ||||
| 		 * its up by comparaing pointers as it is not known if the pivot pair | ||||
| 		 * is the left child or the right child of its up, | ||||
| 		 */ | ||||
|  | ||||
| 		Node* parent, * z, * c; | ||||
| 		Node* up, * z, * c; | ||||
|  | ||||
| 		QSE_ASSERT (pivot != QSE_NULL); | ||||
|  | ||||
| 		parent = pivot->parent; | ||||
| 		up = pivot->up; | ||||
| 		if (leftwise) | ||||
| 		{ | ||||
| 			// y for leftwise rotation | ||||
| @ -511,17 +506,17 @@ protected: | ||||
| 			c = z->right; | ||||
| 		} | ||||
|  | ||||
| 		z->parent = parent; | ||||
| 		if (parent->notNil()) | ||||
| 		z->up = up; | ||||
| 		if (up->notNil()) | ||||
| 		{ | ||||
| 			if (parent->left == pivot) | ||||
| 			if (up->left == pivot) | ||||
| 			{ | ||||
| 				parent->left = z; | ||||
| 				up->left = z; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				QSE_ASSERT (parent->right == pivot); | ||||
| 				parent->right = z; | ||||
| 				QSE_ASSERT (up->right == pivot); | ||||
| 				up->right = z; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| @ -541,8 +536,8 @@ protected: | ||||
| 			pivot->left = c; | ||||
| 		} | ||||
|  | ||||
| 		if (pivot->notNil()) pivot->parent = z; | ||||
| 		if (c->notNil()) c->parent = pivot; | ||||
| 		if (pivot->notNil()) pivot->up = z; | ||||
| 		if (c->notNil()) c->up = pivot; | ||||
| 	} | ||||
|  | ||||
| 	void rotate_left (Node* pivot) | ||||
| @ -562,12 +557,12 @@ protected: | ||||
| 			Node* tmp, * tmp2, * x_par, * x_grand_par; | ||||
| 			bool leftwise; | ||||
|  | ||||
| 			x_par = node->parent; | ||||
| 			x_par = node->up; | ||||
| 			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) | ||||
| 			{ | ||||
| 				tmp = x_grand_par->right; | ||||
| @ -594,8 +589,8 @@ protected: | ||||
| 				{ | ||||
| 					node = x_par; | ||||
| 					this->rotate (node, leftwise); | ||||
| 					x_par = node->parent; | ||||
| 					x_grand_par = x_par->parent; | ||||
| 					x_par = node->up; | ||||
| 					x_grand_par = x_par->up; | ||||
| 				} | ||||
|  | ||||
| 				x_par->color = Node::BLACK; | ||||
| @ -627,7 +622,7 @@ protected: | ||||
| 				{ | ||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | ||||
| 					node = par; | ||||
| 					par = node->parent; | ||||
| 					par = node->up; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| @ -666,7 +661,7 @@ protected: | ||||
| 				{ | ||||
| 					if (tmp->notNil()) tmp->color = Node::RED; | ||||
| 					node = par; | ||||
| 					par = node->parent; | ||||
| 					par = node->up; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| @ -711,8 +706,8 @@ protected: | ||||
|  | ||||
| 		x = (y->left->isNil())? y->right: y->left; | ||||
|  | ||||
| 		par = y->parent; | ||||
| 		if (x->notNil()) x->parent = par; | ||||
| 		par = y->up; | ||||
| 		if (x->notNil()) x->up = par; | ||||
|  | ||||
| 		if (par->notNil()) // if (par) | ||||
| 		{ | ||||
| @ -738,23 +733,23 @@ protected: | ||||
| 			if (y->color == Node::BLACK && x->notNil()) | ||||
| 				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->parent->right == node) node->parent->right = y; | ||||
| 				if (node->up->left == node) node->up->left = y; | ||||
| 				if (node->up->right == node) node->up->right = y; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				this->root = y; | ||||
| 			} | ||||
|  | ||||
| 			y->parent = node->parent; | ||||
| 			y->up = node->up; | ||||
| 			y->left = node->left; | ||||
| 			y->right = node->right; | ||||
| 			y->color = node->color; | ||||
|  | ||||
| 			if (node->left->parent == node) node->left->parent = y; | ||||
| 			if (node->right->parent == node) node->right->parent = y; | ||||
| 			if (node->left->up == node) node->left->up = y; | ||||
| 			if (node->right->up == node) node->right->up = y; | ||||
|  | ||||
| 			this->dispose_node (node); | ||||
| 		} | ||||
| @ -800,7 +795,6 @@ public: | ||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	template <typename MT, typename MCOMPARATOR> | ||||
| 	T* heterofindValue(const MT& datum) | ||||
| 	{ | ||||
| @ -839,6 +833,20 @@ public: | ||||
| 		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* x_cur = this->root; | ||||
| @ -881,7 +889,7 @@ public: | ||||
| 				x_par->left = x_new; | ||||
| 			} | ||||
|  | ||||
| 			x_new->parent = x_par; | ||||
| 			x_new->up = x_par; | ||||
| 			this->rebalance_for_injection (x_new); | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -80,6 +80,13 @@ void operator delete (void* ptr, QSE::Mmgr* mmgr) | ||||
| 	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 | ||||
| void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr) | ||||
| { | ||||
|  | ||||
| @ -182,7 +182,7 @@ QSE_END_NAMESPACE(QSE) | ||||
|  | ||||
| void* operator new (qse_size_t size, QSE::Mpool* mp) | ||||
| { | ||||
| 	return mp->isEnabled()? mp->allocate (): ::operator new (size, mp->getMmgr()); | ||||
| 	return mp->isEnabled()? mp->allocate(): ::operator new(size, mp->getMmgr()); | ||||
| } | ||||
|  | ||||
| void operator delete (void* ptr, QSE::Mpool* mp) | ||||
| @ -190,3 +190,8 @@ void operator delete (void* ptr, QSE::Mpool* mp) | ||||
| 	if (mp->isEnabled()) mp->dispose (ptr); | ||||
| 	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