/* pqueue.h Priority Queues Copyright (C) 2021 Bill Currie Author: Bill Currie Date: 2021/08/02 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifndef __QF_pqueue_h #define __QF_pqueue_h #include #include "QF/heapsort.h" #include "QF/sys.h" /** \defgroup pqueue Priority Queues \ingroup utils Priority queue management */ ///@{ /** The structure def for a priority queue with elements of the given type. This is just the def of a struct delcaration: it is useless on its own. The intended usage is something like: typedef struct priority_queue_s PQUEUE_TYPE (int) priority_queue_t; This allows full flexibility in just how the actual type is used. The \a size field is the number of elements currently in the queue, and the \a maxSize field is the number of elements the queue can hold. The priority queue functions will never resize the array. However, with a little glue logic, priority queues can be used with dynamic arrays. \param T The type to use for the element array, which is accessed by the \a a field. */ #define PQUEUE_TYPE(T) \ { \ size_t size; \ size_t maxSize; \ T *a; \ int (*compare) (const T *a, const T *b, void *data); \ void *data; \ } #define PQUEUE_IS_EMPTY(queue) ((queue)->size == 0) #define PQUEUE_IS_FULL(queue) \ ({ \ __auto_type q_f = (queue); \ q_f->size == q_f->maxSize; \ }) #define PQUEUE_PEEK(queue) ((queue)->a[0]) #define PQUEUE_INSERT(queue, value) \ do { \ __auto_type q = (queue); \ if (PQUEUE_IS_FULL (q)) { \ Sys_Error ("Priority queue full"); \ } \ q->a[q->size++] = (value); \ heap_swim_r (q->a, q->size - 1, q->size, sizeof (q->a[0]), \ (__compar_d_fn_t) q->compare, q->data); \ } while (0) #define PQUEUE_REMOVE(queue) \ ({ \ __auto_type q = (queue); \ if (PQUEUE_IS_EMPTY (q)) { \ Sys_Error ("Priority queue empty"); \ } \ __auto_type value = q->a[0]; \ q->a[0] = q->a[--q->size]; \ heap_sink_r (q->a, 0, q->size, sizeof (q->a[0]), \ (__compar_d_fn_t) q->compare, q->data); \ value; \ }) #define PQUEUE_ADJUST(queue, index) \ do { \ __auto_type q = (queue); \ size_t ind = (index); \ if (ind >= q->size) { \ Sys_Error ("Priority queue index error"); \ } \ if (ind>0 && q->compare(q->a + ind, q->a + (ind-1)/2, q->data)>0) { \ heap_swim_r (q->a, ind, q->size, sizeof (q->a[0]), \ (__compar_d_fn_t) q->compare, q->data); \ } else { \ heap_sink_r (q->a, ind, q->size, sizeof (q->a[0]), \ (__compar_d_fn_t) q->compare, q->data); \ } \ } while (0) ///@} #endif//__QF_pqueue_h