Simple data structures / objects in plain C Snapshot
|
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