added RedBlackTable
This commit is contained in:
parent
8c4921a9b4
commit
0ece41a9e0
@ -84,6 +84,7 @@ class LinkedListIterator
|
||||
{
|
||||
public:
|
||||
friend class LinkedList<T,EQUALER>;
|
||||
//typedef LinkedListNode<T,EQUALER> Node;
|
||||
typedef NODE Node;
|
||||
typedef LinkedListIterator<T,EQUALER,NODE,GET_T> SelfType;
|
||||
|
||||
@ -162,11 +163,10 @@ public:
|
||||
return this->current->getValue();
|
||||
}
|
||||
|
||||
SelfType& setValue (const T& v)
|
||||
void setValue (const T& v)
|
||||
{
|
||||
QSE_ASSERT (this->current != QSE_NULL);
|
||||
this->current->setValue (v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Node* getNode ()
|
||||
|
@ -53,6 +53,6 @@ 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
|
||||
RedBlackTree.hpp RedBlackTable.hpp
|
||||
endif
|
||||
|
||||
|
@ -53,7 +53,7 @@ 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
|
||||
@ENABLE_CXX_TRUE@ RedBlackTree.hpp RedBlackTable.hpp
|
||||
|
||||
subdir = include/qse/cmn
|
||||
DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \
|
||||
@ -93,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 RedBlackTree.hpp
|
||||
HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
|
268
qse/include/qse/cmn/RedBlackTable.hpp
Normal file
268
qse/include/qse/cmn/RedBlackTable.hpp
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* $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_REDBLACKTABLE_HPP_
|
||||
#define _QSE_CMN_REDBLACKTABLE_HPP_
|
||||
|
||||
#include <qse/cmn/Association.hpp>
|
||||
#include <qse/cmn/RedBlackTree.hpp>
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
struct RedBlackTableComparator
|
||||
{
|
||||
// it must return true if two values are equal
|
||||
int operator() (const T& v1, const T& v2) const
|
||||
{
|
||||
if (v1 > v2) return 1;
|
||||
if (v1 < v2) return -1;
|
||||
QSE_ASSERT (v1 == v2);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename COMPARATOR = RedBlackTableComparator<K> >
|
||||
class RedBlackTable: public Mmged
|
||||
{
|
||||
public:
|
||||
typedef Association<K,V> Pair;
|
||||
typedef RedBlackTable<K,V,COMPARATOR> SelfType;
|
||||
|
||||
typedef RedBlackTableComparator<K> DefaultComparator;
|
||||
|
||||
struct PairComparator
|
||||
{
|
||||
qse_size_t operator() (const Pair& p1, const Pair& p2) const
|
||||
{
|
||||
COMPARATOR comparator;
|
||||
return comparator (p1.key, p2.key);
|
||||
}
|
||||
};
|
||||
|
||||
struct PairHeteroComparator
|
||||
{
|
||||
qse_size_t operator() (const K& p1, const Pair& p2) const
|
||||
{
|
||||
COMPARATOR comparator;
|
||||
return comparator (p1, p2.key);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MK, typename MCOMPARATOR>
|
||||
struct MHeteroComparator
|
||||
{
|
||||
qse_size_t operator() (const MK& p1, const Pair& p2) const
|
||||
{
|
||||
MCOMPARATOR mcomparator;
|
||||
return mcomparator (p1, p2.key);
|
||||
}
|
||||
};
|
||||
|
||||
typedef RedBlackTree<Pair,PairComparator> PairTree;
|
||||
typedef typename PairTree::Node PairNode;
|
||||
typedef typename PairTree::Iterator Iterator;
|
||||
typedef typename PairTree::ConstIterator ConstIterator;
|
||||
|
||||
|
||||
RedBlackTable (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0):
|
||||
Mmged(mmgr), pair_tree (mmgr, mpb_size)
|
||||
{
|
||||
}
|
||||
|
||||
RedBlackTable (const SelfType& table): Mmged (table), pair_tree (table.pair_tree)
|
||||
{
|
||||
}
|
||||
|
||||
SelfType& operator= (const SelfType& table)
|
||||
{
|
||||
this->pair_tree = table.pair_tree;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Mpool& getMpool ()
|
||||
{
|
||||
return this->pair_tree.getMpool ();
|
||||
}
|
||||
|
||||
const Mpool& getMpool () const
|
||||
{
|
||||
return this->pair_tree.getMpool ();
|
||||
}
|
||||
|
||||
qse_size_t getCapacity() const
|
||||
{
|
||||
return this->pair_tree.getCapacity ();
|
||||
}
|
||||
|
||||
qse_size_t getSize() const
|
||||
{
|
||||
return this->pair_tree.getSize ();
|
||||
}
|
||||
|
||||
bool isEmpty () const
|
||||
{
|
||||
return this->pair_tree.isEmpty ();
|
||||
}
|
||||
|
||||
PairNode* getHeadNode ()
|
||||
{
|
||||
return this->pair_tree.getHeadNode ();
|
||||
}
|
||||
|
||||
const PairNode* getHeadNode () const
|
||||
{
|
||||
return this->pair_tree.getHeadNode ();
|
||||
}
|
||||
|
||||
PairNode* getTailNode ()
|
||||
{
|
||||
return this->pair_tree.getTailNode ();
|
||||
}
|
||||
|
||||
const PairNode* getTailNode () const
|
||||
{
|
||||
return this->pair_tree.getTailNode ();
|
||||
}
|
||||
|
||||
Pair* inject (const K& key, const V& value, int mode, bool* injected = QSE_NULL)
|
||||
{
|
||||
PairNode* node = this->pair_tree.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_tree.insert (Pair(key, value));
|
||||
if (!node) return QSE_NULL;
|
||||
return &node->value;
|
||||
}
|
||||
|
||||
Pair* ensert (const K& key, const V& value)
|
||||
{
|
||||
PairNode* node = this->pair_tree.ensert (Pair(key, value));
|
||||
if (!node) return QSE_NULL;
|
||||
return &node->value;
|
||||
}
|
||||
|
||||
Pair* upsert (const K& key, const V& value)
|
||||
{
|
||||
//PairNode* node = this->pair_tree.upsert (Pair(key, value));
|
||||
//if (!node) return QSE_NULL;
|
||||
//return &node->value;
|
||||
|
||||
// Don't call pair_tree.upsert() to make sure that the 'key' object
|
||||
// itself remains identical after potential update operation.
|
||||
// pair_tree.upsert() changes the Pair object as a whole. so this
|
||||
// trick is required.
|
||||
bool injected;
|
||||
PairNode* node = this->pair_tree.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_tree.update (Pair(key, value));
|
||||
//if (!node) return QSE_NULL;
|
||||
//return &node->value;
|
||||
|
||||
PairNode* node = this->pair_tree.template heterofindNode<K,PairHeteroComparator> (key);
|
||||
if (!node) return QSE_NULL;
|
||||
Pair& pair = node->value;
|
||||
pair.value = value;
|
||||
return &pair;
|
||||
}
|
||||
|
||||
Pair* search (const K& key)
|
||||
{
|
||||
//PairNode* node = this->pair_tree.update (Pair(key));
|
||||
PairNode* node = this->pair_tree.template heterofindNode<K,PairHeteroComparator> (key);
|
||||
if (!node) return QSE_NULL;
|
||||
return &node->value;
|
||||
}
|
||||
|
||||
int remove (const K& key)
|
||||
{
|
||||
//return this->pair_tree.remove (Pair(key));
|
||||
return this->pair_tree.template heteroremove<K,PairHeteroComparator> (key);
|
||||
}
|
||||
|
||||
template <typename MK, typename MCOMPARATOR>
|
||||
Pair* heterosearch (const MK& key)
|
||||
{
|
||||
typedef MHeteroComparator<MK,MCOMPARATOR> MComparator;
|
||||
PairNode* node = this->pair_tree.template heterosearch<MK,MComparator> (key);
|
||||
if (!node) return QSE_NULL;
|
||||
return &node->value;
|
||||
}
|
||||
|
||||
template <typename MK, typename MCOMPARATOR>
|
||||
const Pair* heterosearch (const MK& key) const
|
||||
{
|
||||
typedef MHeteroComparator<MK,MCOMPARATOR> MComparator;
|
||||
PairNode* node = this->pair_tree.template heterosearch<MK,MComparator> (key);
|
||||
if (!node) return QSE_NULL;
|
||||
return &node->value;
|
||||
}
|
||||
|
||||
template <typename MK, typename MCOMPARATOR>
|
||||
int heteroremove (const MK& key)
|
||||
{
|
||||
typedef MHeteroComparator<MK,MCOMPARATOR> MComparator;
|
||||
return this->pair_tree.template heteroremove<MK,MComparator> (key);
|
||||
}
|
||||
|
||||
void clear (bool clear_mpool = false)
|
||||
{
|
||||
return this->pair_tree.clear (clear_mpool);
|
||||
}
|
||||
|
||||
Iterator getIterator (qse_size_t index = 0)
|
||||
{
|
||||
return this->pair_tree.getIterator (index);
|
||||
}
|
||||
|
||||
ConstIterator getConstIterator (qse_size_t index = 0) const
|
||||
{
|
||||
return this->pair_tree.getConstIterator (index);
|
||||
}
|
||||
|
||||
protected:
|
||||
PairTree pair_tree;
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
#endif
|
@ -113,8 +113,10 @@ struct RedBlackTreeComparator
|
||||
{
|
||||
int operator() (const T& v1, const T& v2) const
|
||||
{
|
||||
return (v1 > v2)? 1:
|
||||
(v1 < v2)? -1: 0;
|
||||
if (v1 > v2) return 1;
|
||||
if (v1 < v2) return -1;
|
||||
QSE_ASSERT (v1 == v2);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -250,6 +252,20 @@ public:
|
||||
|
||||
// no operator--
|
||||
|
||||
bool operator== (const SelfType& it) const
|
||||
{
|
||||
QSE_ASSERT (this->current != QSE_NULL);
|
||||
return this->current == it.current &&
|
||||
this->previous == it.previous;
|
||||
}
|
||||
|
||||
bool operator!= (const SelfType& it) const
|
||||
{
|
||||
QSE_ASSERT (this->current != QSE_NULL);
|
||||
return this->current != it.current ||
|
||||
this->previous != it.previous;
|
||||
}
|
||||
|
||||
bool isLegit() const
|
||||
{
|
||||
return current->notNil();
|
||||
@ -302,7 +318,10 @@ public:
|
||||
|
||||
typedef RedBlackTreeComparator<T> DefaultComparator;
|
||||
|
||||
RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr), mp (mmgr, QSE_SIZEOF(Node), mpb_size), node_count (0)
|
||||
RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0):
|
||||
Mmged(mmgr),
|
||||
mp (mmgr, QSE_SIZEOF(Node), mpb_size),
|
||||
node_count (0)
|
||||
{
|
||||
// create a nil object
|
||||
this->nil = new(&this->mp) Node();
|
||||
@ -311,9 +330,25 @@ public:
|
||||
this->root = this->nil;
|
||||
}
|
||||
|
||||
RedBlackTree (const RedBlackTree& rbt)
|
||||
RedBlackTree (const RedBlackTree& rbt):
|
||||
Mmged(rbt.getMmgr()),
|
||||
mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()),
|
||||
node_count (0)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
// create a nil object
|
||||
this->nil = new(&this->mp) Node();
|
||||
|
||||
// set root to nil
|
||||
this->root = this->nil;
|
||||
|
||||
// TODO: do the level-order traversal to minize rebalancing.
|
||||
Iterator it = rbt.getIterator();
|
||||
while (it.isLegit())
|
||||
{
|
||||
this->insert (*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
~RedBlackTree ()
|
||||
@ -326,7 +361,13 @@ public:
|
||||
{
|
||||
this->clear ();
|
||||
|
||||
/* TODO */
|
||||
// TODO: do the level-order traversal to minize rebalancing.
|
||||
Iterator it = rbt.getIterator();
|
||||
while (it.isLegit())
|
||||
{
|
||||
this->insert (*it);
|
||||
++it;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -792,6 +833,7 @@ public:
|
||||
void clear (bool clear_mpool = false)
|
||||
{
|
||||
while (this->root->notNil()) this->remove_node (this->root);
|
||||
QSE_ASSERT (this->root = this->nil);
|
||||
}
|
||||
|
||||
Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
|
||||
|
Loading…
x
Reference in New Issue
Block a user