pcb 4.1.1
An interactive printed circuit board layout editor.

gts/heap.c

Go to the documentation of this file.
00001 /* GTS - Library for the manipulation of triangulated surfaces
00002  * Copyright (C) 1999 Stéphane Popinet
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include <stdlib.h>
00021 #include "gts.h"
00022 
00023 #define PARENT(i) ((i) >= 2 ? (i)/2 : 0)
00024 #define LEFT_CHILD(i) (2*(i))
00025 #define RIGHT_CHILD(i) (2*(i) + 1)
00026 
00027 struct _GtsHeap {
00028   GPtrArray * elts;
00029   GCompareFunc func;
00030   gboolean frozen;
00031 };
00032 
00039 GtsHeap * gts_heap_new (GCompareFunc compare_func)
00040 {
00041   GtsHeap * heap;
00042 
00043   g_return_val_if_fail (compare_func != NULL, NULL);
00044   
00045   heap = g_malloc (sizeof(GtsHeap));
00046   heap->elts = g_ptr_array_new ();
00047   heap->func = compare_func;
00048   heap->frozen = FALSE;
00049   return heap;
00050 }
00051 
00052 static void sift_up (GtsHeap * heap, guint i)
00053 {
00054   gpointer parent, child;
00055   guint p;
00056   gpointer * pdata = heap->elts->pdata;
00057   GCompareFunc func = heap->func;
00058 
00059   child = pdata[i - 1];
00060   while ((p = PARENT (i))) {
00061     parent = pdata[p - 1];
00062     if ((*func) (parent, child) > 0) {
00063       pdata[p - 1] = child;
00064       pdata[i - 1] = parent;
00065       i = p;
00066     }
00067     else
00068       i = 0;
00069   }
00070 }
00071 
00079 void gts_heap_insert (GtsHeap * heap, gpointer p)
00080 {
00081   g_return_if_fail (heap != NULL);
00082 
00083   g_ptr_array_add (heap->elts, p);
00084   if (!heap->frozen)
00085     sift_up (heap, heap->elts->len);
00086 }
00087 
00088 static void sift_down (GtsHeap * heap, guint i)
00089 {
00090   gpointer left_child, right_child, child, parent;
00091   guint lc, rc, c;
00092   gpointer * pdata = heap->elts->pdata;
00093   guint len = heap->elts->len;
00094   GCompareFunc func = heap->func;
00095 
00096   lc = LEFT_CHILD (i);
00097   rc = RIGHT_CHILD (i);
00098   left_child = lc <= len ? pdata[lc - 1] : NULL;
00099   right_child = rc <= len ? pdata[rc - 1] : NULL;
00100 
00101   parent = pdata[i - 1];
00102   while (left_child != NULL) {
00103     if (right_child == NULL ||
00104         (*func) (left_child, right_child) < 0) {
00105       child = left_child;
00106       c = lc;
00107     }
00108     else {
00109       child = right_child;
00110       c = rc;
00111     }
00112     if ((*func) (parent, child) > 0) {
00113       pdata[i - 1] = child;
00114       pdata[c - 1] = parent;
00115       i = c;
00116       lc = LEFT_CHILD (i);
00117       rc = RIGHT_CHILD (i);
00118       left_child = lc <= len ? pdata[lc - 1] : NULL;
00119       right_child = rc <= len ? pdata[rc - 1] : NULL;      
00120     }
00121     else
00122       left_child = NULL;
00123   }
00124 }
00125 
00134 gpointer gts_heap_remove_top (GtsHeap * heap)
00135 {
00136   gpointer root;
00137   GPtrArray * elts;
00138   guint len;
00139 
00140   g_return_val_if_fail (heap != NULL, NULL);
00141 
00142   elts = heap->elts; len = elts->len;
00143 
00144   if (len == 0)
00145     return NULL;
00146   if (len == 1)
00147     return g_ptr_array_remove_index (elts, 0);
00148 
00149   root = elts->pdata[0];
00150   elts->pdata[0] = g_ptr_array_remove_index (elts, len - 1);
00151   sift_down (heap, 1);
00152   return root;
00153 }
00154 
00161 gpointer gts_heap_top (GtsHeap * heap)
00162 {
00163   GPtrArray * elts;
00164   guint len;
00165 
00166   g_return_val_if_fail (heap != NULL, NULL);
00167 
00168   elts = heap->elts; 
00169   len = elts->len;
00170   if (len == 0)
00171     return NULL;
00172   return elts->pdata[0];
00173 }
00174 
00181 void gts_heap_destroy (GtsHeap * heap)
00182 {
00183   g_return_if_fail (heap != NULL);
00184 
00185   g_ptr_array_free (heap->elts, TRUE);
00186   g_free (heap);
00187 }
00188 
00196 void gts_heap_thaw (GtsHeap * heap)
00197 {
00198   guint i;
00199   
00200   g_return_if_fail (heap != NULL);
00201 
00202   if (!heap->frozen)
00203     return;
00204 
00205   for (i = heap->elts->len/2; i > 0; i--)
00206     sift_down (heap, i);
00207 
00208   heap->frozen = FALSE;
00209 }
00210 
00217 void gts_heap_foreach (GtsHeap * heap, 
00218                        GFunc func,
00219                        gpointer user_data)
00220 {
00221   guint i;
00222   GPtrArray * elts;
00223   
00224   g_return_if_fail (heap != NULL);
00225   g_return_if_fail (func != NULL);
00226 
00227   elts = heap->elts;
00228   for (i = 0; i < elts->len; i++)
00229     (*func) (elts->pdata[i], user_data);
00230 }
00231 
00240 void gts_heap_freeze (GtsHeap * heap)
00241 {
00242   g_return_if_fail (heap != NULL);
00243 
00244   heap->frozen = TRUE;
00245 }
00246 
00253 guint gts_heap_size (GtsHeap * heap)
00254 {
00255   g_return_val_if_fail (heap != NULL, 0);
00256 
00257   return heap->elts->len;
00258 }