1 /* GTS - Library for the manipulation of triangulated surfaces
2 * Copyright (C) 1999 Stéphane Popinet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 #define PARENT(i) ((i) >= 2 ? (i)/2 : 0)
24 #define LEFT_CHILD(i) (2*(i))
25 #define RIGHT_CHILD(i) (2*(i) + 1)
30 * @key_func: a #GtsKeyFunc or %NULL.
31 * @data: user data to be passed to @key_func.
33 * Returns: a new #GtsEHeap using @key_func as key.
35 GtsEHeap
* gts_eheap_new (GtsKeyFunc key_func
,
40 heap
= g_malloc (sizeof(GtsEHeap
));
41 heap
->elts
= g_ptr_array_new ();
42 heap
->func
= key_func
;
45 heap
->randomized
= FALSE
;
49 static void sift_up (GtsEHeap
* heap
, guint i
)
51 GtsEHeapPair
* parent
, * child
;
53 gpointer
* pdata
= heap
->elts
->pdata
;
58 while ((p
= PARENT (i
))) {
59 parent
= pdata
[p
- 1];
60 if (parent
->key
> key
||
61 (heap
->randomized
&& parent
->key
== key
&& rand () < RAND_MAX
/2)) {
63 pdata
[i
- 1] = parent
;
76 * @p: a pointer to add to the heap.
78 * Inserts a new element @p in the heap.
80 * Returns: a #GtsEHeapPair describing the position of the element in the heap.
81 * This pointer is necessary for gts_eheap_remove() and
82 * gts_eheap_decrease_key().
84 GtsEHeapPair
* gts_eheap_insert (GtsEHeap
* heap
, gpointer p
)
89 g_return_val_if_fail (heap
!= NULL
, NULL
);
90 g_return_val_if_fail (heap
->func
!= NULL
, NULL
);
93 pair
= g_malloc (sizeof (GtsEHeapPair
));
94 g_ptr_array_add (elts
, pair
);
96 pair
->pos
= elts
->len
;
97 pair
->key
= (*heap
->func
) (p
, heap
->data
);
99 sift_up (heap
, elts
->len
);
104 * gts_eheap_insert_with_key:
105 * @heap: a #GtsEHeap.
106 * @p: a pointer to add to the heap.
107 * @key: the value of the key associated to @p.
109 * Inserts a new element @p in the heap.
111 * Returns: a #GtsEHeapPair describing the position of the element in the heap.
112 * This pointer is necessary for gts_eheap_remove() and
113 * gts_eheap_decrease_key().
115 GtsEHeapPair
* gts_eheap_insert_with_key (GtsEHeap
* heap
,
122 g_return_val_if_fail (heap
!= NULL
, NULL
);
125 pair
= g_malloc (sizeof (GtsEHeapPair
));
126 g_ptr_array_add (elts
, pair
);
128 pair
->pos
= elts
->len
;
131 sift_up (heap
, elts
->len
);
135 static void sift_down (GtsEHeap
* heap
, guint i
)
137 GtsEHeapPair
* left_child
, * right_child
, * child
, * parent
;
139 gpointer
* pdata
= heap
->elts
->pdata
;
140 guint len
= heap
->elts
->len
;
144 rc
= RIGHT_CHILD (i
);
145 left_child
= lc
<= len
? pdata
[lc
- 1] : NULL
;
146 right_child
= rc
<= len
? pdata
[rc
- 1] : NULL
;
148 parent
= pdata
[i
- 1];
150 while (left_child
!= NULL
) {
151 if (right_child
== NULL
|| left_child
->key
< right_child
->key
) {
159 if (key
> child
->key
) {
160 pdata
[i
- 1] = child
;
162 pdata
[c
- 1] = parent
;
166 rc
= RIGHT_CHILD (i
);
167 left_child
= lc
<= len
? pdata
[lc
- 1] : NULL
;
168 right_child
= rc
<= len
? pdata
[rc
- 1] : NULL
;
176 * gts_eheap_remove_top:
177 * @heap: a #GtsEHeap.
178 * @key: a pointer on a gdouble or %NULL.
180 * Removes the element at the top of the heap and optionally (if @key is not
181 * %NULL) returns the value of its key.
183 * Returns: the element at the top of the heap.
185 gpointer
gts_eheap_remove_top (GtsEHeap
* heap
, gdouble
* key
)
192 g_return_val_if_fail (heap
!= NULL
, NULL
);
200 pair
= g_ptr_array_remove_index (elts
, 0);
208 pair
= elts
->pdata
[0];
213 pair
= g_ptr_array_remove_index (elts
, len
- 1);
214 elts
->pdata
[0] = pair
;
222 * @heap: a #GtsEHeap.
223 * @key: a pointer on a gdouble or %NULL.
225 * Returns: the element at the top of the heap and optionally (if @key is not
228 gpointer
gts_eheap_top (GtsEHeap
* heap
, gdouble
* key
)
233 g_return_val_if_fail (heap
!= NULL
, NULL
);
240 pair
= elts
->pdata
[0];
248 * @heap: a #GtsEHeap.
250 * Free all the memory allocated for @heap.
252 void gts_eheap_destroy (GtsEHeap
* heap
)
256 g_return_if_fail (heap
!= NULL
);
258 for (i
= 0; i
< heap
->elts
->len
; i
++)
259 g_free (heap
->elts
->pdata
[i
]);
260 g_ptr_array_free (heap
->elts
, TRUE
);
266 * @heap: a #GtsEHeap.
268 * If @heap has been frozen previously using gts_eheap_freeze(), reorder it
269 * in O(n) time and unfreeze it.
271 void gts_eheap_thaw (GtsEHeap
* heap
)
275 g_return_if_fail (heap
!= NULL
);
280 for (i
= heap
->elts
->len
/2; i
> 0; i
--)
283 heap
->frozen
= FALSE
;
288 * @heap: a #GtsEHeap.
289 * @func: the function to call for each element in the heap.
290 * @data: to pass to @func.
292 void gts_eheap_foreach (GtsEHeap
* heap
,
299 g_return_if_fail (heap
!= NULL
);
300 g_return_if_fail (func
!= NULL
);
303 for (i
= 0; i
< elts
->len
; i
++)
304 (*func
) (((GtsEHeapPair
*) elts
->pdata
[i
])->data
, data
);
309 * @heap: a #GtsEHeap.
310 * @p: a #GtsEHeapPair.
312 * Removes element corresponding to @p from @heap in O(log n).
314 * Returns: the element just removed from @heap.
316 gpointer
gts_eheap_remove (GtsEHeap
* heap
, GtsEHeapPair
* p
)
318 GtsEHeapPair
** pdata
;
319 GtsEHeapPair
* parent
;
323 g_return_val_if_fail (heap
!= NULL
, NULL
);
324 g_return_val_if_fail (p
!= NULL
, NULL
);
326 pdata
= (GtsEHeapPair
**)heap
->elts
->pdata
;
330 g_return_val_if_fail (i
> 0 && i
<= heap
->elts
->len
, NULL
);
331 g_return_val_if_fail (p
== pdata
[i
- 1], NULL
);
333 /* move element to the top */
334 while ((par
= PARENT (i
))) {
335 parent
= pdata
[par
- 1];
337 pdata
[i
- 1] = parent
;
343 gts_eheap_remove_top (heap
, NULL
);
349 * gts_eheap_decrease_key:
350 * @heap: a #GtsEHeap.
351 * @p: a #GtsEHeapPair.
352 * @new_key: the new value of the key for this element. Must be smaller than
355 * Decreases the value of the key of the element at position @p.
357 void gts_eheap_decrease_key (GtsEHeap
* heap
,
363 g_return_if_fail (heap
!= NULL
);
364 g_return_if_fail (p
!= NULL
);
367 g_return_if_fail (i
> 0 && i
<= heap
->elts
->len
);
368 g_return_if_fail (p
== heap
->elts
->pdata
[i
- 1]);
370 g_return_if_fail (new_key
<= p
->key
);
379 * @heap: a #GtsEHeap.
381 * Freezes the heap. Any subsequent operation will not preserve the heap
382 * property. Used in conjunction with gts_eheap_insert() and gts_eheap_thaw()
383 * to create a heap in O(n) time.
385 void gts_eheap_freeze (GtsEHeap
* heap
)
387 g_return_if_fail (heap
!= NULL
);
394 * @heap: a #GtsEHeap.
396 * Returns: the number of items in @heap.
398 guint
gts_eheap_size (GtsEHeap
* heap
)
400 g_return_val_if_fail (heap
!= NULL
, 0);
402 return heap
->elts
->len
;
407 * @heap: a #GtsEHeap.
409 * Updates the key of each element of @heap and reorders it.
411 void gts_eheap_update (GtsEHeap
* heap
)
414 GtsEHeapPair
** pairs
;
418 g_return_if_fail (heap
!= NULL
);
419 g_return_if_fail (heap
->func
!= NULL
);
423 len
= heap
->elts
->len
;
424 pairs
= (GtsEHeapPair
**) heap
->elts
->pdata
;
428 for (i
= 0; i
< len
; i
++) {
429 GtsEHeapPair
* pair
= pairs
[i
];
430 pair
->key
= (*func
) (pair
->data
, data
);
433 gts_eheap_thaw (heap
);
438 * @heap: a #GtsEHeap.
439 * @p: a pointer to be tested;
441 * Returns: the value of the key for pointer @p.
443 gdouble
gts_eheap_key (GtsEHeap
* heap
, gpointer p
)
445 g_return_val_if_fail (heap
!= NULL
, 0.);
446 g_return_val_if_fail (heap
->func
!= NULL
, 0.);
448 return (* heap
->func
) (p
, heap
->data
);
452 * gts_eheap_randomized:
453 * @heap: a #GtsEHeap.
454 * @randomized: whether @heap should be randomized.
456 void gts_eheap_randomized (GtsEHeap
* heap
, gboolean randomized
)
458 g_return_if_fail (heap
!= NULL
);
460 heap
->randomized
= randomized
;