Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include <math.h>
00017
00018 #include "lib/binaryheap.h"
00019
00020 static void sift_down(binaryheap *heap, int node_off);
00021 static void sift_up(binaryheap *heap, int node_off);
00022 static inline void swap_nodes(binaryheap *heap, int a, int b);
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 binaryheap *
00033 binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
00034 {
00035 int sz;
00036 binaryheap *heap;
00037
00038 sz = offsetof(binaryheap, bh_nodes) + sizeof(Datum) * capacity;
00039 heap = palloc(sz);
00040 heap->bh_size = 0;
00041 heap->bh_space = capacity;
00042 heap->bh_has_heap_property = true;
00043 heap->bh_compare = compare;
00044 heap->bh_arg = arg;
00045
00046 return heap;
00047 }
00048
00049
00050
00051
00052
00053
00054 void
00055 binaryheap_free(binaryheap *heap)
00056 {
00057 pfree(heap);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 static inline int
00070 left_offset(int i)
00071 {
00072 return 2 * i + 1;
00073 }
00074
00075 static inline int
00076 right_offset(int i)
00077 {
00078 return 2 * i + 2;
00079 }
00080
00081 static inline int
00082 parent_offset(int i)
00083 {
00084 return (i - 1) / 2;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 void
00096 binaryheap_add_unordered(binaryheap *heap, Datum d)
00097 {
00098 if (heap->bh_size >= heap->bh_space)
00099 elog(ERROR, "out of binary heap slots");
00100 heap->bh_has_heap_property = false;
00101 heap->bh_nodes[heap->bh_size] = d;
00102 heap->bh_size++;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 void
00112 binaryheap_build(binaryheap *heap)
00113 {
00114 int i;
00115
00116 for (i = parent_offset(heap->bh_size - 1); i >= 0; i--)
00117 sift_down(heap, i);
00118 heap->bh_has_heap_property = true;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 void
00128 binaryheap_add(binaryheap *heap, Datum d)
00129 {
00130 if (heap->bh_size >= heap->bh_space)
00131 elog(ERROR, "out of binary heap slots");
00132 heap->bh_nodes[heap->bh_size] = d;
00133 heap->bh_size++;
00134 sift_up(heap, heap->bh_size - 1);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 Datum
00145 binaryheap_first(binaryheap *heap)
00146 {
00147 Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);
00148 return heap->bh_nodes[0];
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 Datum
00160 binaryheap_remove_first(binaryheap *heap)
00161 {
00162 Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);
00163
00164 if (heap->bh_size == 1)
00165 {
00166 heap->bh_size--;
00167 return heap->bh_nodes[0];
00168 }
00169
00170
00171
00172
00173
00174
00175 swap_nodes(heap, 0, heap->bh_size - 1);
00176 heap->bh_size--;
00177 sift_down(heap, 0);
00178
00179 return heap->bh_nodes[heap->bh_size];
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 void
00190 binaryheap_replace_first(binaryheap *heap, Datum d)
00191 {
00192 Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);
00193
00194 heap->bh_nodes[0] = d;
00195
00196 if (heap->bh_size > 1)
00197 sift_down(heap, 0);
00198 }
00199
00200
00201
00202
00203 static inline void
00204 swap_nodes(binaryheap *heap, int a, int b)
00205 {
00206 Datum swap;
00207
00208 swap = heap->bh_nodes[a];
00209 heap->bh_nodes[a] = heap->bh_nodes[b];
00210 heap->bh_nodes[b] = swap;
00211 }
00212
00213
00214
00215
00216
00217 static void
00218 sift_up(binaryheap *heap, int node_off)
00219 {
00220 while (node_off != 0)
00221 {
00222 int cmp;
00223 int parent_off;
00224
00225
00226
00227
00228
00229 parent_off = parent_offset(node_off);
00230 cmp = heap->bh_compare(heap->bh_nodes[node_off],
00231 heap->bh_nodes[parent_off],
00232 heap->bh_arg);
00233 if (cmp <= 0)
00234 break;
00235
00236
00237
00238
00239
00240 swap_nodes(heap, node_off, parent_off);
00241 node_off = parent_off;
00242 }
00243 }
00244
00245
00246
00247
00248
00249 static void
00250 sift_down(binaryheap *heap, int node_off)
00251 {
00252 while (true)
00253 {
00254 int left_off = left_offset(node_off);
00255 int right_off = right_offset(node_off);
00256 int swap_off = 0;
00257
00258
00259 if (left_off < heap->bh_size &&
00260 heap->bh_compare(heap->bh_nodes[node_off],
00261 heap->bh_nodes[left_off],
00262 heap->bh_arg) < 0)
00263 swap_off = left_off;
00264
00265
00266 if (right_off < heap->bh_size &&
00267 heap->bh_compare(heap->bh_nodes[node_off],
00268 heap->bh_nodes[right_off],
00269 heap->bh_arg) < 0)
00270 {
00271
00272 if (!swap_off ||
00273 heap->bh_compare(heap->bh_nodes[left_off],
00274 heap->bh_nodes[right_off],
00275 heap->bh_arg) < 0)
00276 swap_off = right_off;
00277 }
00278
00279
00280
00281
00282
00283 if (!swap_off)
00284 break;
00285
00286
00287
00288
00289
00290 swap_nodes(heap, swap_off, node_off);
00291 node_off = swap_off;
00292 }
00293 }