added qse_arr_setheapposoffset()
This commit is contained in:
parent
6b9fd818f8
commit
d321a312d4
@ -149,6 +149,8 @@ struct qse_arr_t
|
||||
qse_arr_keeper_t keeper; /* data keeper */
|
||||
qse_arr_sizer_t sizer; /* size calculator */
|
||||
qse_byte_t scale; /* scale factor */
|
||||
qse_size_t heap_pos_offset; /* offset in the data element where position
|
||||
* is stored when heap operation is performed. */
|
||||
qse_size_t size; /* number of items */
|
||||
qse_size_t capa; /* capacity */
|
||||
qse_arr_slot_t** slot;
|
||||
@ -446,6 +448,36 @@ QSE_EXPORT qse_size_t qse_arr_updateheap (
|
||||
qse_size_t dlen
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_size_t qse_arr_getheapposoffset (
|
||||
qse_arr_t* arr
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_arr_setheapposoffset() function sets the offset to a position holding
|
||||
* field within a data element. It assumes that the field is of the qse_size_t type.
|
||||
*
|
||||
* \code
|
||||
* struct data_t
|
||||
* {
|
||||
* int v;
|
||||
* qse_size_t pos;
|
||||
* };
|
||||
* struct data_t d;
|
||||
* qse_arr_setheapposoffset (arr, QSE_OFFSETOF(struct data_t, pos));
|
||||
* d.v = 20;
|
||||
* qse_arr_pushheap (arr, &d, 1);
|
||||
* \endcode
|
||||
*
|
||||
* In the code above, the 'pos' field of the first element in the array must be 0.
|
||||
*
|
||||
* If it's set to QSE_ARR_NIL, position is not updated when heapification is
|
||||
* performed.
|
||||
*/
|
||||
QSE_EXPORT void qse_arr_setheapposoffset (
|
||||
qse_arr_t* arr,
|
||||
qse_size_t offset
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
@ -135,6 +135,7 @@ int qse_arr_init (arr_t* arr, mmgr_t* mmgr, size_t capa)
|
||||
arr->capa = 0;
|
||||
arr->slot = QSE_NULL;
|
||||
arr->scale = 1;
|
||||
arr->heap_pos_offset = QSE_ARR_NIL;
|
||||
|
||||
arr->copier = QSE_ARR_COPIER_SIMPLE;
|
||||
arr->comper = default_comparator;
|
||||
@ -608,13 +609,20 @@ void qse_arr_popstack (arr_t* arr)
|
||||
#define HEAP_LEFT(x) ((x)*2 + 1)
|
||||
#define HEAP_RIGHT(x) ((x)*2 + 2)
|
||||
|
||||
size_t sift_up (arr_t* arr, size_t index)
|
||||
#define HEAP_UPDATE_POS(arr, index) \
|
||||
do { \
|
||||
if (arr->heap_pos_offset != QSE_ARR_NIL) \
|
||||
*(qse_size_t*)((qse_byte_t*)DPTR(arr->slot[index]) + arr->heap_pos_offset) = index; \
|
||||
} while(0)
|
||||
|
||||
qse_size_t sift_up (arr_t* arr, qse_size_t index)
|
||||
{
|
||||
size_t parent;
|
||||
int n;
|
||||
qse_size_t parent;
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
int n;
|
||||
|
||||
parent = HEAP_PARENT(index);
|
||||
n = arr->comper (arr,
|
||||
DPTR(arr->slot[index]), DLEN(arr->slot[index]),
|
||||
@ -628,6 +636,7 @@ size_t sift_up (arr_t* arr, size_t index)
|
||||
while (1)
|
||||
{
|
||||
arr->slot[index] = arr->slot[parent];
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
|
||||
index = parent;
|
||||
parent = HEAP_PARENT(parent);
|
||||
@ -641,6 +650,7 @@ size_t sift_up (arr_t* arr, size_t index)
|
||||
}
|
||||
|
||||
arr->slot[index] = tmp;
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
@ -684,11 +694,13 @@ size_t sift_down (arr_t* arr, size_t index)
|
||||
if (n > 0) break;
|
||||
|
||||
arr->slot[index] = arr->slot[child];
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
index = child;
|
||||
}
|
||||
while (index < base);
|
||||
|
||||
arr->slot[index] = tmp;
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
@ -701,6 +713,7 @@ size_t qse_arr_pushheap (arr_t* arr, void* dptr, size_t dlen)
|
||||
/* add a value at the back of the array */
|
||||
index = arr->size;
|
||||
if (qse_arr_insert (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL;
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
|
||||
QSE_ASSERT (arr->size == index + 1);
|
||||
|
||||
@ -715,7 +728,7 @@ void qse_arr_popheap (arr_t* arr)
|
||||
qse_arr_deleteheap (arr, 0);
|
||||
}
|
||||
|
||||
void qse_arr_deleteheap (arr_t* arr, size_t index)
|
||||
void qse_arr_deleteheap (arr_t* arr, qse_size_t index)
|
||||
{
|
||||
slot_t* tmp;
|
||||
|
||||
@ -732,6 +745,7 @@ void qse_arr_deleteheap (arr_t* arr, size_t index)
|
||||
|
||||
/* move the last item to the deleting position */
|
||||
arr->slot[index] = arr->slot[arr->size];
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
|
||||
/* move it up if the last item is greater than the item to be deleted,
|
||||
* move it down otherwise. */
|
||||
@ -750,7 +764,7 @@ void qse_arr_deleteheap (arr_t* arr, size_t index)
|
||||
arr->slot[arr->size] = QSE_NULL;
|
||||
}
|
||||
|
||||
size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_size_t dlen)
|
||||
qse_size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_size_t dlen)
|
||||
{
|
||||
slot_t* tmp;
|
||||
int n;
|
||||
@ -762,9 +776,21 @@ size_t qse_arr_updateheap (qse_arr_t* arr, qse_size_t index, void* dptr, qse_siz
|
||||
if (n)
|
||||
{
|
||||
if (qse_arr_update (arr, index, dptr, dlen) == QSE_ARR_NIL) return QSE_ARR_NIL;
|
||||
HEAP_UPDATE_POS (arr, index);
|
||||
|
||||
if (n > 0) sift_up (arr, index);
|
||||
else sift_down (arr, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
qse_size_t qse_arr_getheapposoffset (qse_arr_t* arr)
|
||||
{
|
||||
return arr->heap_pos_offset;
|
||||
}
|
||||
|
||||
void qse_arr_setheapposoffset (qse_arr_t* arr, qse_size_t offset)
|
||||
{
|
||||
arr->heap_pos_offset = offset;
|
||||
}
|
||||
|
@ -19,20 +19,20 @@ void keeper1 (qse_arr_t* arr, void* dptr, qse_size_t dlen)
|
||||
qse_arr_walk_t walker1 (qse_arr_t* arr, qse_size_t index, void* arg)
|
||||
{
|
||||
qse_printf (QSE_T("%d => [%.*s]\n"),
|
||||
index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index));
|
||||
(int)index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index));
|
||||
return QSE_ARR_WALK_FORWARD;
|
||||
}
|
||||
qse_arr_walk_t rwalker1 (qse_arr_t* arr, qse_size_t index, void* arg)
|
||||
{
|
||||
qse_printf (QSE_T("%d => [%.*s]\n"),
|
||||
index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index));
|
||||
(int)index, (int)QSE_ARR_DLEN(arr,index), QSE_ARR_DPTR(arr,index));
|
||||
return QSE_ARR_WALK_BACKWARD;
|
||||
}
|
||||
|
||||
qse_arr_walk_t walker3 (qse_arr_t* arr, qse_size_t index, void* arg)
|
||||
{
|
||||
qse_printf (QSE_T("%d => [%d]\n"),
|
||||
index, *(int*)QSE_ARR_DPTR(arr,index));
|
||||
(int)index, *(int*)QSE_ARR_DPTR(arr,index));
|
||||
return QSE_ARR_WALK_FORWARD;
|
||||
}
|
||||
|
||||
@ -476,6 +476,113 @@ static int test5 ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct test6_data_t
|
||||
{
|
||||
int v;
|
||||
qse_size_t pos;
|
||||
};
|
||||
typedef struct test6_data_t test6_data_t;
|
||||
|
||||
static int test6_comparator (qse_arr_t* arr,
|
||||
const void* dptr1, size_t dlen1,
|
||||
const void* dptr2, size_t dlen2)
|
||||
{
|
||||
return ((test6_data_t*)dptr1)->v > ((test6_data_t*)dptr2)->v? 1:
|
||||
((test6_data_t*)dptr1)->v < ((test6_data_t*)dptr2)->v? -1: 0;
|
||||
}
|
||||
|
||||
qse_arr_walk_t test6_walker (qse_arr_t* arr, qse_size_t index, void* arg)
|
||||
{
|
||||
test6_data_t* x;
|
||||
|
||||
x = QSE_ARR_DPTR(arr,index);
|
||||
qse_printf (QSE_T("%d => [%d] pos=%d\n"), (int)index, (int)x->v, (int)x->pos);
|
||||
QSE_ASSERT (index == x->pos);
|
||||
return QSE_ARR_WALK_FORWARD;
|
||||
}
|
||||
|
||||
static int test6 ()
|
||||
{
|
||||
qse_arr_t* s1;
|
||||
int i, oldv, newv;
|
||||
test6_data_t j;
|
||||
|
||||
s1 = qse_arr_open (QSE_MMGR_GETDFL(), 0, 3);
|
||||
if (s1 == QSE_NULL)
|
||||
{
|
||||
qse_printf (QSE_T("cannot open an array\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_arr_setcopier (s1, QSE_ARR_COPIER_INLINE);
|
||||
qse_arr_setscale (s1, QSE_SIZEOF(j));
|
||||
qse_arr_setcomper (s1, test6_comparator);
|
||||
qse_arr_setheapposoffset (s1, QSE_OFFSETOF(test6_data_t, pos));
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
j.v = rand () % 65535;
|
||||
qse_arr_pushheap (s1, &j, 1);
|
||||
}
|
||||
|
||||
j.v = 88888888;
|
||||
qse_arr_updateheap (s1, QSE_ARR_SIZE(s1) / 2, &j, 1);
|
||||
j.v = -123;
|
||||
qse_arr_updateheap (s1, QSE_ARR_SIZE(s1) / 2, &j, 1);
|
||||
|
||||
qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1));
|
||||
qse_arr_walk (s1, test6_walker, QSE_NULL);
|
||||
|
||||
oldv = 99999999;
|
||||
while (QSE_ARR_SIZE(s1) > 50)
|
||||
{
|
||||
newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v;
|
||||
qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv);
|
||||
QSE_ASSERT (newv <= oldv);
|
||||
qse_arr_popheap (s1);
|
||||
oldv = newv;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1));
|
||||
qse_arr_walk (s1, test6_walker, QSE_NULL);
|
||||
|
||||
while (QSE_ARR_SIZE(s1) > 10)
|
||||
{
|
||||
newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v;
|
||||
qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv);
|
||||
QSE_ASSERT (newv <= oldv);
|
||||
qse_arr_popheap (s1);
|
||||
oldv = newv;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1));
|
||||
qse_arr_walk (s1, test6_walker, QSE_NULL);
|
||||
|
||||
while (QSE_ARR_SIZE(s1) > 1)
|
||||
{
|
||||
newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v;
|
||||
qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv);
|
||||
QSE_ASSERT (newv <= oldv);
|
||||
qse_arr_popheap (s1);
|
||||
oldv = newv;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("arr size => %lu\n"), QSE_ARR_SIZE(s1));
|
||||
qse_arr_walk (s1, test6_walker, QSE_NULL);
|
||||
|
||||
while (QSE_ARR_SIZE(s1) > 0)
|
||||
{
|
||||
newv = ((test6_data_t*)QSE_ARR_DPTR(s1,0))->v;
|
||||
qse_printf (QSE_T("top => %d prevtop => %d\n"), newv, oldv);
|
||||
QSE_ASSERT (newv <= oldv);
|
||||
qse_arr_popheap (s1);
|
||||
oldv = newv;
|
||||
}
|
||||
|
||||
qse_arr_close (s1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
qse_openstdsios ();
|
||||
@ -484,6 +591,7 @@ int main ()
|
||||
R (test3);
|
||||
R (test4);
|
||||
R (test5);
|
||||
R (test6);
|
||||
qse_closestdsios ();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user