heap.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /****************************************************************************
  2. *
  3. * MODULE: r.cost
  4. *
  5. * AUTHOR(S): Antony Awaida - IESL - M.I.T.
  6. * James Westervelt - CERL
  7. * Pierre de Mouveaux <pmx audiovu com>
  8. * Eric G. Miller <egm2 jps net>
  9. *
  10. * min heap by Markus Metz
  11. *
  12. * PURPOSE: Outputs a raster map layer showing the cumulative cost
  13. * of moving between different geographic locations on an
  14. * input raster map layer whose cell category values
  15. * represent cost.
  16. *
  17. * COPYRIGHT: (C) 2006-2009 by the GRASS Development Team
  18. *
  19. * This program is free software under the GNU General Public
  20. * License (>=v2). Read the file COPYING that comes with GRASS
  21. * for details.
  22. *
  23. ***************************************************************************/
  24. /* These routines manage the list of grid-cell candidates for
  25. * visiting to calculate distances to surrounding cells.
  26. * A min-heap approach is used. Components are
  27. * sorted first by distance then by the order in which they were added.
  28. *
  29. * insert ()
  30. * inserts a new row-col with its distance value into the heap
  31. *
  32. * delete()
  33. * deletes a row-col entry in the heap
  34. *
  35. * get_lowest()
  36. * retrieves the entry with the smallest distance value
  37. */
  38. #include <stdlib.h>
  39. #include <grass/gis.h>
  40. #include <grass/glocale.h>
  41. #include "cost.h"
  42. #define GET_PARENT(c) (((c) - 2) / 3 + 1)
  43. #define GET_CHILD(p) (((p) * 3) - 1)
  44. static long next_point = 0;
  45. static long heap_size = 0;
  46. static long heap_alloced = 0;
  47. static struct cost **heap_index, *free_point;
  48. int init_heap(void)
  49. {
  50. next_point = 0;
  51. heap_size = 0;
  52. heap_alloced = 1000;
  53. heap_index = (struct cost **) G_malloc(heap_alloced * sizeof(struct cost *));
  54. free_point = NULL;
  55. return 0;
  56. }
  57. int free_heap(void)
  58. {
  59. if (heap_alloced)
  60. G_free(heap_index);
  61. if (free_point)
  62. G_free(free_point);
  63. return 0;
  64. }
  65. /* compare two costs
  66. * return 1 if a < b else 0 */
  67. int cmp_costs(struct cost *a, struct cost *b)
  68. {
  69. if (a->min_cost < b->min_cost)
  70. return 1;
  71. else if (a->min_cost == b->min_cost) {
  72. if (a->age < b->age)
  73. return 1;
  74. }
  75. return 0;
  76. }
  77. long sift_up(long start, struct cost * child_pnt)
  78. {
  79. register long parent, child;
  80. child = start;
  81. while (child > 1) {
  82. parent = GET_PARENT(child);
  83. /* child is smaller */
  84. if (cmp_costs(child_pnt, heap_index[parent])) {
  85. /* push parent point down */
  86. heap_index[child] = heap_index[parent];
  87. child = parent;
  88. }
  89. else
  90. /* no more sifting up, found new slot for child */
  91. break;
  92. }
  93. /* put point in new slot */
  94. if (child < start) {
  95. heap_index[child] = child_pnt;
  96. }
  97. return child;
  98. }
  99. struct cost *insert(double min_cost, int row, int col)
  100. {
  101. struct cost *new_cell;
  102. if (free_point) {
  103. new_cell = free_point;
  104. free_point = NULL;
  105. }
  106. else
  107. new_cell = (struct cost *)(G_malloc(sizeof(struct cost)));
  108. new_cell->min_cost = min_cost;
  109. new_cell->age = next_point;
  110. new_cell->row = row;
  111. new_cell->col = col;
  112. next_point++;
  113. heap_size++;
  114. if (heap_size >= heap_alloced) {
  115. heap_alloced += 1000;
  116. heap_index = (struct cost **) G_realloc((void *)heap_index, heap_alloced * sizeof(struct cost *));
  117. }
  118. heap_index[heap_size] = new_cell;
  119. sift_up(heap_size, new_cell);
  120. return (new_cell);
  121. }
  122. struct cost *get_lowest(void)
  123. {
  124. struct cost *next_cell;
  125. register long parent, child, childr, i;
  126. if (heap_size == 0)
  127. return NULL;
  128. next_cell = heap_index[1];
  129. heap_index[0] = next_cell;
  130. if (heap_size == 1) {
  131. heap_size--;
  132. heap_index[1] = NULL;
  133. return next_cell;
  134. }
  135. /* start with root */
  136. parent = 1;
  137. /* sift down: move hole back towards bottom of heap */
  138. while ((child = GET_CHILD(parent)) <= heap_size) {
  139. /* select smallest child */
  140. if (child < heap_size) {
  141. childr = child + 1;
  142. i = child + 3;
  143. while (childr < i && childr <= heap_size) {
  144. /* get smallest child */
  145. if (cmp_costs(heap_index[childr], heap_index[child])) {
  146. child = childr;
  147. }
  148. childr++;
  149. }
  150. }
  151. /* move hole down */
  152. heap_index[parent] = heap_index[child];
  153. parent = child;
  154. }
  155. /* hole is in lowest layer, move to heap end */
  156. if (parent < heap_size) {
  157. heap_index[parent] = heap_index[heap_size];
  158. /* sift up last swapped point, only necessary if hole moved to heap end */
  159. sift_up(parent, heap_index[parent]);
  160. }
  161. /* the actual drop */
  162. heap_size--;
  163. return next_cell;
  164. }
  165. int delete(struct cost *delete_cell)
  166. {
  167. if (free_point)
  168. G_free(delete_cell);
  169. else
  170. free_point = delete_cell;
  171. return 0;
  172. }