added POSITIONER to Array and BinaryHeap
This commit is contained in:
parent
09bd5bb54a
commit
8eadd34b9d
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user