Added a couple of 'operator new()' definitions.
Started adding Array and BinaryHeap
This commit is contained in:
parent
e26a49bcb8
commit
0c0f0df7d8
460
qse/include/qse/cmn/Array.hpp
Normal file
460
qse/include/qse/cmn/Array.hpp
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
/*
|
||||||
|
* $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_ARRAY_HPP_
|
||||||
|
#define _QSE_CMN_ARRAY_HPP_
|
||||||
|
|
||||||
|
#include <qse/Types.hpp>
|
||||||
|
#include <qse/cmn/Mpool.hpp>
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
struct ArrayResizer
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename RESIZER = ArrayResizer>
|
||||||
|
class Array: public Mmged
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Array<T,RESIZER> SelfType;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_CAPACITY = 128,
|
||||||
|
INVALID_INDEX = ~(qse_size_t)0
|
||||||
|
};
|
||||||
|
|
||||||
|
Array (Mmgr* mmgr = QSE_NULL,
|
||||||
|
qse_size_t capacity = DEFAULT_CAPACITY,
|
||||||
|
qse_size_t mpb_size = 0):
|
||||||
|
Mmged (mmgr),
|
||||||
|
mp (mmgr, QSE_SIZEOF(T), mpb_size)
|
||||||
|
{
|
||||||
|
if (capacity <= 0)
|
||||||
|
{
|
||||||
|
this->buffer = QSE_NULL;
|
||||||
|
this->capacity = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this->buffer = new T[capacity];
|
||||||
|
this->buffer = (T*)::operator new (capacity * QSE_SIZEOF(*this->buffer), &this->mp);
|
||||||
|
this->capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Array (const SelfType& array)
|
||||||
|
{
|
||||||
|
if (array.buffer == QSE_NULL)
|
||||||
|
{
|
||||||
|
this->buffer = QSE_NULL;
|
||||||
|
this->capacity = 0;
|
||||||
|
this->grow_factor = array.grow_factor;
|
||||||
|
this->count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T* tmp = QSE_NULL;
|
||||||
|
QSE_ASSERT (array.capacity > 0 && array.grow_factor > 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
tmp = new T[array.capacity];
|
||||||
|
for (qse_size_t i = 0; i < array.this->count; i++) {
|
||||||
|
tmp[i] = array.buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
// just in case where the assignment throws an
|
||||||
|
// exception. when T is a class type, the operator =
|
||||||
|
// for the class may throw an exception.
|
||||||
|
if (tmp != QSE_NULL) delete[] tmp;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->buffer = tmp;
|
||||||
|
this->capacity = array.capacity;
|
||||||
|
this->grow_factor = array.grow_factor;
|
||||||
|
this->count = array.this->count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
~Array ()
|
||||||
|
{
|
||||||
|
if (this->buffer)
|
||||||
|
{
|
||||||
|
for (qse_size_t i = this->count; i > 0; )
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
this->buffer[i].~T ();
|
||||||
|
}
|
||||||
|
|
||||||
|
::operator delete (this->buffer, &this->mp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
SelfType& operator= (const SelfType& array)
|
||||||
|
{
|
||||||
|
setSize (array.this->count);
|
||||||
|
for (qse_size_t i = 0; i < array.this->count; i++) {
|
||||||
|
this->buffer[i] = array.buffer[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Array<T>& operator+= (const T& value)
|
||||||
|
{
|
||||||
|
addDatum (value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Array<T>& operator+ (const T& value) const
|
||||||
|
{
|
||||||
|
Array<T> array (*this);
|
||||||
|
array.addDatum (value);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool isEmpty () const
|
||||||
|
{
|
||||||
|
return this->count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t getSize () const
|
||||||
|
{
|
||||||
|
return this->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t getCapacity () const
|
||||||
|
{
|
||||||
|
return this->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T* ()
|
||||||
|
{
|
||||||
|
return this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const T* () const
|
||||||
|
{
|
||||||
|
return this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* getBuffer ()
|
||||||
|
{
|
||||||
|
return this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* getBuffer () const
|
||||||
|
{
|
||||||
|
return this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[] (qse_size_t index)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->count);
|
||||||
|
return this->buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[] (qse_size_t index) const
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->count);
|
||||||
|
return this->buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& get (qse_size_t index)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->count);
|
||||||
|
return this->buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& get (qse_size_t index) const
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->count);
|
||||||
|
return this->buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void set (qse_size_t index, const T& value)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->count);
|
||||||
|
this->buffer[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void set_item (qse_size_t index, const T& value)
|
||||||
|
{
|
||||||
|
if (index >= this->count)
|
||||||
|
new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value);
|
||||||
|
else
|
||||||
|
this->buffer[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
qse_size_t insert (qse_size_t index, const T& value)
|
||||||
|
{
|
||||||
|
if (index >= this->capacity)
|
||||||
|
{
|
||||||
|
qse_size_t new_capa = this->resizer (this->capacity);
|
||||||
|
|
||||||
|
if (index < new_capa)
|
||||||
|
this->setCapacity (new_capa);
|
||||||
|
else
|
||||||
|
this->setCapacity (index + 1);
|
||||||
|
}
|
||||||
|
else if (this->count >= this->capacity)
|
||||||
|
{
|
||||||
|
qse_size_t new_capa = this->resizer (this->capacity);
|
||||||
|
this->setCapacity (new_capa);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qse_size_t i = this->count; i > index; i--)
|
||||||
|
{
|
||||||
|
//this->buffer[i] = this->buffer[i - 1];
|
||||||
|
this->set_item (i, this->buffer[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//this->buffer[index] = value;
|
||||||
|
this->set_item (index, value);
|
||||||
|
if (index > this->count) this->count = index + 1;
|
||||||
|
else this->count++;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove (qse_size_t index)
|
||||||
|
{
|
||||||
|
this->remove (index, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove (qse_size_t from_index, qse_size_t to_index)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (from_index < this->count);
|
||||||
|
QSE_ASSERT (to_index < this->count);
|
||||||
|
|
||||||
|
qse_size_t j = from_index;
|
||||||
|
qse_size_t i = to_index + 1;
|
||||||
|
while (i < this->count)
|
||||||
|
{
|
||||||
|
this->buffer[j++] = this->buffer[i++];
|
||||||
|
}
|
||||||
|
this->count -= to_index - from_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qse_size_t addDatum (const T& value)
|
||||||
|
{
|
||||||
|
return insert (this->count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t removeDatum (const T& value)
|
||||||
|
{
|
||||||
|
qse_size_t i = 0, sz = this->size();
|
||||||
|
while (i < this->count)
|
||||||
|
{
|
||||||
|
if (value == this->buffer[i])
|
||||||
|
{
|
||||||
|
remove (i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sz - this->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t removeDatums (const T& value)
|
||||||
|
{
|
||||||
|
qse_size_t i = 0, sz = this->size();
|
||||||
|
|
||||||
|
while (i < this->count)
|
||||||
|
{
|
||||||
|
if (value == this->buffer[i]) remove (i);
|
||||||
|
else i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sz - this->size();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void clear ()
|
||||||
|
{
|
||||||
|
setSize (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trimToSize ()
|
||||||
|
{
|
||||||
|
setCapacity (this->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize (qse_size_t size)
|
||||||
|
{
|
||||||
|
if (size > this->capacity) this->setCapacity (size);
|
||||||
|
QSE_ASSERT (size <= this->capacity);
|
||||||
|
this->count = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCapacity (qse_size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= 0)
|
||||||
|
{
|
||||||
|
if (this->buffer != QSE_NULL)
|
||||||
|
delete[] this->buffer;
|
||||||
|
this->buffer = QSE_NULL;
|
||||||
|
this->capacity = 0;
|
||||||
|
this->count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T* tmp = QSE_NULL;
|
||||||
|
qse_size_t cnt = this->count;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tmp = new T[capacity];
|
||||||
|
if (cnt > capacity) cnt = capacity;
|
||||||
|
for (qse_size_t i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
tmp[i] = this->buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
if (tmp != QSE_NULL) delete[] tmp;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->buffer != QSE_NULL)
|
||||||
|
delete[] this->buffer;
|
||||||
|
this->buffer = tmp;
|
||||||
|
this->capacity = capacity;
|
||||||
|
this->count = cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qse_size_t indexOf (const T& value) const
|
||||||
|
{
|
||||||
|
for (qse_size_t i = 0; i < this->count; i++)
|
||||||
|
{
|
||||||
|
if (this->buffer[i] == value) return i;
|
||||||
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t indexOf (const T& value, qse_size_t index) const
|
||||||
|
{
|
||||||
|
for (qse_size_t i = index; i < this->count; i++)
|
||||||
|
{
|
||||||
|
if (this->buffer[i] == value) return i;
|
||||||
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t lastIndexOf (const T& value) const
|
||||||
|
{
|
||||||
|
for (qse_size_t i = this->count; i > 0; )
|
||||||
|
{
|
||||||
|
if (this->buffer[--i] == value) return i;
|
||||||
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t lastIndexOf (const T& value, qse_size_t index) const
|
||||||
|
{
|
||||||
|
for (qse_size_t i = index + 1; i > 0; )
|
||||||
|
{
|
||||||
|
if (this->buffer[--i] == value) return i;
|
||||||
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void rotate (int dir, qse_size_t n)
|
||||||
|
{
|
||||||
|
qse_size_t first, last, cnt, index, nk;
|
||||||
|
T c;
|
||||||
|
|
||||||
|
if (dir == 0) return this->count;
|
||||||
|
if ((n %= this->count) == 0) return this->count;
|
||||||
|
|
||||||
|
if (dir > 0) n = this->count - n;
|
||||||
|
first = 0; nk = this->count - n; cnt = 0;
|
||||||
|
|
||||||
|
while (cnt < n)
|
||||||
|
{
|
||||||
|
last = first + nk;
|
||||||
|
index = first;
|
||||||
|
c = this->buffer[first];
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
cnt++;
|
||||||
|
while (index < nk)
|
||||||
|
{
|
||||||
|
this->buffer[index] = this->buffer[index + n];
|
||||||
|
index += n;
|
||||||
|
}
|
||||||
|
if (index == last) break;
|
||||||
|
this->buffer[index] = this->buffer[index - nk];
|
||||||
|
index -= nk;
|
||||||
|
}
|
||||||
|
this->buffer[last] = c; first++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Mpool mp;
|
||||||
|
RESIZER resizer;
|
||||||
|
|
||||||
|
qse_size_t count;
|
||||||
|
qse_size_t capacity;
|
||||||
|
T* buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
QSE_END_NAMESPACE(QSE)
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
360
qse/include/qse/cmn/BinaryHeap.hpp
Normal file
360
qse/include/qse/cmn/BinaryHeap.hpp
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* $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_BINARYHEAP_HPP_
|
||||||
|
#define _QSE_CMN_BINARYHEAP_HPP_
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This file provides an array-based binary heap.
|
||||||
|
/// In the heap, each node is greater than or equal to its BinaryHeap
|
||||||
|
///
|
||||||
|
/// #include <qse/cmn/BinaryHeap.hpp>
|
||||||
|
/// #include <stdio.h>
|
||||||
|
///
|
||||||
|
/// struct IntComparator
|
||||||
|
/// {
|
||||||
|
/// bool operator() (int v1, int v2) const
|
||||||
|
/// {
|
||||||
|
/// //return !(v1 > v2);
|
||||||
|
/// return v1 > v2;
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// int main (int argc, char* argv[])
|
||||||
|
/// {
|
||||||
|
/// QSE::BinaryHeap<int,IntComparator> heap;
|
||||||
|
///
|
||||||
|
/// heap.insert (70);
|
||||||
|
/// heap.insert (90);
|
||||||
|
/// heap.insert (10);
|
||||||
|
/// heap.insert (5);
|
||||||
|
/// heap.insert (88);
|
||||||
|
/// heap.insert (87);
|
||||||
|
/// heap.insert (300);
|
||||||
|
/// heap.insert (91);
|
||||||
|
/// heap.insert (100);
|
||||||
|
/// heap.insert (200);
|
||||||
|
///
|
||||||
|
/// while (heap.getSize() > 0)
|
||||||
|
/// {
|
||||||
|
/// printf ("%d\n", heap.getRootValue());
|
||||||
|
/// heap.remove (0);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// return 0;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
|
||||||
|
#include <qse/Types.hpp>
|
||||||
|
#include <qse/cmn/Mpool.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct BinaryHeapComparator
|
||||||
|
{
|
||||||
|
// this can be used to build a max heap
|
||||||
|
bool operator() (const T& v1, const T& v2) const
|
||||||
|
{
|
||||||
|
return v1 > v2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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, xp_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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BinaryHeap<T,COMPARATOR,ASSIGNER,RESIZER> SelfType;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_CAPACITY = 10,
|
||||||
|
MIN_CAPACITY = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BinaryHeap
|
||||||
|
Mpool& getMpool ()
|
||||||
|
{
|
||||||
|
return this->mp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Mpool& getMpool () const
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
return (this->greater_than (value, old))? sift_up (index): sift_down (index);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void remove_node (qse_size_t index)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (index < this->data_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];
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
|
// delete the last item
|
||||||
|
Tree<T>::remove (this->data_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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear ()
|
||||||
|
{
|
||||||
|
while (this->root->notNil()) this->remove_node (this->root);
|
||||||
|
QSE_ASSERT (this->root = this->nil);
|
||||||
|
QSE_ASSERT (this->node_count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Node* 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]))
|
||||||
|
{
|
||||||
|
// note that this->assign() isn't called for temporary assignment.
|
||||||
|
T item = this->data_buffer[index];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//this->data_buffer[index] = this->data_buffer[up];
|
||||||
|
this->assign (this->data_buffer[index], this->data_buffer[up], index);
|
||||||
|
|
||||||
|
index = up;
|
||||||
|
up = QSE_ARRAY_HEAP_PARENT (up);
|
||||||
|
}
|
||||||
|
while (index > 0 && this->greater_than (item, this->data_buffer[up]));
|
||||||
|
|
||||||
|
//this->data_buffer[index] = item;
|
||||||
|
this->assign (this->data_buffer[index], item, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#endif
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* sift_down (qse_size_t index)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
qse_size_t half_data_count = this->data_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];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
qse_size_t left, right, greater;
|
||||||
|
|
||||||
|
left = QSE_ARRAY_HEAP_LEFT (index);
|
||||||
|
right = QSE_ARRAY_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 the right child exists and
|
||||||
|
// the right item is greater than the left item
|
||||||
|
greater = right;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
index = greater;
|
||||||
|
}
|
||||||
|
while (index < half_data_count);
|
||||||
|
|
||||||
|
//this->data_buffer[index] = item;
|
||||||
|
this->assign (this->data_buffer[index], item, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
QSE_END_NAMESPACE(QSE)
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
@ -53,6 +53,7 @@ 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 RedBlackTable.hpp
|
RedBlackTree.hpp RedBlackTable.hpp \
|
||||||
|
Array.hpp BinaryHeap.hpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ 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 RedBlackTable.hpp
|
@ENABLE_CXX_TRUE@ RedBlackTree.hpp RedBlackTable.hpp \
|
||||||
|
@ENABLE_CXX_TRUE@ Array.hpp BinaryHeap.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 +94,8 @@ 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 RedBlackTable.hpp
|
HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp Array.hpp \
|
||||||
|
BinaryHeap.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/||"`;; \
|
||||||
|
@ -179,6 +179,8 @@ QSE_END_NAMESPACE(QSE)
|
|||||||
void* operator new (qse_size_t size, QSE::Mmgr* mmgr);
|
void* operator new (qse_size_t size, QSE::Mmgr* mmgr);
|
||||||
void operator delete (void* ptr, QSE::Mmgr* mmgr);
|
void operator delete (void* ptr, QSE::Mmgr* mmgr);
|
||||||
|
|
||||||
|
void* operator new (qse_size_t size, QSE::Mmgr* mmgr, void* existing_ptr);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// i found no way to delete an array allocated with
|
// i found no way to delete an array allocated with
|
||||||
// the placement new operator. if the array element is an instance
|
// the placement new operator. if the array element is an instance
|
||||||
|
@ -117,5 +117,6 @@ QSE_END_NAMESPACE(QSE)
|
|||||||
void* operator new (qse_size_t size, QSE::Mpool* mp);
|
void* operator new (qse_size_t size, QSE::Mpool* mp);
|
||||||
void operator delete (void* ptr, QSE::Mpool* mp);
|
void operator delete (void* ptr, QSE::Mpool* mp);
|
||||||
|
|
||||||
|
void* operator new (qse_size_t size, QSE::Mpool* mp, void* existing_ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -55,19 +55,19 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Color color;
|
Color color;
|
||||||
SelfType* parent;
|
SelfType* up;
|
||||||
SelfType* left; // left child
|
SelfType* left; // left child
|
||||||
SelfType* right; // right child
|
SelfType* right; // right child
|
||||||
|
|
||||||
RedBlackTreeNode(): color (BLACK), parent (this), left (this), right (this)
|
RedBlackTreeNode(): color (BLACK), up (this), left (this), right (this)
|
||||||
{
|
{
|
||||||
// no initialization on 'value' in this constructor.
|
// no initialization on 'value' in this constructor.
|
||||||
}
|
}
|
||||||
|
|
||||||
RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right):
|
RedBlackTreeNode(const T& value, Color color, SelfType* up, SelfType* left, SelfType* right):
|
||||||
value (value), color (color), parent (parent), left (left), right (right)
|
value (value), color (color), up (up), left (left), right (right)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (parent != this);
|
QSE_ASSERT (up != this);
|
||||||
QSE_ASSERT (left != this);
|
QSE_ASSERT (left != this);
|
||||||
QSE_ASSERT (right != this);
|
QSE_ASSERT (right != this);
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public:
|
|||||||
|
|
||||||
bool isNil () const
|
bool isNil () const
|
||||||
{
|
{
|
||||||
return this->parent == this; // && this->left == this && this->right == this;
|
return this->up == this; // && this->left == this && this->right == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notNil () const
|
bool notNil () const
|
||||||
@ -90,28 +90,21 @@ public:
|
|||||||
bool isBlack () const { return this->color == BLACK; }
|
bool isBlack () const { return this->color == BLACK; }
|
||||||
bool isRed () const { return this->color == RED; }
|
bool isRed () const { return this->color == RED; }
|
||||||
|
|
||||||
SelfType* getParent () { return this->parent; }
|
SelfType* getUpNode () { return this->up; }
|
||||||
const SelfType* getParent () const { return this->parent; }
|
const SelfType* getUpNode () const { return this->up; }
|
||||||
SelfType* getParentNode () { return this->parent; }
|
|
||||||
const SelfType* getParentNode () const { return this->parent; }
|
|
||||||
|
|
||||||
SelfType* getLeft () { return this->left; }
|
|
||||||
const SelfType* getLeft () const { return this->left; }
|
|
||||||
SelfType* getLeftNode () { return this->left; }
|
SelfType* getLeftNode () { return this->left; }
|
||||||
const SelfType* getLeftNode () const { return this->left; }
|
const SelfType* getLeftNode () const { return this->left; }
|
||||||
|
|
||||||
SelfType* getRight () { return this->right; }
|
|
||||||
const SelfType* getRight () const { return this->right; }
|
|
||||||
SelfType* getRightNode () { return this->right; }
|
SelfType* getRightNode () { return this->right; }
|
||||||
const SelfType* getRightNode () const { return this->right; }
|
const SelfType* getRightNode () const { return this->right; }
|
||||||
|
|
||||||
//void setBlack () { this->color = BLACK; }
|
//void setBlack () { this->color = BLACK; }
|
||||||
//void setRed () { this->color = RED; }
|
//void setRed () { this->color = RED; }
|
||||||
//void setParent (SelfType* node) { this->parent = node; }
|
//void setUpNode (SelfType* node) { this->up = node; }
|
||||||
//void setLeft (SelfType* node) { this->left = node; }
|
//void setLeftNode (SelfType* node) { this->left = node; }
|
||||||
//void setRight (SelfType* node) { this->right = node; }
|
//void setRightNode (SelfType* node) { this->right = node; }
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -153,16 +146,16 @@ public:
|
|||||||
{
|
{
|
||||||
QSE_ASSERT (root != QSE_NULL);
|
QSE_ASSERT (root != QSE_NULL);
|
||||||
|
|
||||||
this->previous = root->getParent();
|
this->previous = root->getUpNode();
|
||||||
if (mode == DESCENDING)
|
if (mode == DESCENDING)
|
||||||
{
|
{
|
||||||
this->get_left = &Node::getRight;
|
this->get_left = &Node::getRightNode;
|
||||||
this->get_right = &Node::getLeft;
|
this->get_right = &Node::getLeftNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->get_left = &Node::getLeft;
|
this->get_left = &Node::getLeftNode;
|
||||||
this->get_right = &Node::getRight;
|
this->get_right = &Node::getRightNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->__move_to_next_node ();
|
this->__move_to_next_node ();
|
||||||
@ -175,9 +168,9 @@ protected:
|
|||||||
|
|
||||||
while (this->current->notNil())
|
while (this->current->notNil())
|
||||||
{
|
{
|
||||||
if (this->previous == this->current->getParent())
|
if (this->previous == this->current->getUpNode())
|
||||||
{
|
{
|
||||||
/* the previous node is the parent of the current node.
|
/* the previous node is the up of the current node.
|
||||||
* it indicates that we're going down to the getChild(l) */
|
* it indicates that we're going down to the getChild(l) */
|
||||||
if ((this->current->*this->get_left)()->notNil())
|
if ((this->current->*this->get_left)()->notNil())
|
||||||
{
|
{
|
||||||
@ -201,9 +194,9 @@ protected:
|
|||||||
{
|
{
|
||||||
/* both the left child and the right child have been traversed */
|
/* both the left child and the right child have been traversed */
|
||||||
QSE_ASSERT (this->previous == (this->current->*this->get_right)());
|
QSE_ASSERT (this->previous == (this->current->*this->get_right)());
|
||||||
/* just move up to the parent */
|
/* just move up to the up */
|
||||||
this->previous = this->current;
|
this->previous = this->current;
|
||||||
this->current = this->current->getParent();
|
this->current = this->current->getUpNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,9 +213,9 @@ protected:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* otherwise, move up to the parent */
|
/* otherwise, move up to the up */
|
||||||
this->previous = this->current;
|
this->previous = this->current;
|
||||||
this->current = this->current->getParent();
|
this->current = this->current->getUpNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pending_action == 2)
|
else if (pending_action == 2)
|
||||||
@ -235,9 +228,9 @@ protected:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* otherwise, move up to the parent */
|
/* otherwise, move up to the up */
|
||||||
this->previous = this->current;
|
this->previous = this->current;
|
||||||
this->current = this->current->getParent();
|
this->current = this->current->getUpNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +331,7 @@ public:
|
|||||||
this->root = this->nil;
|
this->root = this->nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
RedBlackTree (const RedBlackTree& rbt):
|
RedBlackTree (const SelfType& rbt):
|
||||||
Mmged (rbt.getMmgr()),
|
Mmged (rbt.getMmgr()),
|
||||||
mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()),
|
mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()),
|
||||||
node_count (0)
|
node_count (0)
|
||||||
@ -365,7 +358,7 @@ public:
|
|||||||
this->dispose_node (this->nil);
|
this->dispose_node (this->nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
RedBlackTree& operator= (const RedBlackTree& rbt)
|
SelfType& operator= (const SelfType& rbt)
|
||||||
{
|
{
|
||||||
this->clear ();
|
this->clear ();
|
||||||
|
|
||||||
@ -400,14 +393,16 @@ public:
|
|||||||
return this->node_count <= 0;
|
return this->node_count <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The getRootNode() function gets the pointer to the root node.
|
||||||
|
/// If no node exists in the tree, it returns #QSE_NULL.
|
||||||
Node* getRootNode ()
|
Node* getRootNode ()
|
||||||
{
|
{
|
||||||
return this->root;
|
return this->root->isNil()? QSE_NULL: this->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Node* getRootNode () const
|
const Node* getRootNode () const
|
||||||
{
|
{
|
||||||
return this->root;
|
return this->root->isNil()? QSE_NULL: this->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -463,7 +458,7 @@ protected:
|
|||||||
* left child(x). move the pivot's right child(y) to the pivot's original
|
* 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
|
* position. as 'c1' is between 'y' and 'pivot', move it to the right
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
* parent parent
|
* up up
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot y
|
* pivot y
|
||||||
* / \ / \
|
* / \ / \
|
||||||
@ -477,7 +472,7 @@ protected:
|
|||||||
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
*
|
*
|
||||||
* parent parent
|
* up up
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot x
|
* pivot x
|
||||||
* / \ / \
|
* / \ / \
|
||||||
@ -487,15 +482,15 @@ protected:
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* the actual implementation here resolves the pivot's relationship to
|
* the actual implementation here resolves the pivot's relationship to
|
||||||
* its parent by comparaing pointers as it is not known if the pivot pair
|
* its up by comparaing pointers as it is not known if the pivot pair
|
||||||
* is the left child or the right child of its parent,
|
* is the left child or the right child of its up,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Node* parent, * z, * c;
|
Node* up, * z, * c;
|
||||||
|
|
||||||
QSE_ASSERT (pivot != QSE_NULL);
|
QSE_ASSERT (pivot != QSE_NULL);
|
||||||
|
|
||||||
parent = pivot->parent;
|
up = pivot->up;
|
||||||
if (leftwise)
|
if (leftwise)
|
||||||
{
|
{
|
||||||
// y for leftwise rotation
|
// y for leftwise rotation
|
||||||
@ -511,17 +506,17 @@ protected:
|
|||||||
c = z->right;
|
c = z->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
z->parent = parent;
|
z->up = up;
|
||||||
if (parent->notNil())
|
if (up->notNil())
|
||||||
{
|
{
|
||||||
if (parent->left == pivot)
|
if (up->left == pivot)
|
||||||
{
|
{
|
||||||
parent->left = z;
|
up->left = z;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (parent->right == pivot);
|
QSE_ASSERT (up->right == pivot);
|
||||||
parent->right = z;
|
up->right = z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -541,8 +536,8 @@ protected:
|
|||||||
pivot->left = c;
|
pivot->left = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pivot->notNil()) pivot->parent = z;
|
if (pivot->notNil()) pivot->up = z;
|
||||||
if (c->notNil()) c->parent = pivot;
|
if (c->notNil()) c->up = pivot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rotate_left (Node* pivot)
|
void rotate_left (Node* pivot)
|
||||||
@ -562,12 +557,12 @@ protected:
|
|||||||
Node* tmp, * tmp2, * x_par, * x_grand_par;
|
Node* tmp, * tmp2, * x_par, * x_grand_par;
|
||||||
bool leftwise;
|
bool leftwise;
|
||||||
|
|
||||||
x_par = node->parent;
|
x_par = node->up;
|
||||||
if (x_par->color == Node::BLACK) break;
|
if (x_par->color == Node::BLACK) break;
|
||||||
|
|
||||||
QSE_ASSERT (x_par->parent->notNil());
|
QSE_ASSERT (x_par->up->notNil());
|
||||||
|
|
||||||
x_grand_par = x_par->parent;
|
x_grand_par = x_par->up;
|
||||||
if (x_par == x_grand_par->left)
|
if (x_par == x_grand_par->left)
|
||||||
{
|
{
|
||||||
tmp = x_grand_par->right;
|
tmp = x_grand_par->right;
|
||||||
@ -594,8 +589,8 @@ protected:
|
|||||||
{
|
{
|
||||||
node = x_par;
|
node = x_par;
|
||||||
this->rotate (node, leftwise);
|
this->rotate (node, leftwise);
|
||||||
x_par = node->parent;
|
x_par = node->up;
|
||||||
x_grand_par = x_par->parent;
|
x_grand_par = x_par->up;
|
||||||
}
|
}
|
||||||
|
|
||||||
x_par->color = Node::BLACK;
|
x_par->color = Node::BLACK;
|
||||||
@ -627,7 +622,7 @@ protected:
|
|||||||
{
|
{
|
||||||
if (tmp->notNil()) tmp->color = Node::RED;
|
if (tmp->notNil()) tmp->color = Node::RED;
|
||||||
node = par;
|
node = par;
|
||||||
par = node->parent;
|
par = node->up;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -666,7 +661,7 @@ protected:
|
|||||||
{
|
{
|
||||||
if (tmp->notNil()) tmp->color = Node::RED;
|
if (tmp->notNil()) tmp->color = Node::RED;
|
||||||
node = par;
|
node = par;
|
||||||
par = node->parent;
|
par = node->up;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -711,8 +706,8 @@ protected:
|
|||||||
|
|
||||||
x = (y->left->isNil())? y->right: y->left;
|
x = (y->left->isNil())? y->right: y->left;
|
||||||
|
|
||||||
par = y->parent;
|
par = y->up;
|
||||||
if (x->notNil()) x->parent = par;
|
if (x->notNil()) x->up = par;
|
||||||
|
|
||||||
if (par->notNil()) // if (par)
|
if (par->notNil()) // if (par)
|
||||||
{
|
{
|
||||||
@ -738,23 +733,23 @@ protected:
|
|||||||
if (y->color == Node::BLACK && x->notNil())
|
if (y->color == Node::BLACK && x->notNil())
|
||||||
this->rebalance_for_removal (x, par);
|
this->rebalance_for_removal (x, par);
|
||||||
|
|
||||||
if (node->parent->notNil()) //if (node->parent)
|
if (node->up->notNil()) //if (node->up)
|
||||||
{
|
{
|
||||||
if (node->parent->left == node) node->parent->left = y;
|
if (node->up->left == node) node->up->left = y;
|
||||||
if (node->parent->right == node) node->parent->right = y;
|
if (node->up->right == node) node->up->right = y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->root = y;
|
this->root = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
y->parent = node->parent;
|
y->up = node->up;
|
||||||
y->left = node->left;
|
y->left = node->left;
|
||||||
y->right = node->right;
|
y->right = node->right;
|
||||||
y->color = node->color;
|
y->color = node->color;
|
||||||
|
|
||||||
if (node->left->parent == node) node->left->parent = y;
|
if (node->left->up == node) node->left->up = y;
|
||||||
if (node->right->parent == node) node->right->parent = y;
|
if (node->right->up == node) node->right->up = y;
|
||||||
|
|
||||||
this->dispose_node (node);
|
this->dispose_node (node);
|
||||||
}
|
}
|
||||||
@ -800,7 +795,6 @@ public:
|
|||||||
return this->heterofind_node<MT,MCOMPARATOR> (datum);
|
return this->heterofind_node<MT,MCOMPARATOR> (datum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename MT, typename MCOMPARATOR>
|
template <typename MT, typename MCOMPARATOR>
|
||||||
T* heterofindValue(const MT& datum)
|
T* heterofindValue(const MT& datum)
|
||||||
{
|
{
|
||||||
@ -839,6 +833,20 @@ public:
|
|||||||
return this->heterofind_node<MT,MCOMPARATOR> (datum);
|
return this->heterofind_node<MT,MCOMPARATOR> (datum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The inject() function inserts a \a datum if no existing datum
|
||||||
|
/// is found to be equal using the comparator. The \a mode argument
|
||||||
|
/// determines what action to take when an equal datum is found.
|
||||||
|
/// - -1: failure
|
||||||
|
/// - 0: do nothing
|
||||||
|
/// - 1: overwrite the existing datum
|
||||||
|
///
|
||||||
|
/// if \a injected is not #QSE_NULL, it is set to true when \a datum
|
||||||
|
/// has been inserted newly and false when an equal datum has been
|
||||||
|
/// found.
|
||||||
|
///
|
||||||
|
/// The function returns the poniter to the node inserted or
|
||||||
|
/// affected. It return #QSE_NULL if mode is set to -1 and a duplicate
|
||||||
|
/// item has been found.
|
||||||
Node* inject (const T& datum, int mode, bool* injected = QSE_NULL)
|
Node* inject (const T& datum, int mode, bool* injected = QSE_NULL)
|
||||||
{
|
{
|
||||||
Node* x_cur = this->root;
|
Node* x_cur = this->root;
|
||||||
@ -881,7 +889,7 @@ public:
|
|||||||
x_par->left = x_new;
|
x_par->left = x_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
x_new->parent = x_par;
|
x_new->up = x_par;
|
||||||
this->rebalance_for_injection (x_new);
|
this->rebalance_for_injection (x_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,13 @@ void operator delete (void* ptr, QSE::Mmgr* mmgr)
|
|||||||
mmgr->dispose (ptr);
|
mmgr->dispose (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* operator new (qse_size_t size, QSE::Mmgr* mmgr, void* existing_ptr)
|
||||||
|
{
|
||||||
|
// mmgr unused. i put it in the parameter list to make this function
|
||||||
|
// less conflicting with the stock ::operator new() that doesn't allocate.
|
||||||
|
return existing_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr)
|
void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr)
|
||||||
{
|
{
|
||||||
|
@ -190,3 +190,8 @@ void operator delete (void* ptr, QSE::Mpool* mp)
|
|||||||
if (mp->isEnabled()) mp->dispose (ptr);
|
if (mp->isEnabled()) mp->dispose (ptr);
|
||||||
else ::operator delete (ptr, mp->getMmgr());
|
else ::operator delete (ptr, mp->getMmgr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* operator new (qse_size_t size, QSE::Mpool* mp, void* existing_ptr)
|
||||||
|
{
|
||||||
|
return existing_ptr;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user