priorityq.c revision e7980a23
1f220fa62Smrg/* 2f220fa62Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3f220fa62Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4f220fa62Smrg * 5f220fa62Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6f220fa62Smrg * copy of this software and associated documentation files (the "Software"), 7f220fa62Smrg * to deal in the Software without restriction, including without limitation 8f220fa62Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9f220fa62Smrg * and/or sell copies of the Software, and to permit persons to whom the 10f220fa62Smrg * Software is furnished to do so, subject to the following conditions: 11f220fa62Smrg * 12f220fa62Smrg * The above copyright notice including the dates of first publication and 13f220fa62Smrg * either this permission notice or a reference to 14f220fa62Smrg * http://oss.sgi.com/projects/FreeB/ 15f220fa62Smrg * shall be included in all copies or substantial portions of the Software. 16f220fa62Smrg * 17f220fa62Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18f220fa62Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19f220fa62Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20f220fa62Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21f220fa62Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22f220fa62Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23f220fa62Smrg * SOFTWARE. 24f220fa62Smrg * 25f220fa62Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26f220fa62Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27f220fa62Smrg * other dealings in this Software without prior written authorization from 28f220fa62Smrg * Silicon Graphics, Inc. 29f220fa62Smrg */ 30f220fa62Smrg/* 31f220fa62Smrg** Author: Eric Veach, July 1994. 32f220fa62Smrg** 33f220fa62Smrg*/ 34f220fa62Smrg 35f220fa62Smrg#include "gluos.h" 36f220fa62Smrg#include <stddef.h> 37f220fa62Smrg#include <assert.h> 38f220fa62Smrg#include <limits.h> /* LONG_MAX */ 39f220fa62Smrg#include "memalloc.h" 40f220fa62Smrg 41f220fa62Smrg/* Include all the code for the regular heap-based queue here. */ 42f220fa62Smrg 43f220fa62Smrg#include "priorityq-heap.c" 44f220fa62Smrg 45f220fa62Smrg/* Now redefine all the function names to map to their "Sort" versions. */ 46f220fa62Smrg 47f220fa62Smrg#include "priorityq-sort.h" 48f220fa62Smrg 49f220fa62Smrg/* really __gl_pqSortNewPriorityQ */ 50f220fa62SmrgPriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) 51f220fa62Smrg{ 52f220fa62Smrg PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); 53f220fa62Smrg if (pq == NULL) return NULL; 54f220fa62Smrg 55f220fa62Smrg pq->heap = __gl_pqHeapNewPriorityQ( leq ); 56f220fa62Smrg if (pq->heap == NULL) { 57f220fa62Smrg memFree(pq); 58f220fa62Smrg return NULL; 59f220fa62Smrg } 60f220fa62Smrg 61f220fa62Smrg pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) ); 62f220fa62Smrg if (pq->keys == NULL) { 63f220fa62Smrg __gl_pqHeapDeletePriorityQ(pq->heap); 64f220fa62Smrg memFree(pq); 65f220fa62Smrg return NULL; 66f220fa62Smrg } 67f220fa62Smrg 68e7980a23Smrg pq->order = NULL; 69f220fa62Smrg pq->size = 0; 70f220fa62Smrg pq->max = INIT_SIZE; 71f220fa62Smrg pq->initialized = FALSE; 72f220fa62Smrg pq->leq = leq; 73f220fa62Smrg return pq; 74f220fa62Smrg} 75f220fa62Smrg 76f220fa62Smrg/* really __gl_pqSortDeletePriorityQ */ 77f220fa62Smrgvoid pqDeletePriorityQ( PriorityQ *pq ) 78f220fa62Smrg{ 79f220fa62Smrg assert(pq != NULL); 80f220fa62Smrg if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap ); 81f220fa62Smrg if (pq->order != NULL) memFree( pq->order ); 82f220fa62Smrg if (pq->keys != NULL) memFree( pq->keys ); 83f220fa62Smrg memFree( pq ); 84f220fa62Smrg} 85f220fa62Smrg 86f220fa62Smrg 87f220fa62Smrg#define LT(x,y) (! LEQ(y,x)) 88f220fa62Smrg#define GT(x,y) (! LEQ(x,y)) 89f220fa62Smrg#define Swap(a,b) do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0) 90f220fa62Smrg 91f220fa62Smrg/* really __gl_pqSortInit */ 92f220fa62Smrgint pqInit( PriorityQ *pq ) 93f220fa62Smrg{ 94f220fa62Smrg PQkey **p, **r, **i, **j, *piv; 95f220fa62Smrg struct { PQkey **p, **r; } Stack[50], *top = Stack; 96f220fa62Smrg unsigned long seed = 2016473283; 97f220fa62Smrg 98f220fa62Smrg /* Create an array of indirect pointers to the keys, so that we 99f220fa62Smrg * the handles we have returned are still valid. 100f220fa62Smrg */ 101f220fa62Smrg/* 102f220fa62Smrg pq->order = (PQHeapKey **)memAlloc( (size_t) 103f220fa62Smrg (pq->size * sizeof(pq->order[0])) ); 104f220fa62Smrg*/ 105f220fa62Smrg pq->order = (PQHeapKey **)memAlloc( (size_t) 106f220fa62Smrg ((pq->size+1) * sizeof(pq->order[0])) ); 107f220fa62Smrg/* the previous line is a patch to compensate for the fact that IBM */ 108f220fa62Smrg/* machines return a null on a malloc of zero bytes (unlike SGI), */ 109f220fa62Smrg/* so we have to put in this defense to guard against a memory */ 110f220fa62Smrg/* fault four lines down. from fossum@austin.ibm.com. */ 111f220fa62Smrg if (pq->order == NULL) return 0; 112f220fa62Smrg 113f220fa62Smrg p = pq->order; 114f220fa62Smrg r = p + pq->size - 1; 115f220fa62Smrg for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) { 116f220fa62Smrg *i = piv; 117f220fa62Smrg } 118f220fa62Smrg 119f220fa62Smrg /* Sort the indirect pointers in descending order, 120f220fa62Smrg * using randomized Quicksort 121f220fa62Smrg */ 122f220fa62Smrg top->p = p; top->r = r; ++top; 123f220fa62Smrg while( --top >= Stack ) { 124f220fa62Smrg p = top->p; 125f220fa62Smrg r = top->r; 126f220fa62Smrg while( r > p + 10 ) { 127f220fa62Smrg seed = seed * 1539415821 + 1; 128f220fa62Smrg i = p + seed % (r - p + 1); 129f220fa62Smrg piv = *i; 130f220fa62Smrg *i = *p; 131f220fa62Smrg *p = piv; 132f220fa62Smrg i = p - 1; 133f220fa62Smrg j = r + 1; 134f220fa62Smrg do { 135f220fa62Smrg do { ++i; } while( GT( **i, *piv )); 136f220fa62Smrg do { --j; } while( LT( **j, *piv )); 137f220fa62Smrg Swap( i, j ); 138f220fa62Smrg } while( i < j ); 139f220fa62Smrg Swap( i, j ); /* Undo last swap */ 140f220fa62Smrg if( i - p < r - j ) { 141f220fa62Smrg top->p = j+1; top->r = r; ++top; 142f220fa62Smrg r = i-1; 143f220fa62Smrg } else { 144f220fa62Smrg top->p = p; top->r = i-1; ++top; 145f220fa62Smrg p = j+1; 146f220fa62Smrg } 147f220fa62Smrg } 148f220fa62Smrg /* Insertion sort small lists */ 149f220fa62Smrg for( i = p+1; i <= r; ++i ) { 150f220fa62Smrg piv = *i; 151f220fa62Smrg for( j = i; j > p && LT( **(j-1), *piv ); --j ) { 152f220fa62Smrg *j = *(j-1); 153f220fa62Smrg } 154f220fa62Smrg *j = piv; 155f220fa62Smrg } 156f220fa62Smrg } 157f220fa62Smrg pq->max = pq->size; 158f220fa62Smrg pq->initialized = TRUE; 159f220fa62Smrg __gl_pqHeapInit( pq->heap ); /* always succeeds */ 160f220fa62Smrg 161f220fa62Smrg#ifndef NDEBUG 162f220fa62Smrg p = pq->order; 163f220fa62Smrg r = p + pq->size - 1; 164f220fa62Smrg for( i = p; i < r; ++i ) { 165f220fa62Smrg assert( LEQ( **(i+1), **i )); 166f220fa62Smrg } 167f220fa62Smrg#endif 168f220fa62Smrg 169f220fa62Smrg return 1; 170f220fa62Smrg} 171f220fa62Smrg 172f220fa62Smrg/* really __gl_pqSortInsert */ 173f220fa62Smrg/* returns LONG_MAX iff out of memory */ 174f220fa62SmrgPQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) 175f220fa62Smrg{ 176f220fa62Smrg long curr; 177f220fa62Smrg 178f220fa62Smrg if( pq->initialized ) { 179f220fa62Smrg return __gl_pqHeapInsert( pq->heap, keyNew ); 180f220fa62Smrg } 181f220fa62Smrg curr = pq->size; 182f220fa62Smrg if( ++ pq->size >= pq->max ) { 183f220fa62Smrg PQkey *saveKey= pq->keys; 184f220fa62Smrg 185f220fa62Smrg /* If the heap overflows, double its size. */ 186f220fa62Smrg pq->max <<= 1; 187f220fa62Smrg pq->keys = (PQHeapKey *)memRealloc( pq->keys, 188f220fa62Smrg (size_t) 189f220fa62Smrg (pq->max * sizeof( pq->keys[0] ))); 190f220fa62Smrg if (pq->keys == NULL) { 191f220fa62Smrg pq->keys = saveKey; /* restore ptr to free upon return */ 192f220fa62Smrg return LONG_MAX; 193f220fa62Smrg } 194f220fa62Smrg } 195f220fa62Smrg assert(curr != LONG_MAX); 196f220fa62Smrg pq->keys[curr] = keyNew; 197f220fa62Smrg 198f220fa62Smrg /* Negative handles index the sorted array. */ 199f220fa62Smrg return -(curr+1); 200f220fa62Smrg} 201f220fa62Smrg 202f220fa62Smrg/* really __gl_pqSortExtractMin */ 203f220fa62SmrgPQkey pqExtractMin( PriorityQ *pq ) 204f220fa62Smrg{ 205f220fa62Smrg PQkey sortMin, heapMin; 206f220fa62Smrg 207f220fa62Smrg if( pq->size == 0 ) { 208f220fa62Smrg return __gl_pqHeapExtractMin( pq->heap ); 209f220fa62Smrg } 210f220fa62Smrg sortMin = *(pq->order[pq->size-1]); 211f220fa62Smrg if( ! __gl_pqHeapIsEmpty( pq->heap )) { 212f220fa62Smrg heapMin = __gl_pqHeapMinimum( pq->heap ); 213f220fa62Smrg if( LEQ( heapMin, sortMin )) { 214f220fa62Smrg return __gl_pqHeapExtractMin( pq->heap ); 215f220fa62Smrg } 216f220fa62Smrg } 217f220fa62Smrg do { 218f220fa62Smrg -- pq->size; 219f220fa62Smrg } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ); 220f220fa62Smrg return sortMin; 221f220fa62Smrg} 222f220fa62Smrg 223f220fa62Smrg/* really __gl_pqSortMinimum */ 224f220fa62SmrgPQkey pqMinimum( PriorityQ *pq ) 225f220fa62Smrg{ 226f220fa62Smrg PQkey sortMin, heapMin; 227f220fa62Smrg 228f220fa62Smrg if( pq->size == 0 ) { 229f220fa62Smrg return __gl_pqHeapMinimum( pq->heap ); 230f220fa62Smrg } 231f220fa62Smrg sortMin = *(pq->order[pq->size-1]); 232f220fa62Smrg if( ! __gl_pqHeapIsEmpty( pq->heap )) { 233f220fa62Smrg heapMin = __gl_pqHeapMinimum( pq->heap ); 234f220fa62Smrg if( LEQ( heapMin, sortMin )) { 235f220fa62Smrg return heapMin; 236f220fa62Smrg } 237f220fa62Smrg } 238f220fa62Smrg return sortMin; 239f220fa62Smrg} 240f220fa62Smrg 241f220fa62Smrg/* really __gl_pqSortIsEmpty */ 242f220fa62Smrgint pqIsEmpty( PriorityQ *pq ) 243f220fa62Smrg{ 244f220fa62Smrg return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap ); 245f220fa62Smrg} 246f220fa62Smrg 247f220fa62Smrg/* really __gl_pqSortDelete */ 248f220fa62Smrgvoid pqDelete( PriorityQ *pq, PQhandle curr ) 249f220fa62Smrg{ 250f220fa62Smrg if( curr >= 0 ) { 251f220fa62Smrg __gl_pqHeapDelete( pq->heap, curr ); 252f220fa62Smrg return; 253f220fa62Smrg } 254f220fa62Smrg curr = -(curr+1); 255f220fa62Smrg assert( curr < pq->max && pq->keys[curr] != NULL ); 256f220fa62Smrg 257f220fa62Smrg pq->keys[curr] = NULL; 258f220fa62Smrg while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) { 259f220fa62Smrg -- pq->size; 260f220fa62Smrg } 261f220fa62Smrg} 262