added POSITIONER to Array and BinaryHeap

This commit is contained in:
hyung-hwan 2015-03-09 07:05:46 +00:00
parent 09bd5bb54a
commit 8eadd34b9d
2 changed files with 88 additions and 33 deletions

View File

@ -34,6 +34,15 @@
QSE_BEGIN_NAMESPACE(QSE)
/////////////////////////////////
template <typename T>
struct ArrayPositioner
{
void operator() (T& v, qse_size_t index) const
{
// do nothing
}
};
struct ArrayResizer
{
qse_size_t operator() (qse_size_t current) const
@ -51,12 +60,13 @@ struct ArrayResizer
///
/// The Array class provides a dynamically resized array.
///
template <typename T, typename RESIZER = ArrayResizer >
template <typename T, typename POSITIONER = ArrayPositioner<T>, typename RESIZER = ArrayResizer >
class Array: public Mmged
{
public:
typedef Array<T,RESIZER> SelfType;
typedef Array<T,POSITIONER,RESIZER> SelfType;
typedef ArrayPositioner<T> DefaultPositioner;
typedef ArrayResizer DefaultResizer;
enum
@ -128,6 +138,7 @@ protected:
{
// copy-construct each element.
new((QSE::Mmgr*)QSE_NULL, &tmp[index]) T(srcbuf[index]);
this->positioner (tmp[index], index);
}
}
catch (...)
@ -137,6 +148,7 @@ protected:
while (index > 0)
{
--index;
this->positioner (tmp[index], INVALID_INDEX);
tmp[index].~T ();
}
::operator delete (tmp, this->getMmgr());
@ -153,11 +165,13 @@ protected:
// no value exists in the given position.
// i can copy-construct the value.
new((QSE::Mmgr*)QSE_NULL, &this->buffer[index]) T(value);
this->positioner (this->buffer[index], index);
}
else
{
// there is an old value in the position.
this->buffer[index] = value;
this->positioner (this->buffer[index], index);
}
}
@ -168,6 +182,7 @@ protected:
for (qse_size_t i = this->count; i > 0; )
{
--i;
this->positioner (this->buffer[i], INVALID_INDEX);
this->buffer[i].~T ();
}
@ -232,11 +247,14 @@ public:
return INVALID_INDEX;
}
T& operator[] (qse_size_t index)
{
QSE_ASSERT (index < this->count);
return this->buffer[index];
}
// i don't want expose a non-const accessor as i don't like
// a proper update procesure to be skipped.
// use setValueAt() or update() to modify the existing element.
//T& operator[] (qse_size_t index)
//{
// QSE_ASSERT (index < this->count);
// return this->buffer[index];
//}
const T& operator[] (qse_size_t index) const
{
@ -244,11 +262,14 @@ public:
return this->buffer[index];
}
T& getValueAt (qse_size_t index)
{
QSE_ASSERT (index < this->count);
return this->buffer[index];
}
// i don't want expose a non-const accessor as i don't like
// a proper update procesure to be skipped.
// use setValueAt() or update() to modify the existing element.
//T& getValueAt (qse_size_t index)
//{
// QSE_ASSERT (index < this->count);
// return this->buffer[index];
//}
const T& getValueAt (qse_size_t index) const
{
@ -258,7 +279,7 @@ public:
void setValueAt (qse_size_t index, const T& value)
{
this->insert (index, value);
this->update (index, value);
}
qse_size_t insert (qse_size_t index, const T& value)
@ -298,6 +319,7 @@ public:
for (qse_size_t i = this->count; i < index; i++)
{
new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T();
this->positioner (this->buffer[i], i);
}
}
@ -308,7 +330,15 @@ public:
return index;
}
qse_size_t update (qse_size_t index, const T& value)
{
QSE_ASSERT (index < this->count);
this->buffer[index] = value;
this->positioner (this->buffer[index], index);
return index;
}
void remove (qse_size_t index)
{
this->remove (index, index);
@ -325,13 +355,27 @@ public:
// replace deleted elements by surviving elements at the back
while (i < this->count)
{
// which is better?
// 1. destruct followed by copy construct
// 2. operator assignment.
// 1. destruct followed by copy construct
//this->positioner (this->buffer[j], INVALID_INDEX);
//this->buffer[j].~T();
//new((QSE::Mmgr*)QSE_NULL, &this->buffer[j]) T(this->buffer[i]);
//this->positioner (this->buffer[j], j);
// 2. operator assignment
this->buffer[j] = this->buffer[i];
this->positioner (this->buffer[j], j);
j++; i++;
}
// call the destructor of deleted elements.
while (j < this->count)
{
this->positioner (this->buffer[j], INVALID_INDEX);
this->buffer[j].~T ();
j++;
}
@ -381,6 +425,7 @@ public:
for (qse_size_t i = size; i < this->count; ++i)
{
// call the destructor of the items
this->positioner (this->buffer[i], INVALID_INDEX);
this->buffer[i].~T ();
}
@ -393,6 +438,7 @@ public:
{
// use the default contructor to set the value.
new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T();
this->positioner (this->buffer[i], i);
}
this->count = size;
@ -497,18 +543,24 @@ public:
while (index < nk)
{
this->buffer[index] = this->buffer[index + n];
this->positioner (this->buffer[index], index);
index += n;
}
if (index == last) break;
this->buffer[index] = this->buffer[index - nk];
this->positioner (this->buffer[index], index);
index -= nk;
}
this->buffer[last] = c;
this->positioner (this->buffer[last], last);
first++;
}
}
protected:
POSITIONER positioner;
RESIZER resizer;
qse_size_t count;

