changed void* operator new (qse_size_t size, QSE::Mpool* mp) to fall back to mmgr upon size mismatch.
finished primitive BinaryHeap code. renamed Array::get() to Array::getValueAt() renamed Array::set() to Array::setValueAt()
This commit is contained in:
parent
fc316009b6
commit
efc997750e
@ -57,6 +57,8 @@ class Array: public Mmged
|
||||
public:
|
||||
typedef Array<T,RESIZER> SelfType;
|
||||
|
||||
typedef ArrayResizer DefaultResizer;
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 128,
|
||||
@ -229,21 +231,20 @@ public:
|
||||
return this->buffer[index];
|
||||
}
|
||||
|
||||
T& get (qse_size_t index)
|
||||
T& getValueAtgetValueAt (qse_size_t index)
|
||||
{
|
||||
QSE_ASSERT (index < this->count);
|
||||
return this->buffer[index];
|
||||
}
|
||||
|
||||
const T& get (qse_size_t index) const
|
||||
const T& getValueAt (qse_size_t index) const
|
||||
{
|
||||
QSE_ASSERT (index < this->count);
|
||||
return this->buffer[index];
|
||||
}
|
||||
|
||||
void set (qse_size_t index, const T& value)
|
||||
void setValueAt (qse_size_t index, const T& value)
|
||||
{
|
||||
QSE_ASSERT (index < this->count);
|
||||
this->insert (index, value);
|
||||
}
|
||||
|
||||
@ -383,6 +384,8 @@ public:
|
||||
|
||||
void setCapacity (qse_size_t capa)
|
||||
{
|
||||
if (capa == this->capacity) return;
|
||||
|
||||
if (capa <= 0)
|
||||
{
|
||||
this->clear (true);
|
||||
@ -395,15 +398,7 @@ public:
|
||||
if (cnt > capa) cnt = capa;
|
||||
|
||||
T* tmp = this->clone_buffer (this->buffer, capa, cnt);
|
||||
|
||||
// don't call this->clear(true) here. clear items only.
|
||||
this->clear_all_items ();
|
||||
|
||||
// deallocate the current buffer;
|
||||
::operator delete (this->buffer, this->getMmgr());
|
||||
this->capacity = 0;
|
||||
this->buffer = QSE_NULL;
|
||||
|
||||
this->clear (true);
|
||||
this->buffer = tmp;
|
||||
this->capacity = capa;
|
||||
this->count = cnt;
|
||||
@ -418,7 +413,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void trimToSize ()
|
||||
// The compact() function
|
||||
void compact ()
|
||||
{
|
||||
this->setCapacity (this->size);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define _QSE_CMN_BINARYHEAP_HPP_
|
||||
|
||||
///
|
||||
/// This file provides an array-based binary heap.
|
||||
/// This file provides a binary heap implementation.
|
||||
/// In the heap, each node is greater than or equal to its BinaryHeap
|
||||
///
|
||||
/// #include <qse/cmn/BinaryHeap.hpp>
|
||||
@ -60,7 +60,7 @@
|
||||
///
|
||||
/// while (heap.getSize() > 0)
|
||||
/// {
|
||||
/// printf ("%d\n", heap.getRootValue());
|
||||
/// printf ("%d\n", heap.getValueAt(0));
|
||||
/// heap.remove (0);
|
||||
/// }
|
||||
///
|
||||
@ -68,14 +68,13 @@
|
||||
/// }
|
||||
///
|
||||
|
||||
#include <qse/Types.hpp>
|
||||
#include <qse/cmn/Mpool.hpp>
|
||||
|
||||
#include <qse/cmn/Array.hpp>
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
// greater-than comparator
|
||||
template <typename T>
|
||||
struct BinaryHeapComparator
|
||||
{
|
||||
@ -86,170 +85,92 @@ struct BinaryHeapComparator
|
||||
}
|
||||
};
|
||||
|
||||
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, qse_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));
|
||||
}
|
||||
};
|
||||
|
||||
typedef ArrayResizer BinaryHeapResizer;
|
||||
|
||||
#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
|
||||
template <typename T, typename COMPARATOR = BinaryHeapComparator<T>, typename RESIZER = BinaryHeapResizer >
|
||||
class BinaryHeap: protected Array<T,RESIZER>
|
||||
{
|
||||
public:
|
||||
typedef BinaryHeap<T,COMPARATOR,ASSIGNER,RESIZER> SelfType;
|
||||
typedef BinaryHeap<T,COMPARATOR,RESIZER> SelfType;
|
||||
typedef Array<T,RESIZER> ParentType;
|
||||
|
||||
typedef BinaryHeapComparator<T> DefaultComparator;
|
||||
typedef BinaryHeapResizer DefaultResizer;
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 10,
|
||||
MIN_CAPACITY = 1
|
||||
DEFAULT_CAPACITY = ParentType::DEFAULT_CAPACITY,
|
||||
INVALID_INDEX = ParentType::INVALID_INDEX
|
||||
};
|
||||
|
||||
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)
|
||||
BinaryHeap (Mmgr* mmgr = QSE_NULL, qse_size_t capacity = DEFAULT_CAPACITY):
|
||||
ParentType (mmgr, capacity)
|
||||
{
|
||||
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)
|
||||
BinaryHeap (const SelfType& heap): ParentType (heap)
|
||||
{
|
||||
// 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
|
||||
ParentType::operator= (heap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~BinaryHeap
|
||||
Mpool& getMpool ()
|
||||
using ParentType::isEmpty;
|
||||
using ParentType::getSize;
|
||||
using ParentType::getCapacity;
|
||||
using ParentType::clear;
|
||||
using ParentType::compact;
|
||||
|
||||
const T& getValueAt (qse_size_t index) const
|
||||
{
|
||||
return this->mp;
|
||||
return ParentType::getValueAt (index);
|
||||
}
|
||||
|
||||
const Mpool& getMpool () const
|
||||
qse_size_t insert (const T& value)
|
||||
{
|
||||
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;
|
||||
qse_size_t index = this->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
|
||||
ParentType::insert (index, value);
|
||||
|
||||
// move the item up to the top if it's greater than the up item
|
||||
return this->sift_up(index);
|
||||
}
|
||||
|
||||
#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);
|
||||
this->buffer[index] = value;
|
||||
|
||||
return (this->greater_than (value, old))? sift_up (index): sift_down (index);
|
||||
return (this->greater_than(value, old))? this->sift_up(index): this->sift_down(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
void remove_node (qse_size_t index)
|
||||
void remove (qse_size_t index)
|
||||
{
|
||||
QSE_ASSERT (index < this->data_count);
|
||||
QSE_ASSERT (index < this->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];
|
||||
T old = this->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);
|
||||
this->buffer[index] = this->buffer[this->count - 1];
|
||||
|
||||
// delete the last item
|
||||
Tree<T>::remove (this->data_count - 1);
|
||||
ParentType::remove (this->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 */
|
||||
(this->greater_than (this->buffer[index], old))? this->sift_up(index): this->sift_down(index);
|
||||
}
|
||||
|
||||
void clear ()
|
||||
@ -260,60 +181,51 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
Node* sift_up (qse_size_t index)
|
||||
qse_size_t 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]))
|
||||
up = QSE_BINARY_HEAP_UP(index);
|
||||
if (index > 0 && this->greater_than(this->buffer[index], this->buffer[up]))
|
||||
{
|
||||
// note that this->assign() isn't called for temporary assignment.
|
||||
T item = this->data_buffer[index];
|
||||
T item = this->buffer[index];
|
||||
|
||||
do
|
||||
{
|
||||
//this->data_buffer[index] = this->data_buffer[up];
|
||||
this->assign (this->data_buffer[index], this->data_buffer[up], index);
|
||||
this->buffer[index] = this->buffer[up];
|
||||
|
||||
index = up;
|
||||
up = QSE_ARRAY_HEAP_PARENT (up);
|
||||
index = up;
|
||||
up = QSE_BINARY_HEAP_UP(up);
|
||||
}
|
||||
while (index > 0 && this->greater_than (item, this->data_buffer[up]));
|
||||
while (index > 0 && this->greater_than(item, this->buffer[up]));
|
||||
|
||||
//this->data_buffer[index] = item;
|
||||
this->assign (this->data_buffer[index], item, index);
|
||||
this->buffer[index] = item;
|
||||
}
|
||||
|
||||
return index;
|
||||
#endif
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
Node* sift_down (qse_size_t index)
|
||||
qse_size_t sift_down (qse_size_t index)
|
||||
{
|
||||
#if 0
|
||||
qse_size_t half_data_count = this->data_count / 2;
|
||||
qse_size_t half_data_count = this->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];
|
||||
T item = this->buffer[index];
|
||||
|
||||
do
|
||||
{
|
||||
qse_size_t left, right, greater;
|
||||
|
||||
left = QSE_ARRAY_HEAP_LEFT (index);
|
||||
right = QSE_ARRAY_HEAP_RIGHT (index);
|
||||
left = QSE_BINARY_HEAP_LEFT(index);
|
||||
right = QSE_BINARY_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 (right < this->count &&
|
||||
this->greater_than(this->buffer[right], this->buffer[left]))
|
||||
{
|
||||
// if the right child exists and
|
||||
// the right item is greater than the left item
|
||||
@ -323,33 +235,22 @@ protected:
|
||||
{
|
||||
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);
|
||||
|
||||
if (this->greater_than(item, this->buffer[greater])) break;
|
||||
|
||||
this->buffer[index] = this->buffer[greater];
|
||||
index = greater;
|
||||
}
|
||||
while (index < half_data_count);
|
||||
|
||||
//this->data_buffer[index] = item;
|
||||
this->assign (this->data_buffer[index], item, index);
|
||||
this->buffer[index] = item;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
typedef qse_mmgr_t mmgr_t;
|
||||
|
||||
QSE_EXCEPTION (MemoryError);
|
||||
QSE_EXCEPTION (InvalidArgumentError);
|
||||
|
||||
protected:
|
||||
bool raise_exception;
|
||||
|
@ -170,7 +170,7 @@ protected:
|
||||
{
|
||||
if (this->previous == this->current->getUpNode())
|
||||
{
|
||||
/* the previous node is the up of the current node.
|
||||
/* the previous node is the parent of the current node.
|
||||
* it indicates that we're going down to the getChild(l) */
|
||||
if ((this->current->*this->get_left)()->notNil())
|
||||
{
|
||||
@ -194,7 +194,7 @@ 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 up */
|
||||
/* just move up to the parent */
|
||||
this->previous = this->current;
|
||||
this->current = this->current->getUpNode();
|
||||
}
|
||||
@ -213,7 +213,7 @@ protected:
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, move up to the up */
|
||||
/* otherwise, move up to the parent */
|
||||
this->previous = this->current;
|
||||
this->current = this->current->getUpNode();
|
||||
}
|
||||
@ -228,7 +228,7 @@ protected:
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, move up to the up */
|
||||
/* otherwise, move up to the parent */
|
||||
this->previous = this->current;
|
||||
this->current = this->current->getUpNode();
|
||||
}
|
||||
@ -478,7 +478,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.
|
||||
* up up
|
||||
* parent parent
|
||||
* | | (left or right?) | |
|
||||
* pivot y
|
||||
* / \ / \
|
||||
@ -492,7 +492,7 @@ protected:
|
||||
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
||||
* of the new pivot position.
|
||||
*
|
||||
* up up
|
||||
* parent parent
|
||||
* | | (left or right?) | |
|
||||
* pivot x
|
||||
* / \ / \
|
||||
@ -502,8 +502,8 @@ protected:
|
||||
*
|
||||
*
|
||||
* the actual implementation here resolves the pivot's relationship to
|
||||
* 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,
|
||||
* 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,
|
||||
*/
|
||||
|
||||
Node* up, * z, * c;
|
||||
|
@ -184,19 +184,24 @@ void* operator new (qse_size_t size, QSE::Mpool* mp)
|
||||
{
|
||||
if (mp->isEnabled())
|
||||
{
|
||||
QSE_ASSERT (size == mp->getDatumSize());
|
||||
QSE_ASSERTX (size == mp->getDatumSize(),
|
||||
"Pass the right allocation size for the given memory pool");
|
||||
// the size argument is not really used. you must make sure that
|
||||
// the given size matches the datum size of the memory pool.
|
||||
if (size != mp->getDatumSize())
|
||||
{
|
||||
//QSE::Mmgr* mmgr = mp->getMmgr();
|
||||
QSE_THROW (QSE::Mmgr::InvalidArgumentError);
|
||||
// when the assertion above is excluded during the build,
|
||||
// bypass the memory pool if a wrong size is passed in.
|
||||
// debug your application properly so that this block
|
||||
// is never reached.
|
||||
goto use_mmgr;
|
||||
}
|
||||
return mp->allocate ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// but when the memory pool is not enabled, it goes through
|
||||
use_mmgr:
|
||||
// when the memory pool is not enabled, it goes through
|
||||
// the memory manager directly and it honors the size argument.
|
||||
return ::operator new(size, mp->getMmgr());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user