added HashList::inject() and HashTable::inject().
improved HashTable::upsert(). added HashList::ensert() and HashTable::ensert(). started porting rbt to RedBlackTree
This commit is contained in:
		| @ -44,7 +44,7 @@ struct HashListHasher | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct HashListComparator | ||||
| struct HashListEqualer | ||||
| { | ||||
| 	bool operator() (const T& v1, const T& v2) const | ||||
| 	{ | ||||
| @ -76,18 +76,18 @@ struct HashListResizer | ||||
| /// For a hash value of hc, this->nodes[hc * 2] points to the first node and | ||||
| /// this->nodes[hc * 2 + 1] ponits to the last node.      | ||||
|  | ||||
| template <typename T, typename HASHER = HashListHasher<T>, typename COMPARATOR = HashListComparator<T>, typename RESIZER = HashListResizer > | ||||
| template <typename T, typename HASHER = HashListHasher<T>, typename EQUALER = HashListEqualer<T>, typename RESIZER = HashListResizer > | ||||
| class HashList: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef LinkedList<T,COMPARATOR> DatumList; | ||||
| 	typedef LinkedList<T,EQUALER> DatumList; | ||||
| 	typedef typename DatumList::Node Node; | ||||
| 	typedef typename DatumList::Iterator Iterator; | ||||
| 	typedef typename DatumList::ConstIterator ConstIterator; | ||||
| 	typedef HashList<T,HASHER,COMPARATOR,RESIZER> SelfType; | ||||
| 	typedef HashList<T,HASHER,EQUALER,RESIZER> SelfType; | ||||
|  | ||||
| 	typedef HashListHasher<T> DefaultHasher; | ||||
| 	typedef HashListComparator<T> DefaultComparator; | ||||
| 	typedef HashListEqualer<T> DefaultEqualer; | ||||
| 	typedef HashListResizer DefaultResizer; | ||||
|  | ||||
| 	enum | ||||
| @ -304,7 +304,7 @@ protected: | ||||
| 			do  | ||||
| 			{ | ||||
| 				T& t = np->value; | ||||
| 				if (this->comparator(datum, t)) return np; | ||||
| 				if (this->equaler(datum, t)) return np; | ||||
| 				if (np == this->nodes[tail]) break; | ||||
| 				np = np->getNextNode (); | ||||
| 			} | ||||
| @ -314,10 +314,10 @@ protected: | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MEQUALER> | ||||
| 	Node* heterofind_node (const MT& datum, qse_size_t hc) const | ||||
| 	{ | ||||
| 		MCOMPARATOR is_equal; | ||||
| 		MEQUALER m_Equaler; | ||||
|  | ||||
| 		qse_size_t head, tail; | ||||
| 		Node* np; | ||||
| @ -330,7 +330,7 @@ protected: | ||||
| 			do  | ||||
| 			{ | ||||
| 				T& t = np->value; | ||||
| 				if (is_equal(datum, t)) return np; | ||||
| 				if (m_Equaler(datum, t)) return np; | ||||
| 				if (np == this->nodes[tail]) break; | ||||
| 				np = np->getNextNode (); | ||||
| 			} | ||||
| @ -340,53 +340,6 @@ protected: | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	Node* insert_value (const T& datum, bool overwrite = true) | ||||
| 	{ | ||||
| 		qse_size_t hc, head, tail; | ||||
| 		Node* np; | ||||
|  | ||||
| 		hc = this->hasher(datum) % this->node_capacity; | ||||
| 		head = hc << 1; tail = head + 1; | ||||
|  | ||||
| 		np = this->nodes[head]; | ||||
| 		if (np)  | ||||
| 		{ | ||||
| 			do  | ||||
| 			{ | ||||
| 				T& t = np->value; | ||||
| 				if (this->comparator(datum, t))  | ||||
| 				{ | ||||
| 					if (!overwrite) return QSE_NULL; | ||||
| 					t = datum; | ||||
| 					return np; | ||||
| 				} | ||||
|  | ||||
| 				if (np == this->nodes[tail]) break; | ||||
| 				np = np->getNextNode (); | ||||
| 			} | ||||
| 			while (1);  | ||||
| 		} | ||||
|  | ||||
| 		if (datum_list->getSize() >= threshold)  | ||||
| 		{ | ||||
| 			this->rehash (); | ||||
| 			hc = this->hasher(datum) % this->node_capacity; | ||||
| 			head = hc << 1; tail = head + 1; | ||||
| 		} | ||||
|  | ||||
| 		if (nodes[head] == QSE_NULL)  | ||||
| 		{ | ||||
| 			this->nodes[head] = this->datum_list->insert ((Node*)QSE_NULL, datum); | ||||
| 			this->nodes[tail] = this->nodes[head]; | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			this->nodes[head] = this->datum_list->insert (this->nodes[head], datum); | ||||
| 		} | ||||
|  | ||||
| 		return this->nodes[head]; | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	Node* findNode (const T& datum) | ||||
| 	{ | ||||
| @ -412,34 +365,34 @@ public: | ||||
| 		return &b->value; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	Node* heterofindNode (const MT& datum) | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		return this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	const Node* heterofindNode (const MT& datum) const | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		return this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	T* heterofindValue(const MT& datum) | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		Node* b = this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		Node* b = this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 		if (!b) return QSE_NULL; | ||||
| 		return &b->value; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	const T* heterofindValue(const MT& datum) const | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		Node* b = this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		Node* b = this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 		if (!b) return QSE_NULL; | ||||
| 		return &b->value; | ||||
| 	} | ||||
| @ -460,23 +413,82 @@ public: | ||||
| 		return this->find_node (datum); | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	Node* heterosearch (const MT& datum) | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		return this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	const Node* heterosearch (const MT& datum) const | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		return this->heterofind_node<MT,MCOMPARATOR> (datum, hash(datum) % this->node_capacity); | ||||
| 		return this->heterofind_node<MT,MEQUALER> (datum, hash(datum) % this->node_capacity); | ||||
| 	} | ||||
|  | ||||
| 	Node* inject (const T& datum, int mode, bool* injected = QSE_NULL) | ||||
| 	{ | ||||
| 		qse_size_t hc, head, tail; | ||||
| 		Node* np; | ||||
|  | ||||
| 		hc = this->hasher(datum) % this->node_capacity; | ||||
| 		head = hc << 1; tail = head + 1; | ||||
|  | ||||
| 		np = this->nodes[head]; | ||||
| 		if (np)  | ||||
| 		{ | ||||
| 			do  | ||||
| 			{ | ||||
| 				T& t = np->value; | ||||
| 				if (this->equaler(datum, t))  | ||||
| 				{ | ||||
| 					if (injected) *injected = false; | ||||
| 					if (mode <= -1) return QSE_NULL; // failure | ||||
| 					if (mode >= 1) t = datum; // overwrite | ||||
| 					return np; | ||||
| 				} | ||||
|  | ||||
| 				if (np == this->nodes[tail]) break; | ||||
| 				np = np->getNextNode (); | ||||
| 			} | ||||
| 			while (1);  | ||||
| 		} | ||||
|  | ||||
| 		if (datum_list->getSize() >= threshold)  | ||||
| 		{ | ||||
| 			this->rehash (); | ||||
| 			hc = this->hasher(datum) % this->node_capacity; | ||||
| 			head = hc << 1; tail = head + 1; | ||||
| 		} | ||||
|  | ||||
| 		if (nodes[head] == QSE_NULL)  | ||||
| 		{ | ||||
| 			this->nodes[head] = this->datum_list->insert ((Node*)QSE_NULL, datum); | ||||
| 			this->nodes[tail] = this->nodes[head]; | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			this->nodes[head] = this->datum_list->insert (this->nodes[head], datum); | ||||
| 		} | ||||
|  | ||||
| 		if (injected) *injected = true; | ||||
| 		return this->nodes[head]; | ||||
| 	} | ||||
|  | ||||
| 	Node* insert (const T& datum) | ||||
| 	{ | ||||
| 		return this->insert_value (datum, false); | ||||
| 		return this->inject (datum, -1, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| 	Node* ensert (const T& datum) | ||||
| 	{ | ||||
| 		return this->inject (datum, 0, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| 	Node* upsert (const T& datum) | ||||
| 	{ | ||||
| 		return this->inject (datum, 1, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| 	Node* update (const T& datum) | ||||
| @ -486,11 +498,6 @@ public: | ||||
| 		return node; | ||||
| 	} | ||||
|  | ||||
| 	Node* upsert (const T& datum) | ||||
| 	{ | ||||
| 		return this->insert_value (datum, true); | ||||
| 	} | ||||
|  | ||||
| 	int remove (const T& datum) | ||||
| 	{ | ||||
| 		qse_size_t hc, head, tail; | ||||
| @ -505,7 +512,7 @@ public: | ||||
| 			do  | ||||
| 			{ | ||||
| 				T& t = np->value; | ||||
| 				if (this->comparator(datum, t))  | ||||
| 				if (this->equaler(datum, t))  | ||||
| 				{ | ||||
| 					if (this->nodes[head] == this->nodes[tail]) | ||||
| 					{ | ||||
| @ -534,13 +541,13 @@ public: | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MT, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MT, typename MHASHER, typename MEQUALER> | ||||
| 	int heteroremove (const MT& datum) | ||||
| 	{ | ||||
| 		MHASHER hash; | ||||
| 		qse_size_t hc = hash(datum) % this->node_capacity; | ||||
|  | ||||
| 		Node* np = this->heterofind_node<MT,MCOMPARATOR> (datum, hc); | ||||
| 		Node* np = this->heterofind_node<MT,MEQUALER> (datum, hc); | ||||
| 		if (np) | ||||
| 		{ | ||||
| 			qse_size_t head, tail; | ||||
| @ -614,7 +621,7 @@ protected: | ||||
| 	mutable qse_size_t threshold; | ||||
| 	qse_size_t         load_factor; | ||||
| 	HASHER             hasher; | ||||
| 	COMPARATOR         comparator; | ||||
| 	EQUALER            equaler; | ||||
| 	RESIZER            resizer; | ||||
|  | ||||
| 	void rehash ()  | ||||
|  | ||||
| @ -44,7 +44,7 @@ struct HashTableHasher | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct HashTableComparator | ||||
| struct HashTableEqualer | ||||
| { | ||||
| 	// it must return true if two values are equal | ||||
| 	bool operator() (const T& v1, const T& v2) const | ||||
| @ -55,15 +55,15 @@ struct HashTableComparator | ||||
|  | ||||
| typedef HashListResizer HashTableResizer; | ||||
|  | ||||
| template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename COMPARATOR = HashTableComparator<K>, typename RESIZER = HashTableResizer> | ||||
| template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename EQUALER = HashTableEqualer<K>, typename RESIZER = HashTableResizer> | ||||
| class HashTable: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef Association<K,V> Pair; | ||||
| 	typedef HashTable<K,V,HASHER,COMPARATOR,RESIZER> SelfType; | ||||
| 	typedef HashTable<K,V,HASHER,EQUALER,RESIZER> SelfType; | ||||
|  | ||||
| 	typedef HashTableHasher<K> DefaultHasher; | ||||
| 	typedef HashTableComparator<K> DefaultComparator; | ||||
| 	typedef HashTableEqualer<K> DefaultEqualer; | ||||
| 	typedef HashTableResizer DefaultResizer; | ||||
|  | ||||
| 	struct PairHasher | ||||
| @ -75,35 +75,35 @@ public: | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	struct PairComparator | ||||
| 	struct PairEqualer | ||||
| 	{ | ||||
| 		qse_size_t operator() (const Pair& p1, const Pair& p2) const | ||||
| 		{ | ||||
| 			COMPARATOR comparator; | ||||
| 			return comparator (p1.key, p2.key); | ||||
| 			EQUALER equaler; | ||||
| 			return equaler (p1.key, p2.key); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	struct PairHeteroComparator | ||||
| 	struct PairHeteroEqualer | ||||
| 	{ | ||||
| 		qse_size_t operator() (const K& p1, const Pair& p2) const | ||||
| 		{ | ||||
| 			COMPARATOR is_equal; | ||||
| 			return is_equal (p1, p2.key); | ||||
| 			EQUALER equaler; | ||||
| 			return equaler (p1, p2.key); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	template <typename MK, typename MCOMPARATOR> | ||||
| 	struct MHeteroComparator | ||||
| 	template <typename MK, typename MEQUALER> | ||||
| 	struct MHeteroEqualer | ||||
| 	{ | ||||
| 		qse_size_t operator() (const MK& p1, const Pair& p2) const | ||||
| 		{ | ||||
| 			MCOMPARATOR is_equal; | ||||
| 			return is_equal (p1, p2.key); | ||||
| 			MEQUALER mequaler; | ||||
| 			return mequaler (p1, p2.key); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	typedef HashList<Pair,PairHasher,PairComparator,RESIZER> PairList; | ||||
| 	typedef HashList<Pair,PairHasher,PairEqualer,RESIZER> PairList; | ||||
| 	typedef typename PairList::Node PairNode; | ||||
| 	typedef typename PairList::Iterator Iterator; | ||||
| 	typedef typename PairList::ConstIterator ConstIterator; | ||||
| @ -180,6 +180,13 @@ public: | ||||
| 		return this->pair_list.getTailNode (); | ||||
| 	} | ||||
|  | ||||
| 	Pair* inject (const K& key, const V& value, int mode, bool* injected = QSE_NULL) | ||||
| 	{ | ||||
| 		PairNode* node = this->pair_list.inject (Pair(key, value), mode, injected); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		return &node->value; | ||||
| 	} | ||||
|  | ||||
| 	Pair* insert (const K& key, const V& value) | ||||
| 	{ | ||||
| 		PairNode* node = this->pair_list.insert (Pair(key, value)); | ||||
| @ -187,20 +194,38 @@ public: | ||||
| 		return &node->value; | ||||
| 	} | ||||
|  | ||||
| 	Pair* upsert (const K& key, const V& value) | ||||
| 	Pair* ensert (const K& key, const V& value) | ||||
| 	{ | ||||
| 		PairNode* node = this->pair_list.upsert (Pair(key, value)); | ||||
| 		PairNode* node = this->pair_list.ensert (Pair(key, value)); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		return &node->value; | ||||
| 	} | ||||
|  | ||||
| 	Pair* upsert (const K& key, const V& value) | ||||
| 	{ | ||||
| 		//PairNode* node = this->pair_list.upsert (Pair(key, value)); | ||||
| 		//if (!node) return QSE_NULL; | ||||
| 		//return &node->value; | ||||
|  | ||||
| 		// Don't call pair_list.upsert() to make sure that the 'key' object | ||||
| 		// itself remains identical after potential update operation.  | ||||
| 		// pair_list.upsert() changes the Pair object as a whole. so this | ||||
| 		// trick is required. | ||||
| 		bool injected; | ||||
| 		PairNode* node = this->pair_list.inject (Pair(key, value), 0, &injected); | ||||
| 		QSE_ASSERT (node != QSE_NULL); | ||||
| 		Pair& pair = node->value; | ||||
| 		if (injected) pair.value = value; | ||||
| 		return &pair; | ||||
| 	} | ||||
|  | ||||
| 	Pair* update (const K& key, const V& value) | ||||
| 	{ | ||||
| 		//PairNode* node = this->pair_list.update (Pair(key, value)); | ||||
| 		//if (!node) return QSE_NULL; | ||||
| 		//return &node->value; | ||||
|  | ||||
| 		PairNode* node = this->pair_list.template heterofindNode<K,HASHER,PairHeteroComparator> (key); | ||||
| 		PairNode* node = this->pair_list.template heterofindNode<K,HASHER,PairHeteroEqualer> (key); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		Pair& pair = node->value; | ||||
| 		pair.value = value; | ||||
| @ -210,7 +235,7 @@ public: | ||||
| 	Pair* search (const K& key) | ||||
| 	{ | ||||
| 		//PairNode* node = this->pair_list.update (Pair(key)); | ||||
| 		PairNode* node = this->pair_list.template heterofindNode<K,HASHER,PairHeteroComparator> (key); | ||||
| 		PairNode* node = this->pair_list.template heterofindNode<K,HASHER,PairHeteroEqualer> (key); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		return &node->value; | ||||
| 	} | ||||
| @ -218,32 +243,32 @@ public: | ||||
| 	int remove (const K& key) | ||||
| 	{ | ||||
| 		//return this->pair_list.remove (Pair(key)); | ||||
| 		return this->pair_list.template heteroremove<K,HASHER,PairHeteroComparator> (key); | ||||
| 		return this->pair_list.template heteroremove<K,HASHER,PairHeteroEqualer> (key); | ||||
| 	} | ||||
|  | ||||
| 	template <typename MK, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MK, typename MHASHER, typename MEQUALER> | ||||
| 	Pair* heterosearch (const MK& key) | ||||
| 	{ | ||||
| 		typedef MHeteroComparator<MK,MCOMPARATOR> MComparator; | ||||
| 		PairNode* node = this->pair_list.template heterosearch<MK,MHASHER,MComparator> (key); | ||||
| 		typedef MHeteroEqualer<MK,MEQUALER> MEqualer; | ||||
| 		PairNode* node = this->pair_list.template heterosearch<MK,MHASHER,MEqualer> (key); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		return &node->value; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MK, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MK, typename MHASHER, typename MEQUALER> | ||||
| 	const Pair* heterosearch (const MK& key) const | ||||
| 	{ | ||||
| 		typedef MHeteroComparator<MK,MCOMPARATOR> MComparator; | ||||
| 		PairNode* node = this->pair_list.template heterosearch<MK,MHASHER,MComparator> (key); | ||||
| 		typedef MHeteroEqualer<MK,MEQUALER> MEqualer; | ||||
| 		PairNode* node = this->pair_list.template heterosearch<MK,MHASHER,MEqualer> (key); | ||||
| 		if (!node) return QSE_NULL; | ||||
| 		return &node->value; | ||||
| 	} | ||||
|  | ||||
| 	template <typename MK, typename MHASHER, typename MCOMPARATOR> | ||||
| 	template <typename MK, typename MHASHER, typename MEQUALER> | ||||
| 	int heteroremove (const MK& key) | ||||
| 	{ | ||||
| 		typedef MHeteroComparator<MK,MCOMPARATOR> MComparator; | ||||
| 		return this->pair_list.template heteroremove<MK,MHASHER,MComparator> (key); | ||||
| 		typedef MHeteroEqualer<MK,MEQUALER> MEqualer; | ||||
| 		return this->pair_list.template heteroremove<MK,MHASHER,MEqualer> (key); | ||||
| 	} | ||||
|  | ||||
| 	void clear (bool clear_mpool = false) | ||||
|  | ||||
| @ -34,14 +34,14 @@ | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| template <typename T, typename COMPARATOR> class LinkedList; | ||||
| template <typename T, typename EQUALER> class LinkedList; | ||||
|  | ||||
| template <typename T, typename COMPARATOR>  | ||||
| template <typename T, typename EQUALER>  | ||||
| class LinkedListNode | ||||
| { | ||||
| public: | ||||
| 	friend class LinkedList<T,COMPARATOR>; | ||||
| 	typedef LinkedListNode<T,COMPARATOR> SelfType; | ||||
| 	friend class LinkedList<T,EQUALER>; | ||||
| 	typedef LinkedListNode<T,EQUALER> SelfType; | ||||
|  | ||||
| 	T value; // you can use this variable or accessor functions below | ||||
|  | ||||
| @ -79,12 +79,12 @@ protected: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template <typename T, typename COMPARATOR, typename NODE, typename GET_T> | ||||
| template <typename T, typename EQUALER, typename NODE, typename GET_T> | ||||
| class LinkedListIterator { | ||||
| public: | ||||
| 	friend class LinkedList<T,COMPARATOR>; | ||||
| 	friend class LinkedList<T,EQUALER>; | ||||
| 	typedef NODE Node; | ||||
| 	typedef LinkedListIterator<T,COMPARATOR,NODE,GET_T> SelfType; | ||||
| 	typedef LinkedListIterator<T,EQUALER,NODE,GET_T> SelfType; | ||||
|  | ||||
| 	LinkedListIterator (): current(QSE_NULL) {} | ||||
| 	LinkedListIterator (Node* node): current(node) {} | ||||
| @ -178,7 +178,7 @@ protected: | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct LinkedListComparator | ||||
| struct LinkedListEqualer | ||||
| { | ||||
| 	// it must return true if two values are equal | ||||
| 	bool operator() (const T& v1, const T& v2) const | ||||
| @ -188,17 +188,17 @@ struct LinkedListComparator | ||||
| }; | ||||
|  | ||||
| /// | ||||
| /// The LinkedList<T,COMPARATOR> class provides a template for a doubly-linked list. | ||||
| /// The LinkedList<T,EQUALER> class provides a template for a doubly-linked list. | ||||
| /// | ||||
| template <typename T, typename COMPARATOR = LinkedListComparator<T> > class LinkedList: public Mmged | ||||
| template <typename T, typename EQUALER = LinkedListEqualer<T> > class LinkedList: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef LinkedList<T,COMPARATOR> SelfType; | ||||
| 	typedef LinkedListNode<T,COMPARATOR> Node; | ||||
| 	typedef LinkedListIterator<T,COMPARATOR,Node,T> Iterator; | ||||
| 	typedef LinkedListIterator<T,COMPARATOR,const Node,const T> ConstIterator; | ||||
| 	typedef LinkedList<T,EQUALER> SelfType; | ||||
| 	typedef LinkedListNode<T,EQUALER> Node; | ||||
| 	typedef LinkedListIterator<T,EQUALER,Node,T> Iterator; | ||||
| 	typedef LinkedListIterator<T,EQUALER,const Node,const T> ConstIterator; | ||||
|  | ||||
| 	typedef LinkedListComparator<T> DefaultComparator; | ||||
| 	typedef LinkedListEqualer<T> DefaultEqualer; | ||||
|  | ||||
| 	enum  | ||||
| 	{ | ||||
| @ -270,7 +270,7 @@ public: | ||||
|  | ||||
| 	bool isEmpty () const  | ||||
| 	{ | ||||
| 		return this->node_count == 0; | ||||
| 		return this->node_count <= 0; | ||||
| 	} | ||||
|  | ||||
| 	/// The insertNode() function inserts an externally created \a node | ||||
| @ -576,7 +576,7 @@ public: | ||||
| 	{ | ||||
| 		for (Node* p = this->head_node; p; p = p->next)  | ||||
| 		{ | ||||
| 			if (this->comparator (value, p->value)) return p; | ||||
| 			if (this->equaler (value, p->value)) return p; | ||||
| 		} | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
| @ -585,7 +585,7 @@ public: | ||||
| 	{ | ||||
| 		for (Node* p = tail_node; p; p = p->prev)  | ||||
| 		{ | ||||
| 			if (this->comparator (value, p->value)) return p; | ||||
| 			if (this->equaler (value, p->value)) return p; | ||||
| 		} | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
| @ -594,7 +594,7 @@ public: | ||||
| 	{ | ||||
| 		for (Node* p = head; p; p = p->next) | ||||
| 		{ | ||||
| 			if (this->comparator (value, p->value)) return p; | ||||
| 			if (this->equaler (value, p->value)) return p; | ||||
| 		} | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
| @ -603,7 +603,7 @@ public: | ||||
| 	{ | ||||
| 		for (Node* p = tail; p; p = p->prev)  | ||||
| 		{ | ||||
| 			if (this->comparator (value, p->value)) return p; | ||||
| 			if (this->equaler (value, p->value)) return p; | ||||
| 		} | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
| @ -613,7 +613,7 @@ public: | ||||
| 		qse_size_t index = 0; | ||||
| 		for (Node* p = this->head_node; p; p = p->next)  | ||||
| 		{ | ||||
| 			if (this->comparator (value, p->value)) return index; | ||||
| 			if (this->equaler (value, p->value)) return index; | ||||
| 			index++; | ||||
| 		} | ||||
| 		return INVALID_INDEX; | ||||
| @ -625,7 +625,7 @@ public: | ||||
| 		for (Node* p = tail_node; p; p = p->prev)  | ||||
| 		{ | ||||
| 			index--; | ||||
| 			if (this->comparator (value, p->value)) return index; | ||||
| 			if (this->equaler (value, p->value)) return index; | ||||
| 		} | ||||
| 		return INVALID_INDEX; | ||||
| 	} | ||||
| @ -696,7 +696,7 @@ public: | ||||
|  | ||||
| protected: | ||||
| 	Mpool       mp; | ||||
| 	COMPARATOR  comparator; | ||||
| 	EQUALER     equaler; | ||||
| 	Node*       head_node; | ||||
| 	Node*       tail_node; | ||||
| 	qse_size_t  node_count; | ||||
|  | ||||
| @ -52,6 +52,7 @@ pkginclude_HEADERS = \ | ||||
| if ENABLE_CXX | ||||
| pkginclude_HEADERS += \ | ||||
| 	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 | ||||
| endif | ||||
|  | ||||
|  | ||||
| @ -52,7 +52,8 @@ build_triplet = @build@ | ||||
| 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@	Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ | ||||
| @ENABLE_CXX_TRUE@	RedBlackTree.hpp | ||||
|  | ||||
| subdir = include/qse/cmn | ||||
| DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ | ||||
| @ -92,7 +93,7 @@ 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 | ||||
| 	HashTable.hpp RedBlackTree.hpp | ||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||
| am__vpath_adj = case $$p in \ | ||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||
|  | ||||
							
								
								
									
										166
									
								
								qse/include/qse/cmn/RedBlackTree.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								qse/include/qse/cmn/RedBlackTree.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,166 @@ | ||||
| /* | ||||
|  * $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_REDBLACKTREE_HPP_ | ||||
| #define _QSE_CMN_REDBLACKTREE_HPP_ | ||||
|  | ||||
| #include <qse/Types.hpp> | ||||
| #include <qse/cmn/Mpool.hpp> | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| template <typename T>  | ||||
| class RedBlackTreeNode | ||||
| { | ||||
| public: | ||||
| 	friend class RedBlackTree<T>; | ||||
| 	typedef RedBlackTreeNode<T> SelfType; | ||||
|  | ||||
| 	enum | ||||
| 	{ | ||||
| 		RED, | ||||
| 		BLACK | ||||
| 	}; | ||||
|  | ||||
| 	T value; // you can use this variable or accessor functions below | ||||
|  | ||||
| protected: | ||||
| 	SelfType* parent; | ||||
| 	SelfType* child[2]; // left and right | ||||
|  | ||||
| public: | ||||
| 	T& getValue () { return this->value; } | ||||
| 	const T& getValue () const { return this->value; } | ||||
| 	void setValue (const T& v) { this->value = v; } | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct RedBlackTreeComparator | ||||
| { | ||||
| 	int operator() (const T& v1, const T& v2) const | ||||
| 	{ | ||||
| 		return (v1 > v2)? 1:  | ||||
| 		       (v1 < v2)? -1: 0; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template <typename T, typename COMPARATOR = RedBlackTreeComparator<T> > | ||||
| class RedBlackTree: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef RedBlackTree<T,COMPARATOR> SelfType; | ||||
|  | ||||
| 	typedef RedBlackTreeHasher<T> DefaultHasher; | ||||
| 	typedef RedBlackTreeComparator<T> DefaultComparator; | ||||
|  | ||||
| 	RedBlackTree | ||||
| 		Mmgr* mmgr = QSE_NULL, | ||||
| 		qse_size_t mpb_size = 0): Mmged(mmgr) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTree (const RedBlackTree& rbt) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	~RedBlackTree () | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	RedBlackTree& operator= (const RedBlackTree& rbt) | ||||
| 	{ | ||||
| 		/* TODO */ | ||||
| 		return *this; | ||||
| 	} | ||||
|  | ||||
| 	Mpool& getMpool () | ||||
| 	{ | ||||
| 		return this->mp; | ||||
| 	} | ||||
|  | ||||
| 	const Mpool& getMpool () const | ||||
| 	{ | ||||
| 		return this->mp; | ||||
| 	} | ||||
|  | ||||
| 	qse_size_t getSize () const  | ||||
| 	{ | ||||
| 		return this->node_count; | ||||
| 	} | ||||
|  | ||||
| 	bool isEmpty () const  | ||||
| 	{ | ||||
| 		return this->node_count <= 0; | ||||
| 	} | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	Node* inject (const T& datum, int mode, bool* injected = QSE_NULL) | ||||
| 	{ | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	Node* insert (const T& datum) | ||||
| 	{ | ||||
| 		return this->inject (datum, -1, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| 	Node* ensert (const T& datum) | ||||
| 	{ | ||||
| 		return this->inject (datum, 0, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| 	Node* upsert (const T& datum) | ||||
| 	{ | ||||
| 		return this->inject (datum, 1, QSE_NULL); | ||||
| 	} | ||||
|  | ||||
| #if 0 | ||||
| 	Node* update (const T& datum) | ||||
| 	{ | ||||
| 		Node* node = this->find_node (datum); | ||||
| 		if (node) node->value = datum; | ||||
| 		return node; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| protected: | ||||
| 	Mpool      mp; | ||||
| 	COMPARATOR comparator; | ||||
|  | ||||
| 	Node       xnil; // internal node to present nil  | ||||
| 	Node*      root; // root node. | ||||
| 	qse_size_t node_count; | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_END_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user