Leptonica  1.77.0
Image processing and image analysis suite
heap.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
77 #include <string.h>
78 #include "allheaders.h"
79 
80 static const l_int32 MIN_BUFFER_SIZE = 20; /* n'importe quoi */
81 static const l_int32 INITIAL_BUFFER_ARRAYSIZE = 128; /* n'importe quoi */
82 
83 #define SWAP_ITEMS(i, j) { void *tempitem = lh->array[(i)]; \
84  lh->array[(i)] = lh->array[(j)]; \
85  lh->array[(j)] = tempitem; }
86 
87  /* Static function */
88 static l_int32 lheapExtendArray(L_HEAP *lh);
89 
90 
91 /*--------------------------------------------------------------------------*
92  * L_Heap create/destroy *
93  *--------------------------------------------------------------------------*/
101 L_HEAP *
102 lheapCreate(l_int32 nalloc,
103  l_int32 direction)
104 {
105 L_HEAP *lh;
106 
107  PROCNAME("lheapCreate");
108 
109  if (nalloc < MIN_BUFFER_SIZE)
110  nalloc = MIN_BUFFER_SIZE;
111 
112  /* Allocate ptr array and initialize counters. */
113  if ((lh = (L_HEAP *)LEPT_CALLOC(1, sizeof(L_HEAP))) == NULL)
114  return (L_HEAP *)ERROR_PTR("lh not made", procName, NULL);
115  if ((lh->array = (void **)LEPT_CALLOC(nalloc, sizeof(void *))) == NULL) {
116  lheapDestroy(&lh, FALSE);
117  return (L_HEAP *)ERROR_PTR("ptr array not made", procName, NULL);
118  }
119  lh->nalloc = nalloc;
120  lh->n = 0;
121  lh->direction = direction;
122  return lh;
123 }
124 
125 
144 void
146  l_int32 freeflag)
147 {
148 l_int32 i;
149 L_HEAP *lh;
150 
151  PROCNAME("lheapDestroy");
152 
153  if (plh == NULL) {
154  L_WARNING("ptr address is NULL\n", procName);
155  return;
156  }
157  if ((lh = *plh) == NULL)
158  return;
159 
160  if (freeflag) { /* free each struct in the array */
161  for (i = 0; i < lh->n; i++)
162  LEPT_FREE(lh->array[i]);
163  } else if (lh->n > 0) { /* freeflag == FALSE but elements exist on array */
164  L_WARNING("memory leak of %d items in lheap!\n", procName, lh->n);
165  }
166 
167  if (lh->array)
168  LEPT_FREE(lh->array);
169  LEPT_FREE(lh);
170  *plh = NULL;
171 
172  return;
173 }
174 
175 /*--------------------------------------------------------------------------*
176  * Accessors *
177  *--------------------------------------------------------------------------*/
185 l_ok
187  void *item)
188 {
189  PROCNAME("lheapAdd");
190 
191  if (!lh)
192  return ERROR_INT("lh not defined", procName, 1);
193  if (!item)
194  return ERROR_INT("item not defined", procName, 1);
195 
196  /* If necessary, expand the allocated array by a factor of 2 */
197  if (lh->n >= lh->nalloc)
198  lheapExtendArray(lh);
199 
200  /* Add the item */
201  lh->array[lh->n] = item;
202  lh->n++;
203 
204  /* Restore the heap */
205  lheapSwapUp(lh, lh->n - 1);
206  return 0;
207 }
208 
209 
216 static l_int32
218 {
219  PROCNAME("lheapExtendArray");
220 
221  if (!lh)
222  return ERROR_INT("lh not defined", procName, 1);
223 
224  if ((lh->array = (void **)reallocNew((void **)&lh->array,
225  sizeof(void *) * lh->nalloc,
226  2 * sizeof(void *) * lh->nalloc)) == NULL)
227  return ERROR_INT("new ptr array not returned", procName, 1);
228 
229  lh->nalloc = 2 * lh->nalloc;
230  return 0;
231 }
232 
233 
241 void *
243 {
244 void *item;
245 
246  PROCNAME("lheapRemove");
247 
248  if (!lh)
249  return (void *)ERROR_PTR("lh not defined", procName, NULL);
250 
251  if (lh->n == 0)
252  return NULL;
253 
254  item = lh->array[0];
255  lh->array[0] = lh->array[lh->n - 1]; /* move last to the head */
256  lh->array[lh->n - 1] = NULL; /* set ptr to null */
257  lh->n--;
258 
259  lheapSwapDown(lh); /* restore the heap */
260  return item;
261 }
262 
263 
270 l_int32
272 {
273  PROCNAME("lheapGetCount");
274 
275  if (!lh)
276  return ERROR_INT("lh not defined", procName, 0);
277 
278  return lh->n;
279 }
280 
281 
282 
283 /*--------------------------------------------------------------------------*
284  * Heap operations *
285  *--------------------------------------------------------------------------*/
303 l_ok
305  l_int32 index)
306 {
307 l_int32 ip; /* index to heap for parent; 1 larger than array index */
308 l_int32 ic; /* index into heap for child */
309 l_float32 valp, valc;
310 
311  PROCNAME("lheapSwapUp");
312 
313  if (!lh)
314  return ERROR_INT("lh not defined", procName, 1);
315  if (index < 0 || index >= lh->n)
316  return ERROR_INT("invalid index", procName, 1);
317 
318  ic = index + 1; /* index into heap: add 1 to array index */
319  if (lh->direction == L_SORT_INCREASING) {
320  while (1) {
321  if (ic == 1) /* root of heap */
322  break;
323  ip = ic / 2;
324  valc = *(l_float32 *)(lh->array[ic - 1]);
325  valp = *(l_float32 *)(lh->array[ip - 1]);
326  if (valp <= valc)
327  break;
328  SWAP_ITEMS(ip - 1, ic - 1);
329  ic = ip;
330  }
331  } else { /* lh->direction == L_SORT_DECREASING */
332  while (1) {
333  if (ic == 1) /* root of heap */
334  break;
335  ip = ic / 2;
336  valc = *(l_float32 *)(lh->array[ic - 1]);
337  valp = *(l_float32 *)(lh->array[ip - 1]);
338  if (valp >= valc)
339  break;
340  SWAP_ITEMS(ip - 1, ic - 1);
341  ic = ip;
342  }
343  }
344  return 0;
345 }
346 
347 
369 l_ok
371 {
372 l_int32 ip; /* index to heap for parent; 1 larger than array index */
373 l_int32 icr, icl; /* index into heap for left/right children */
374 l_float32 valp, valcl, valcr;
375 
376  PROCNAME("lheapSwapDown");
377 
378  if (!lh)
379  return ERROR_INT("lh not defined", procName, 1);
380  if (lheapGetCount(lh) < 1)
381  return 0;
382 
383  ip = 1; /* index into top of heap: corresponds to array[0] */
384  if (lh->direction == L_SORT_INCREASING) {
385  while (1) {
386  icl = 2 * ip;
387  if (icl > lh->n)
388  break;
389  valp = *(l_float32 *)(lh->array[ip - 1]);
390  valcl = *(l_float32 *)(lh->array[icl - 1]);
391  icr = icl + 1;
392  if (icr > lh->n) { /* only a left child; no iters below */
393  if (valp > valcl)
394  SWAP_ITEMS(ip - 1, icl - 1);
395  break;
396  } else { /* both children exist; swap with the smallest if bigger */
397  valcr = *(l_float32 *)(lh->array[icr - 1]);
398  if (valp <= valcl && valp <= valcr) /* smaller than both */
399  break;
400  if (valcl <= valcr) { /* left smaller; swap */
401  SWAP_ITEMS(ip - 1, icl - 1);
402  ip = icl;
403  } else { /* right smaller; swap */
404  SWAP_ITEMS(ip - 1, icr - 1);
405  ip = icr;
406  }
407  }
408  }
409  } else { /* lh->direction == L_SORT_DECREASING */
410  while (1) {
411  icl = 2 * ip;
412  if (icl > lh->n)
413  break;
414  valp = *(l_float32 *)(lh->array[ip - 1]);
415  valcl = *(l_float32 *)(lh->array[icl - 1]);
416  icr = icl + 1;
417  if (icr > lh->n) { /* only a left child; no iters below */
418  if (valp < valcl)
419  SWAP_ITEMS(ip - 1, icl - 1);
420  break;
421  } else { /* both children exist; swap with the biggest if smaller */
422  valcr = *(l_float32 *)(lh->array[icr - 1]);
423  if (valp >= valcl && valp >= valcr) /* bigger than both */
424  break;
425  if (valcl >= valcr) { /* left bigger; swap */
426  SWAP_ITEMS(ip - 1, icl - 1);
427  ip = icl;
428  } else { /* right bigger; swap */
429  SWAP_ITEMS(ip - 1, icr - 1);
430  ip = icr;
431  }
432  }
433  }
434  }
435 
436  return 0;
437 }
438 
439 
452 l_ok
454 {
455 l_int32 i;
456 
457  PROCNAME("lheapSort");
458 
459  if (!lh)
460  return ERROR_INT("lh not defined", procName, 1);
461 
462  for (i = 0; i < lh->n; i++)
463  lheapSwapUp(lh, i);
464 
465  return 0;
466 }
467 
468 
486 l_ok
488 {
489 l_int32 i, index, size;
490 
491  PROCNAME("lheapSortStrictOrder");
492 
493  if (!lh)
494  return ERROR_INT("lh not defined", procName, 1);
495 
496  size = lh->n; /* save the actual size */
497  for (i = 0; i < size; i++) {
498  index = size - i;
499  SWAP_ITEMS(0, index - 1);
500  lh->n--; /* reduce the apparent heap size by 1 */
501  lheapSwapDown(lh);
502  }
503  lh->n = size; /* restore the size */
504 
505  for (i = 0; i < size / 2; i++) /* reverse */
506  SWAP_ITEMS(i, size - i - 1);
507 
508  return 0;
509 }
510 
511 
512 
513 /*---------------------------------------------------------------------*
514  * Debug output *
515  *---------------------------------------------------------------------*/
523 l_ok
524 lheapPrint(FILE *fp,
525  L_HEAP *lh)
526 {
527 l_int32 i;
528 
529  PROCNAME("lheapPrint");
530 
531  if (!fp)
532  return ERROR_INT("stream not defined", procName, 1);
533  if (!lh)
534  return ERROR_INT("lh not defined", procName, 1);
535 
536  fprintf(fp, "\n L_Heap: nalloc = %d, n = %d, array = %p\n",
537  lh->nalloc, lh->n, lh->array);
538  for (i = 0; i < lh->n; i++)
539  fprintf(fp, "keyval[%d] = %f\n", i, *(l_float32 *)lh->array[i]);
540 
541  return 0;
542 }
l_ok lheapAdd(L_HEAP *lh, void *item)
lheapAdd()
Definition: heap.c:186
l_ok lheapPrint(FILE *fp, L_HEAP *lh)
lheapPrint()
Definition: heap.c:524
l_ok lheapSortStrictOrder(L_HEAP *lh)
lheapSortStrictOrder()
Definition: heap.c:487
void lheapDestroy(L_HEAP **plh, l_int32 freeflag)
lheapDestroy()
Definition: heap.c:145
void * reallocNew(void **pindata, l_int32 oldsize, l_int32 newsize)
reallocNew()
Definition: utils2.c:1161
l_int32 lheapGetCount(L_HEAP *lh)
lheapGetCount()
Definition: heap.c:271
static l_int32 lheapExtendArray(L_HEAP *lh)
lheapExtendArray()
Definition: heap.c:217
L_HEAP * lheapCreate(l_int32 nalloc, l_int32 direction)
lheapCreate()
Definition: heap.c:102
void * lheapRemove(L_HEAP *lh)
lheapRemove()
Definition: heap.c:242
l_int32 direction
Definition: heap.h:82
l_ok lheapSort(L_HEAP *lh)
lheapSort()
Definition: heap.c:453
Definition: heap.h:77
l_ok lheapSwapDown(L_HEAP *lh)
lheapSwapDown()
Definition: heap.c:370
l_ok lheapSwapUp(L_HEAP *lh, l_int32 index)
lheapSwapUp()
Definition: heap.c:304
l_int32 n
Definition: heap.h:80
l_int32 nalloc
Definition: heap.h:79
static const l_int32 INITIAL_BUFFER_ARRAYSIZE
Definition: bbuffer.c:103
void ** array
Definition: heap.h:81