Simple data structures / objects in plain C Snapshot
heap.c
Go to the documentation of this file.
00001 /* Copyright (c) Michael Moser (2011) . 3-clause BSD License applies */
00002 
00003 #include <heap.h>
00004 #include <stdlib.h>
00005 #include <memory.h>
00006 
00007 int HEAP_push( HEAP *heap, void *element, size_t elmsize )
00008 {
00009         size_t pos, pos_offset;
00010         size_t parent, parent_offset;
00011 
00012         if (elmsize != heap->elmsize) {
00013                 return -1;
00014         }
00015 
00016 
00017         if (heap->elmcount >= (heap->elmmaxcount - 1)) {
00018                 unsigned char *pbuffer;
00019                 size_t sz = heap->elmmaxcount * 2;
00020 
00021                 
00022                 pbuffer = realloc( heap->buffer, (sz) * heap->elmsize );        
00023                 if (!pbuffer) {
00024                         return -1;
00025                 }
00026                 heap->buffer = pbuffer;
00027                 heap->elmmaxcount = sz;
00028         }
00029 
00030         elmsize = heap->elmsize;
00031 
00032         heap->elmcount ++;
00033 
00034         pos = heap->elmcount;
00035         while(pos > 1) {
00036 
00037                 parent = pos / 2;
00038 
00039                 pos_offset = (pos - 1) * elmsize;
00040                 parent_offset = (parent - 1) * elmsize;
00041 
00042                 if ( heap->compare_func( heap->buffer + parent_offset, 
00043                                                                  element, 
00044                                                                  elmsize ) > 0) {
00045                         
00046                         memcpy( heap->buffer + pos_offset, heap->buffer + parent_offset, elmsize);
00047                         pos = parent;
00048                 } else {
00049                         break;
00050                 }
00051         }
00052 
00053         memcpy( heap->buffer + (pos - 1) * elmsize, element, elmsize);
00054 
00055 
00056         return 0;
00057 }       
00058 
00059 
00060 int HEAP_pop( HEAP *heap)
00061 {
00062         size_t pos, pos_offset;
00063         size_t left_child, left_child_offset;
00064         size_t right_child, right_child_offset;
00065         size_t next_pos, next_pos_offset;
00066         size_t last_element, last_element_offset;
00067         size_t elmsize;
00068 
00069         if (heap->elmcount == 0) {
00070                 return -1;
00071         }
00072 
00073         elmsize = heap->elmsize;
00074 
00075         last_element = heap->elmcount;
00076         last_element_offset = (last_element -1) * elmsize;
00077         heap->elmcount--;
00078         
00079         pos = 1;
00080         while( pos <= heap->elmcount) {
00081                 
00082                 left_child = (pos << 1);
00083                 if (left_child > heap->elmcount) {
00084                         break;
00085                 }
00086 
00087 
00088                 right_child = left_child + 1;
00089 
00090                 right_child_offset = (right_child - 1) * elmsize;
00091                 left_child_offset = (left_child - 1) * elmsize;
00092 
00093                 if (left_child != heap->elmcount &&
00094                         heap->compare_func( heap->buffer + right_child_offset, 
00095                                                                 heap->buffer + left_child_offset, 
00096                                                                 elmsize) < 0) {
00097 
00098                         next_pos = right_child;
00099                 } else {
00100                         next_pos = left_child;
00101                 }
00102 
00103 
00104                 next_pos_offset = (next_pos-1) * elmsize;
00105                 if (heap->compare_func(heap->buffer + last_element_offset,
00106                                                            heap->buffer + next_pos_offset,
00107                                                            elmsize) > 0) {
00108 
00109                         pos_offset = (pos - 1) * elmsize;
00110                         memcpy( heap->buffer + pos_offset, heap->buffer + next_pos_offset, elmsize);
00111                 } else {
00112                         break;
00113                 }
00114                 pos = next_pos;
00115                 
00116         }
00117         
00118         pos_offset = (pos - 1) * elmsize;
00119         if (pos_offset != last_element_offset) {
00120             memcpy( heap->buffer + pos_offset, heap->buffer + last_element_offset, elmsize);
00121         }
00122 
00123 
00124 
00125         return 0;
00126 }
00127 
00128 
00129 static int check_recursive(HEAP *heap, size_t pos)
00130 {
00131         size_t elmsize = heap->elmsize;
00132         size_t pos_left;
00133         size_t pos_right;
00134 
00135         pos_left = (2 * pos);
00136         if (pos_left <= heap->elmcount) {
00137 
00138                 if (heap->compare_func( heap->buffer + (pos - 1) * elmsize,  
00139                                                             heap->buffer + (pos_left - 1) * elmsize, 
00140                                                                 elmsize) > 0) {
00141                         return 0;
00142                 }
00143                 if (!check_recursive( heap, pos_left)) {
00144                         return 0;
00145                 }
00146         }
00147 
00148 
00149         pos_right =   (2 * pos + 1) * elmsize;
00150         if (pos_right <= heap->elmcount) {
00151 
00152                 if (heap->compare_func( heap->buffer + (pos - 1) * elmsize,  
00153                                                             heap->buffer + (pos_right - 1) * elmsize, 
00154                                                             elmsize) > 0) {
00155                         return 0;
00156                 }
00157                 if (!check_recursive( heap, pos_right)) {
00158                         return 0;
00159                 }
00160         }
00161         return 1;
00162 }
00163 
00164 
00165 int HEAP_check( HEAP *heap )
00166 {
00167 
00168         if (heap->elmcount > heap->elmmaxcount) {
00169                 return 0;
00170         }
00171         if (!check_recursive(heap, 1)) {
00172                 return 0;
00173         }
00174         return 1;
00175 }
00176 
00177 
00178 static void visit_sorted(HEAP *heap, size_t pos, HEAP_VISITOR eval, void *context)
00179 {
00180         size_t elmsize = heap->elmsize;
00181         size_t pos_left;
00182         size_t pos_right;
00183 
00184         if (heap->elmcount > heap->elmmaxcount) {
00185                 return;
00186         }
00187 
00188         pos_left = (2 * pos);
00189         if (pos_left <= heap->elmcount) {
00190 
00191                 check_recursive( heap, pos_left );
00192         }
00193 
00194         pos_right =   (2 * pos + 1) * elmsize;
00195         if (pos_right <= heap->elmcount) {
00196 
00197                 check_recursive( heap, pos_right );
00198         }
00199 
00200         eval( pos, heap->buffer + (pos - 1) * elmsize, elmsize, context );
00201 }
00202 
00203 
00204 
00205 void HEAP_foreach_sorted( HEAP *heap, HEAP_VISITOR eval, void *context)
00206 {
00207         visit_sorted( heap, 1, eval, context );
00208 }
00209 
00210