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