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)
35 * @compare_func: a GCompareFunc.
37 * Returns: a new #GtsHeap using @compare_func as a sorting function.
39 GtsHeap
* gts_heap_new (GCompareFunc compare_func
)
43 g_return_val_if_fail (compare_func
!= NULL
, NULL
);
45 heap
= g_malloc (sizeof(GtsHeap
));
46 heap
->elts
= g_ptr_array_new ();
47 heap
->func
= compare_func
;
52 static void sift_up (GtsHeap
* heap
, guint i
)
54 gpointer parent
, child
;
56 gpointer
* pdata
= heap
->elts
->pdata
;
57 GCompareFunc func
= heap
->func
;
60 while ((p
= PARENT (i
))) {
61 parent
= pdata
[p
- 1];
62 if ((*func
) (parent
, child
) > 0) {
64 pdata
[i
- 1] = parent
;
75 * @p: a pointer to add to the heap.
77 * Inserts a new element @p in the heap.
79 void gts_heap_insert (GtsHeap
* heap
, gpointer p
)
81 g_return_if_fail (heap
!= NULL
);
83 g_ptr_array_add (heap
->elts
, p
);
85 sift_up (heap
, heap
->elts
->len
);
88 static void sift_down (GtsHeap
* heap
, guint i
)
90 gpointer left_child
, right_child
, child
, parent
;
92 gpointer
* pdata
= heap
->elts
->pdata
;
93 guint len
= heap
->elts
->len
;
94 GCompareFunc func
= heap
->func
;
98 left_child
= lc
<= len
? pdata
[lc
- 1] : NULL
;
99 right_child
= rc
<= len
? pdata
[rc
- 1] : NULL
;
101 parent
= pdata
[i
- 1];
102 while (left_child
!= NULL
) {
103 if (right_child
== NULL
||
104 (*func
) (left_child
, right_child
) < 0) {
112 if ((*func
) (parent
, child
) > 0) {
113 pdata
[i
- 1] = child
;
114 pdata
[c
- 1] = parent
;
117 rc
= RIGHT_CHILD (i
);
118 left_child
= lc
<= len
? pdata
[lc
- 1] : NULL
;
119 right_child
= rc
<= len
? pdata
[rc
- 1] : NULL
;
127 * gts_heap_remove_top:
130 * Removes the element at the top of the heap.
132 * Returns: the element at the top of the heap.
134 gpointer
gts_heap_remove_top (GtsHeap
* heap
)
140 g_return_val_if_fail (heap
!= NULL
, NULL
);
142 elts
= heap
->elts
; len
= elts
->len
;
147 return g_ptr_array_remove_index (elts
, 0);
149 root
= elts
->pdata
[0];
150 elts
->pdata
[0] = g_ptr_array_remove_index (elts
, len
- 1);
159 * Returns: the element at the top of the heap.
161 gpointer
gts_heap_top (GtsHeap
* heap
)
166 g_return_val_if_fail (heap
!= NULL
, NULL
);
172 return elts
->pdata
[0];
179 * Free all the memory allocated for @heap.
181 void gts_heap_destroy (GtsHeap
* heap
)
183 g_return_if_fail (heap
!= NULL
);
185 g_ptr_array_free (heap
->elts
, TRUE
);
193 * If @heap has been frozen previously using gts_heap_freeze(), reorder it
194 * in O(n) time and unfreeze it.
196 void gts_heap_thaw (GtsHeap
* heap
)
200 g_return_if_fail (heap
!= NULL
);
205 for (i
= heap
->elts
->len
/2; i
> 0; i
--)
208 heap
->frozen
= FALSE
;
214 * @func: the function to call for each element in the heap.
215 * @user_data: to pass to @func.
217 void gts_heap_foreach (GtsHeap
* heap
,
224 g_return_if_fail (heap
!= NULL
);
225 g_return_if_fail (func
!= NULL
);
228 for (i
= 0; i
< elts
->len
; i
++)
229 (*func
) (elts
->pdata
[i
], user_data
);
236 * Freezes the heap. Any subsequent operation will not preserve the heap
237 * property. Used in conjunction with gts_heap_insert() and gts_heap_thaw()
238 * to create a heap in O(n) time.
240 void gts_heap_freeze (GtsHeap
* heap
)
242 g_return_if_fail (heap
!= NULL
);
251 * Returns: the number of items in @heap.
253 guint
gts_heap_size (GtsHeap
* heap
)
255 g_return_val_if_fail (heap
!= NULL
, 0);
257 return heap
->elts
->len
;