Path: blob/devel/elmergrid/src/metis-5.1.0/GKlib/gk_mkpqueue.h
3206 views
/*!1\file gk_mkpqueue.h2\brief Templates for priority queues34\date Started 4/09/075\author George6\version\verbatim $Id: gk_mkpqueue.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim7*/8910#ifndef _GK_MKPQUEUE_H11#define _GK_MKPQUEUE_H121314#define GK_MKPQUEUE(FPRFX, PQT, KVT, KT, VT, KVMALLOC, KMAX, KEY_LT)\15/*************************************************************************/\16/*! This function creates and initializes a priority queue */\17/**************************************************************************/\18PQT *FPRFX ## Create(size_t maxnodes)\19{\20PQT *queue; \21\22queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate: queue");\23FPRFX ## Init(queue, maxnodes);\24\25return queue;\26}\27\28\29/*************************************************************************/\30/*! This function initializes the data structures of the priority queue */\31/**************************************************************************/\32void FPRFX ## Init(PQT *queue, size_t maxnodes)\33{\34queue->nnodes = 0;\35queue->maxnodes = maxnodes;\36\37queue->heap = KVMALLOC(maxnodes, "gk_PQInit: heap");\38queue->locator = gk_idxsmalloc(maxnodes, -1, "gk_PQInit: locator");\39}\40\41\42/*************************************************************************/\43/*! This function resets the priority queue */\44/**************************************************************************/\45void FPRFX ## Reset(PQT *queue)\46{\47gk_idx_t i;\48gk_idx_t *locator=queue->locator;\49KVT *heap=queue->heap;\50\51for (i=queue->nnodes-1; i>=0; i--)\52locator[heap[i].val] = -1;\53queue->nnodes = 0;\54}\55\56\57/*************************************************************************/\58/*! This function frees the internal datastructures of the priority queue */\59/**************************************************************************/\60void FPRFX ## Free(PQT *queue)\61{\62if (queue == NULL) return;\63gk_free((void **)&queue->heap, &queue->locator, LTERM);\64queue->maxnodes = 0;\65}\66\67\68/*************************************************************************/\69/*! This function frees the internal datastructures of the priority queue \70and the queue itself */\71/**************************************************************************/\72void FPRFX ## Destroy(PQT *queue)\73{\74if (queue == NULL) return;\75FPRFX ## Free(queue);\76gk_free((void **)&queue, LTERM);\77}\78\79\80/*************************************************************************/\81/*! This function returns the length of the queue */\82/**************************************************************************/\83size_t FPRFX ## Length(PQT *queue)\84{\85return queue->nnodes;\86}\87\88\89/*************************************************************************/\90/*! This function adds an item in the priority queue */\91/**************************************************************************/\92int FPRFX ## Insert(PQT *queue, VT node, KT key)\93{\94gk_idx_t i, j;\95gk_idx_t *locator=queue->locator;\96KVT *heap=queue->heap;\97\98ASSERT2(FPRFX ## CheckHeap(queue));\99\100ASSERT(locator[node] == -1);\101\102i = queue->nnodes++;\103while (i > 0) {\104j = (i-1)>>1;\105if (KEY_LT(key, heap[j].key)) {\106heap[i] = heap[j];\107locator[heap[i].val] = i;\108i = j;\109}\110else\111break;\112}\113ASSERT(i >= 0);\114heap[i].key = key;\115heap[i].val = node;\116locator[node] = i;\117\118ASSERT2(FPRFX ## CheckHeap(queue));\119\120return 0;\121}\122\123\124/*************************************************************************/\125/*! This function deletes an item from the priority queue */\126/**************************************************************************/\127int FPRFX ## Delete(PQT *queue, VT node)\128{\129gk_idx_t i, j, nnodes;\130KT newkey, oldkey;\131gk_idx_t *locator=queue->locator;\132KVT *heap=queue->heap;\133\134ASSERT(locator[node] != -1);\135ASSERT(heap[locator[node]].val == node);\136\137ASSERT2(FPRFX ## CheckHeap(queue));\138\139i = locator[node];\140locator[node] = -1;\141\142if (--queue->nnodes > 0 && heap[queue->nnodes].val != node) {\143node = heap[queue->nnodes].val;\144newkey = heap[queue->nnodes].key;\145oldkey = heap[i].key;\146\147if (KEY_LT(newkey, oldkey)) { /* Filter-up */\148while (i > 0) {\149j = (i-1)>>1;\150if (KEY_LT(newkey, heap[j].key)) {\151heap[i] = heap[j];\152locator[heap[i].val] = i;\153i = j;\154}\155else\156break;\157}\158}\159else { /* Filter down */\160nnodes = queue->nnodes;\161while ((j=(i<<1)+1) < nnodes) {\162if (KEY_LT(heap[j].key, newkey)) {\163if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\164j++;\165heap[i] = heap[j];\166locator[heap[i].val] = i;\167i = j;\168}\169else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\170j++;\171heap[i] = heap[j];\172locator[heap[i].val] = i;\173i = j;\174}\175else\176break;\177}\178}\179\180heap[i].key = newkey;\181heap[i].val = node;\182locator[node] = i;\183}\184\185ASSERT2(FPRFX ## CheckHeap(queue));\186\187return 0;\188}\189\190\191/*************************************************************************/\192/*! This function updates the key values associated for a particular item */ \193/**************************************************************************/\194void FPRFX ## Update(PQT *queue, VT node, KT newkey)\195{\196gk_idx_t i, j, nnodes;\197KT oldkey;\198gk_idx_t *locator=queue->locator;\199KVT *heap=queue->heap;\200\201oldkey = heap[locator[node]].key;\202\203ASSERT(locator[node] != -1);\204ASSERT(heap[locator[node]].val == node);\205ASSERT2(FPRFX ## CheckHeap(queue));\206\207i = locator[node];\208\209if (KEY_LT(newkey, oldkey)) { /* Filter-up */\210while (i > 0) {\211j = (i-1)>>1;\212if (KEY_LT(newkey, heap[j].key)) {\213heap[i] = heap[j];\214locator[heap[i].val] = i;\215i = j;\216}\217else\218break;\219}\220}\221else { /* Filter down */\222nnodes = queue->nnodes;\223while ((j=(i<<1)+1) < nnodes) {\224if (KEY_LT(heap[j].key, newkey)) {\225if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\226j++;\227heap[i] = heap[j];\228locator[heap[i].val] = i;\229i = j;\230}\231else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\232j++;\233heap[i] = heap[j];\234locator[heap[i].val] = i;\235i = j;\236}\237else\238break;\239}\240}\241\242heap[i].key = newkey;\243heap[i].val = node;\244locator[node] = i;\245\246ASSERT2(FPRFX ## CheckHeap(queue));\247\248return;\249}\250\251\252/*************************************************************************/\253/*! This function returns the item at the top of the queue and removes\254it from the priority queue */\255/**************************************************************************/\256VT FPRFX ## GetTop(PQT *queue)\257{\258gk_idx_t i, j;\259gk_idx_t *locator;\260KVT *heap;\261VT vtx, node;\262KT key;\263\264ASSERT2(FPRFX ## CheckHeap(queue));\265\266if (queue->nnodes == 0)\267return -1;\268\269queue->nnodes--;\270\271heap = queue->heap;\272locator = queue->locator;\273\274vtx = heap[0].val;\275locator[vtx] = -1;\276\277if ((i = queue->nnodes) > 0) {\278key = heap[i].key;\279node = heap[i].val;\280i = 0;\281while ((j=2*i+1) < queue->nnodes) {\282if (KEY_LT(heap[j].key, key)) {\283if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, heap[j].key))\284j = j+1;\285heap[i] = heap[j];\286locator[heap[i].val] = i;\287i = j;\288}\289else if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, key)) {\290j = j+1;\291heap[i] = heap[j];\292locator[heap[i].val] = i;\293i = j;\294}\295else\296break;\297}\298\299heap[i].key = key;\300heap[i].val = node;\301locator[node] = i;\302}\303\304ASSERT2(FPRFX ## CheckHeap(queue));\305return vtx;\306}\307\308\309/*************************************************************************/\310/*! This function returns the item at the top of the queue. The item is not\311deleted from the queue. */\312/**************************************************************************/\313VT FPRFX ## SeeTopVal(PQT *queue)\314{\315return (queue->nnodes == 0 ? -1 : queue->heap[0].val);\316}\317\318\319/*************************************************************************/\320/*! This function returns the key of the top item. The item is not\321deleted from the queue. */\322/**************************************************************************/\323KT FPRFX ## SeeTopKey(PQT *queue)\324{\325return (queue->nnodes == 0 ? KMAX : queue->heap[0].key);\326}\327\328\329/*************************************************************************/\330/*! This function returns the key of a specific item */\331/**************************************************************************/\332KT FPRFX ## SeeKey(PQT *queue, VT node)\333{\334gk_idx_t *locator;\335KVT *heap;\336\337heap = queue->heap;\338locator = queue->locator;\339\340return heap[locator[node]].key;\341}\342\343\344/*************************************************************************/\345/*! This function returns the first item in a breadth-first traversal of\346the heap whose key is less than maxwgt. This function is here due to\347hMETIS and is not general!*/\348/**************************************************************************/\349/*\350VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts)\351{\352gk_idx_t i;\353\354if (queue->nnodes == 0)\355return -1;\356\357if (maxwgt <= 1000)\358return FPRFX ## SeeTopVal(queue);\359\360for (i=0; i<queue->nnodes; i++) {\361if (queue->heap[i].key > 0) {\362if (wgts[queue->heap[i].val] <= maxwgt)\363return queue->heap[i].val;\364}\365else {\366if (queue->heap[i/2].key <= 0)\367break;\368}\369}\370\371return queue->heap[0].val;\372\373}\374*/\375\376\377/*************************************************************************/\378/*! This functions checks the consistency of the heap */\379/**************************************************************************/\380int FPRFX ## CheckHeap(PQT *queue)\381{\382gk_idx_t i, j;\383size_t nnodes;\384gk_idx_t *locator;\385KVT *heap;\386\387heap = queue->heap;\388locator = queue->locator;\389nnodes = queue->nnodes;\390\391if (nnodes == 0)\392return 1;\393\394ASSERT(locator[heap[0].val] == 0);\395for (i=1; i<nnodes; i++) {\396ASSERT(locator[heap[i].val] == i);\397ASSERT(!KEY_LT(heap[i].key, heap[(i-1)/2].key));\398}\399for (i=1; i<nnodes; i++)\400ASSERT(!KEY_LT(heap[i].key, heap[0].key));\401\402for (j=i=0; i<queue->maxnodes; i++) {\403if (locator[i] != -1)\404j++;\405}\406ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\407\408return 1;\409}\410411412#define GK_MKPQUEUE_PROTO(FPRFX, PQT, KT, VT)\413PQT * FPRFX ## Create(size_t maxnodes);\414void FPRFX ## Init(PQT *queue, size_t maxnodes);\415void FPRFX ## Reset(PQT *queue);\416void FPRFX ## Free(PQT *queue);\417void FPRFX ## Destroy(PQT *queue);\418size_t FPRFX ## Length(PQT *queue);\419int FPRFX ## Insert(PQT *queue, VT node, KT key);\420int FPRFX ## Delete(PQT *queue, VT node);\421void FPRFX ## Update(PQT *queue, VT node, KT newkey);\422VT FPRFX ## GetTop(PQT *queue);\423VT FPRFX ## SeeTopVal(PQT *queue);\424KT FPRFX ## SeeTopKey(PQT *queue);\425KT FPRFX ## SeeKey(PQT *queue, VT node);\426VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts);\427int FPRFX ## CheckHeap(PQT *queue);\428429430/* This is how these macros are used431GK_MKPQUEUE(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX)432GK_MKPQUEUE_PROTO(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t)433*/434435436#endif437438439