added RedBlackTable
This commit is contained in:
parent
8c4921a9b4
commit
0ece41a9e0
@ -84,6 +84,7 @@ class LinkedListIterator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class LinkedList<T,EQUALER>;
|
friend class LinkedList<T,EQUALER>;
|
||||||
|
//typedef LinkedListNode<T,EQUALER> Node;
|
||||||
typedef NODE Node;
|
typedef NODE Node;
|
||||||
typedef LinkedListIterator<T,EQUALER,NODE,GET_T> SelfType;
|
typedef LinkedListIterator<T,EQUALER,NODE,GET_T> SelfType;
|
||||||
|
|
||||||
@ -162,11 +163,10 @@ public:
|
|||||||
return this->current->getValue();
|
return this->current->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfType& setValue (const T& v)
|
void setValue (const T& v)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (this->current != QSE_NULL);
|
QSE_ASSERT (this->current != QSE_NULL);
|
||||||
this->current->setValue (v);
|
this->current->setValue (v);
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* getNode ()
|
Node* getNode ()
|
||||||
|
@ -53,6 +53,6 @@ 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
|
RedBlackTree.hpp RedBlackTable.hpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ 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
|
@ENABLE_CXX_TRUE@ RedBlackTree.hpp RedBlackTable.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 +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 \
|
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
|
HashTable.hpp RedBlackTree.hpp RedBlackTable.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/||"`;; \
|
||||||
|
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
|
int operator() (const T& v1, const T& v2) const
|
||||||
{
|
{
|
||||||
return (v1 > v2)? 1:
|
if (v1 > v2) return 1;
|
||||||
(v1 < v2)? -1: 0;
|
if (v1 < v2) return -1;
|
||||||
|
QSE_ASSERT (v1 == v2);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,6 +252,20 @@ public:
|
|||||||
|
|
||||||
// no operator--
|
// 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
|
bool isLegit() const
|
||||||
{
|
{
|
||||||
return current->notNil();
|
return current->notNil();
|
||||||
@ -302,7 +318,10 @@ public:
|
|||||||
|
|
||||||
typedef RedBlackTreeComparator<T> DefaultComparator;
|
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
|
// create a nil object
|
||||||
this->nil = new(&this->mp) Node();
|
this->nil = new(&this->mp) Node();
|
||||||
@ -311,9 +330,25 @@ public:
|
|||||||
this->root = this->nil;
|
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 ()
|
~RedBlackTree ()
|
||||||
@ -326,7 +361,13 @@ public:
|
|||||||
{
|
{
|
||||||
this->clear ();
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -792,6 +833,7 @@ public:
|
|||||||
void clear (bool clear_mpool = false)
|
void clear (bool clear_mpool = false)
|
||||||
{
|
{
|
||||||
while (this->root->notNil()) this->remove_node (this->root);
|
while (this->root->notNil()) this->remove_node (this->root);
|
||||||
|
QSE_ASSERT (this->root = this->nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
|
Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user