pcb 4.1.1
An interactive printed circuit board layout editor.

eheap.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 
00035 GtsEHeap * gts_eheap_new (GtsKeyFunc key_func,
00036                           gpointer data)
00037 {
00038   GtsEHeap * heap;
00039 
00040   heap = g_malloc (sizeof(GtsEHeap));
00041   heap->elts = g_ptr_array_new ();
00042   heap->func = key_func;
00043   heap->data = data;
00044   heap->frozen = FALSE;
00045   heap->randomized = FALSE;
00046   return heap;
00047 }
00048 
00049 static void sift_up (GtsEHeap * heap, guint i)
00050 {
00051   GtsEHeapPair * parent, * child;
00052   guint p;
00053   gpointer * pdata = heap->elts->pdata;
00054   gdouble key;
00055 
00056   child = pdata[i - 1];
00057   key = child->key;
00058   while ((p = PARENT (i))) {
00059     parent = pdata[p - 1];
00060     if (parent->key > key ||
00061         (heap->randomized && parent->key == key && rand () < RAND_MAX/2)) {
00062       pdata[p - 1] = child;
00063       pdata[i - 1] = parent;
00064       child->pos = p;
00065       parent->pos = i;
00066       i = p;
00067     }
00068     else
00069       i = 0;
00070   }
00071 }
00072 
00084 GtsEHeapPair * gts_eheap_insert (GtsEHeap * heap, gpointer p)
00085 {
00086   GtsEHeapPair * pair;
00087   GPtrArray * elts;
00088 
00089   g_return_val_if_fail (heap != NULL, NULL);
00090   g_return_val_if_fail (heap->func != NULL, NULL);
00091 
00092   elts = heap->elts;
00093   pair = g_malloc (sizeof (GtsEHeapPair));
00094   g_ptr_array_add (elts, pair);
00095   pair->data = p;
00096   pair->pos = elts->len;
00097   pair->key = (*heap->func) (p, heap->data);
00098   if (!heap->frozen)
00099     sift_up (heap, elts->len);
00100   return pair;
00101 }
00102 
00115 GtsEHeapPair * gts_eheap_insert_with_key (GtsEHeap * heap, 
00116                                           gpointer p, 
00117                                           gdouble key)
00118 {
00119   GtsEHeapPair * pair;
00120   GPtrArray * elts;
00121 
00122   g_return_val_if_fail (heap != NULL, NULL);
00123 
00124   elts = heap->elts;
00125   pair = g_malloc (sizeof (GtsEHeapPair));
00126   g_ptr_array_add (elts, pair);
00127   pair->data = p;
00128   pair->pos = elts->len;
00129   pair->key = key;
00130   if (!heap->frozen)
00131     sift_up (heap, elts->len);
00132   return pair;
00133 }
00134 
00135 static void sift_down (GtsEHeap * heap, guint i)
00136 {
00137   GtsEHeapPair * left_child, * right_child, * child, * parent;
00138   guint lc, rc, c;
00139   gpointer * pdata = heap->elts->pdata;
00140   guint len = heap->elts->len;
00141   gdouble key;
00142 
00143   lc = LEFT_CHILD (i);
00144   rc = RIGHT_CHILD (i);
00145   left_child = lc <= len ? pdata[lc - 1] : NULL;
00146   right_child = rc <= len ? pdata[rc - 1] : NULL;
00147 
00148   parent = pdata[i - 1];
00149   key = parent->key;
00150   while (left_child != NULL) {
00151     if (right_child == NULL || left_child->key  < right_child->key) {
00152       child = left_child;
00153       c = lc;
00154     }
00155     else {
00156       child = right_child;
00157       c = rc;
00158     }
00159     if (key > child->key) {
00160       pdata[i - 1] = child;
00161       child->pos = i;
00162       pdata[c - 1] = parent;
00163       parent->pos = c;
00164       i = c;
00165       lc = LEFT_CHILD (i);
00166       rc = RIGHT_CHILD (i);
00167       left_child = lc <= len ? pdata[lc - 1] : NULL;
00168       right_child = rc <= len ? pdata[rc - 1] : NULL;      
00169     }
00170     else
00171       left_child = NULL;
00172   }
00173 }
00174 
00185 gpointer gts_eheap_remove_top (GtsEHeap * heap, gdouble * key)
00186 {
00187   gpointer root;
00188   GPtrArray * elts;
00189   guint len;
00190   GtsEHeapPair * pair;
00191 
00192   g_return_val_if_fail (heap != NULL, NULL);
00193 
00194   elts = heap->elts; 
00195   len = elts->len;
00196 
00197   if (len == 0)
00198     return NULL;
00199   if (len == 1) {
00200     pair = g_ptr_array_remove_index (elts, 0);
00201     root = pair->data;
00202     if (key) 
00203       *key = pair->key;
00204     g_free (pair);
00205     return root;
00206   }
00207 
00208   pair = elts->pdata[0];
00209   root = pair->data;
00210   if (key) 
00211     *key = pair->key;
00212   g_free (pair);
00213   pair = g_ptr_array_remove_index (elts, len - 1);
00214   elts->pdata[0] = pair;
00215   pair->pos = 1;
00216   sift_down (heap, 1);
00217   return root;
00218 }
00219 
00228 gpointer gts_eheap_top (GtsEHeap * heap, gdouble * key)
00229 {
00230   GtsEHeapPair * pair;
00231   GPtrArray * elts;
00232 
00233   g_return_val_if_fail (heap != NULL, NULL);
00234 
00235   elts = heap->elts;
00236 
00237   if (elts->len == 0)
00238     return NULL;
00239 
00240   pair = elts->pdata[0];
00241   if (key)
00242     *key = pair->key;
00243   return pair->data;
00244 }
00245 
00252 void gts_eheap_destroy (GtsEHeap * heap)
00253 {
00254   guint i;
00255 
00256   g_return_if_fail (heap != NULL);
00257 
00258   for (i = 0; i < heap->elts->len; i++)
00259     g_free (heap->elts->pdata[i]);
00260   g_ptr_array_free (heap->elts, TRUE);
00261   g_free (heap);
00262 }
00263 
00271 void gts_eheap_thaw (GtsEHeap * heap)
00272 {
00273   guint i;
00274   
00275   g_return_if_fail (heap != NULL);
00276 
00277   if (!heap->frozen)
00278     return;
00279 
00280   for (i = heap->elts->len/2; i > 0; i--)
00281     sift_down (heap, i);
00282 
00283   heap->frozen = FALSE;
00284 }
00285 
00292 void gts_eheap_foreach (GtsEHeap * heap, 
00293                         GFunc func,
00294                         gpointer data)
00295 {
00296   guint i;
00297   GPtrArray * elts;
00298   
00299   g_return_if_fail (heap != NULL);
00300   g_return_if_fail (func != NULL);
00301 
00302   elts = heap->elts;
00303   for (i = 0; i < elts->len; i++)
00304     (*func) (((GtsEHeapPair *) elts->pdata[i])->data, data);
00305 }
00306 
00316 gpointer gts_eheap_remove (GtsEHeap * heap, GtsEHeapPair * p)
00317 {
00318   GtsEHeapPair ** pdata;
00319   GtsEHeapPair * parent;
00320   guint i, par;
00321   gpointer data;
00322 
00323   g_return_val_if_fail (heap != NULL, NULL);
00324   g_return_val_if_fail (p != NULL, NULL);
00325 
00326   pdata = (GtsEHeapPair **)heap->elts->pdata;
00327   i = p->pos;
00328   data = p->data;
00329 
00330   g_return_val_if_fail (i > 0 && i <= heap->elts->len, NULL);
00331   g_return_val_if_fail (p == pdata[i - 1], NULL);
00332 
00333   /* move element to the top */
00334   while ((par = PARENT (i))) {
00335     parent = pdata[par - 1];
00336     pdata[par - 1] = p;
00337     pdata[i - 1] = parent;
00338     p->pos = par;
00339     parent->pos = i;
00340     i = par;
00341   }
00342 
00343   gts_eheap_remove_top (heap, NULL);
00344 
00345   return data;
00346 }
00347 
00357 void gts_eheap_decrease_key (GtsEHeap * heap, 
00358                              GtsEHeapPair * p,
00359                              gdouble new_key)
00360 {
00361   guint i;
00362 
00363   g_return_if_fail (heap != NULL);
00364   g_return_if_fail (p != NULL);
00365 
00366   i = p->pos;
00367   g_return_if_fail (i > 0 && i <= heap->elts->len);
00368   g_return_if_fail (p == heap->elts->pdata[i - 1]);
00369 
00370   g_return_if_fail (new_key <= p->key);
00371 
00372   p->key = new_key;
00373   if (!heap->frozen)
00374     sift_up (heap, i);
00375 }
00376 
00385 void gts_eheap_freeze (GtsEHeap * heap)
00386 {
00387   g_return_if_fail (heap != NULL);
00388 
00389   heap->frozen = TRUE;
00390 }
00391 
00398 guint gts_eheap_size (GtsEHeap * heap)
00399 {
00400   g_return_val_if_fail (heap != NULL, 0);
00401 
00402   return heap->elts->len;
00403 }
00404 
00411 void gts_eheap_update (GtsEHeap * heap)
00412 {
00413   guint i, len;
00414   GtsEHeapPair ** pairs;
00415   gpointer data;
00416   GtsKeyFunc func;
00417 
00418   g_return_if_fail (heap != NULL);
00419   g_return_if_fail (heap->func != NULL);
00420 
00421   heap->frozen = TRUE;
00422 
00423   len = heap->elts->len;
00424   pairs = (GtsEHeapPair **) heap->elts->pdata;
00425   data = heap->data;
00426   func = heap->func;
00427 
00428   for (i = 0; i < len; i++) {
00429     GtsEHeapPair * pair = pairs[i];
00430     pair->key = (*func) (pair->data, data);
00431   }
00432   
00433   gts_eheap_thaw (heap);
00434 }
00435 
00443 gdouble gts_eheap_key (GtsEHeap * heap, gpointer p)
00444 {
00445   g_return_val_if_fail (heap != NULL, 0.);
00446   g_return_val_if_fail (heap->func != NULL, 0.);
00447 
00448   return (* heap->func) (p, heap->data);
00449 }
00450 
00456 void gts_eheap_randomized (GtsEHeap * heap, gboolean randomized)
00457 {
00458   g_return_if_fail (heap != NULL);
00459 
00460   heap->randomized = randomized;
00461 }