View File

@ -85,20 +85,30 @@ struct BinaryHeapComparator
}
};
template <typename T>
struct BinaryHeapPositioner
{
void operator() (T& v, qse_size_t index) const
{
// do nothing
}
};
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 RESIZER = BinaryHeapResizer >
class BinaryHeap: protected Array<T,RESIZER>
template <typename T, typename COMPARATOR = BinaryHeapComparator<T>, typename POSITIONER = BinaryHeapPositioner<T>, typename RESIZER = BinaryHeapResizer >
class BinaryHeap: protected Array<T,POSITIONER,RESIZER>
{
public:
typedef BinaryHeap<T,COMPARATOR,RESIZER> SelfType;
typedef Array<T,RESIZER> ParentType;
typedef BinaryHeap<T,COMPARATOR,POSITIONER,RESIZER> SelfType;
typedef Array<T,POSITIONER,RESIZER> ParentType;
typedef BinaryHeapComparator<T> DefaultComparator;
typedef BinaryHeapPositioner<T> DefaultPositioner;
typedef BinaryHeapResizer DefaultResizer;
enum
@ -149,16 +159,16 @@ public:
// add the item at the back of the array
ParentType::insert (index, value);
// move the item up to the top if it's greater than the up item
return this->sift_up(index);
}
qse_size_t update (qse_size_t index, const T& value)
{
T old = this->data_buffer[index];
T old = this->buffer[index];
this->buffer[index] = value;
ParentType::update (index, value);
return (this->greater_than(value, old))? this->sift_up(index): this->sift_down(index);
}
@ -170,7 +180,7 @@ public:
// copy the last item to the position to remove
T old = this->buffer[index];
this->buffer[index] = this->buffer[this->count - 1];
ParentType::update (index, this->buffer[this->count - 1]);
// delete the last item
ParentType::remove (this->count - 1);
@ -179,13 +189,6 @@ public:
(this->greater_than (this->buffer[index], old))? this->sift_up(index): this->sift_down(index);
}
void clear ()
{
while (this->root->notNil()) this->remove_node (this->root);
QSE_ASSERT (this->root = this->nil);
QSE_ASSERT (this->node_count == 0);
}
protected:
qse_size_t sift_up (qse_size_t index)
{
@ -198,14 +201,14 @@ protected:
do
{
this->buffer[index] = this->buffer[up];
ParentType::setValueAt (index, this->buffer[up]);
index = up;
up = QSE_BINARY_HEAP_UP(up);
}
while (index > 0 && this->greater_than(item, this->buffer[up]));
this->buffer[index] = item;
ParentType::setValueAt (index, item);
}
return index;
@ -244,12 +247,12 @@ protected:
if (this->greater_than(item, this->buffer[greater])) break;
this->buffer[index] = this->buffer[greater];
ParentType::setValueAt (index, this->buffer[greater]);
index = greater;
}
while (index < half_data_count);
this->buffer[index] = item;
ParentType::setValueAt (index, item);
}
return index;