Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
4.7 KiB

  1. /*
  2. ** Copyright 1994, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. **
  17. ** Author: Eric Veach, July 1994.
  18. */
  19. #include <stddef.h>
  20. #include <assert.h>
  21. #ifdef NT
  22. #include "prq-heap.h"
  23. #else
  24. #include "priorityq-heap.h"
  25. #endif
  26. #include "memalloc.h"
  27. #define INIT_SIZE 32
  28. #define TRUE 1
  29. #define FALSE 0
  30. #ifdef DEBUG
  31. #define LEQ(x,y) (*pq->leq)(x,y)
  32. #else
  33. /* Violates modularity, but a little faster */
  34. #include "geom.h"
  35. #define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y)
  36. #endif
  37. PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
  38. {
  39. PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
  40. pq->size = 0;
  41. pq->max = INIT_SIZE;
  42. pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) );
  43. pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) );
  44. pq->initialized = FALSE;
  45. pq->freeList = 0;
  46. pq->leq = leq;
  47. pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */
  48. pq->handles[1].key = NULL;
  49. return pq;
  50. }
  51. void pqDeletePriorityQ( PriorityQ *pq )
  52. {
  53. memFree( pq->handles );
  54. memFree( pq->nodes );
  55. memFree( pq );
  56. }
  57. static void FloatDown( PriorityQ *pq, long curr )
  58. {
  59. PQnode *n = pq->nodes;
  60. PQhandleElem *h = pq->handles;
  61. PQhandle hCurr, hChild;
  62. long child;
  63. hCurr = n[curr].handle;
  64. for( ;; ) {
  65. child = curr << 1;
  66. if( child < pq->size && LEQ( h[n[child+1].handle].key,
  67. h[n[child].handle].key )) {
  68. ++child;
  69. }
  70. hChild = n[child].handle;
  71. if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) {
  72. n[curr].handle = hCurr;
  73. h[hCurr].node = curr;
  74. break;
  75. }
  76. n[curr].handle = hChild;
  77. h[hChild].node = curr;
  78. curr = child;
  79. }
  80. }
  81. static void FloatUp( PriorityQ *pq, long curr )
  82. {
  83. PQnode *n = pq->nodes;
  84. PQhandleElem *h = pq->handles;
  85. PQhandle hCurr, hParent;
  86. long parent;
  87. hCurr = n[curr].handle;
  88. for( ;; ) {
  89. parent = curr >> 1;
  90. hParent = n[parent].handle;
  91. if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) {
  92. n[curr].handle = hCurr;
  93. h[hCurr].node = curr;
  94. break;
  95. }
  96. n[curr].handle = hParent;
  97. h[hParent].node = curr;
  98. curr = parent;
  99. }
  100. }
  101. void pqInit( PriorityQ *pq )
  102. {
  103. long i;
  104. /* This method of building a heap is O(n), rather than O(n lg n). */
  105. for( i = pq->size; i >= 1; --i ) {
  106. FloatDown( pq, i );
  107. }
  108. pq->initialized = TRUE;
  109. }
  110. PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
  111. {
  112. long curr;
  113. PQhandle free;
  114. curr = ++ pq->size;
  115. if( curr > pq->max ) {
  116. /* If the heap overflows, double its size. */
  117. pq->max <<= 1;
  118. pq->nodes = (PQnode *)memRealloc( pq->nodes,
  119. (size_t)
  120. ((pq->max + 1) * sizeof( pq->nodes[0] )));
  121. pq->handles = (PQhandleElem *)memRealloc( pq->handles,
  122. (size_t)
  123. ((pq->max + 1) *
  124. sizeof( pq->handles[0] )));
  125. }
  126. if( pq->freeList == 0 ) {
  127. free = curr;
  128. } else {
  129. free = pq->freeList;
  130. pq->freeList = pq->handles[free].node;
  131. }
  132. pq->nodes[curr].handle = free;
  133. pq->handles[free].node = curr;
  134. pq->handles[free].key = keyNew;
  135. if( pq->initialized ) {
  136. FloatUp( pq, curr );
  137. }
  138. return free;
  139. }
  140. PQkey pqExtractMin( PriorityQ *pq )
  141. {
  142. PQnode *n = pq->nodes;
  143. PQhandleElem *h = pq->handles;
  144. PQhandle hMin = n[1].handle;
  145. PQkey min = h[hMin].key;
  146. if( pq->size > 0 ) {
  147. n[1].handle = n[pq->size].handle;
  148. h[n[1].handle].node = 1;
  149. h[hMin].key = NULL;
  150. h[hMin].node = pq->freeList;
  151. pq->freeList = hMin;
  152. if( -- pq->size > 0 ) {
  153. FloatDown( pq, 1 );
  154. }
  155. }
  156. return min;
  157. }
  158. void pqDelete( PriorityQ *pq, PQhandle hCurr )
  159. {
  160. PQnode *n = pq->nodes;
  161. PQhandleElem *h = pq->handles;
  162. long curr;
  163. assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL );
  164. curr = h[hCurr].node;
  165. n[curr].handle = n[pq->size].handle;
  166. h[n[curr].handle].node = curr;
  167. if( curr <= -- pq->size ) {
  168. if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) {
  169. FloatDown( pq, curr );
  170. } else {
  171. FloatUp( pq, curr );
  172. }
  173. }
  174. h[hCurr].key = NULL;
  175. h[hCurr].node = pq->freeList;
  176. pq->freeList = hCurr;
  177. }