heap.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 <grass/gis.h>
  39. #include <stdlib.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. int r, c;
  81. r = child_pnt->row;
  82. c = child_pnt->col;
  83. child = start;
  84. while (child > 1) {
  85. parent = GET_PARENT(child);
  86. /* child is smaller */
  87. if (cmp_costs(child_pnt, heap_index[parent])) {
  88. /* push parent point down */
  89. heap_index[child] = heap_index[parent];
  90. child = parent;
  91. }
  92. else
  93. /* no more sifting up, found new slot for child */
  94. break;
  95. }
  96. /* put point in new slot */
  97. if (child < start) {
  98. heap_index[child] = child_pnt;
  99. }
  100. return child;
  101. }
  102. struct cost *insert(double min_cost, int row, int col)
  103. {
  104. struct cost *new_cell;
  105. if (free_point) {
  106. new_cell = free_point;
  107. free_point = NULL;
  108. }
  109. else
  110. new_cell = (struct cost *)(G_malloc(sizeof(struct cost)));
  111. new_cell->min_cost = min_cost;
  112. new_cell->age = next_point;
  113. new_cell->row = row;
  114. new_cell->col = col;
  115. next_point++;
  116. heap_size++;
  117. if (heap_size >= heap_alloced) {
  118. heap_alloced += 1000;
  119. heap_index = (struct cost **) G_realloc((void *)heap_index, heap_alloced * sizeof(struct cost *));
  120. }
  121. heap_index[heap_size] = new_cell;
  122. sift_up(heap_size, new_cell);
  123. return (new_cell);
  124. }
  125. struct cost *get_lowest(void)
  126. {
  127. struct cost *next_cell;
  128. register long parent, child, childr, i;
  129. if (heap_size == 0)
  130. return NULL;
  131. next_cell = heap_index[1];
  132. heap_index[0] = next_cell;
  133. if (heap_size == 1) {
  134. heap_size--;
  135. heap_index[1] = NULL;
  136. return next_cell;
  137. }
  138. /* start with root */
  139. parent = 1;
  140. /* sift down: move hole back towards bottom of heap */
  141. while ((child = GET_CHILD(parent)) <= heap_size) {
  142. /* select smallest child */
  143. if (child < heap_size) {
  144. childr = child + 1;
  145. i = child + 3;
  146. while (childr < i && childr <= heap_size) {
  147. /* get smallest child */
  148. if (cmp_costs(heap_index[childr], heap_index[child])) {
  149. child = childr;
  150. }
  151. childr++;
  152. }
  153. }
  154. /* move hole down */
  155. heap_index[parent] = heap_index[child];
  156. parent = child;
  157. }
  158. /* hole is in lowest layer, move to heap end */
  159. if (parent < heap_size) {
  160. heap_index[parent] = heap_index[heap_size];
  161. /* sift up last swapped point, only necessary if hole moved to heap end */
  162. sift_up(parent, heap_index[parent]);
  163. }
  164. /* the actual drop */
  165. heap_size--;
  166. return next_cell;
  167. }
  168. int delete(struct cost *delete_cell)
  169. {
  170. if (free_point)
  171. G_free(delete_cell);
  172. else
  173. free_point = delete_cell;
  174. return 0;
  175. }