417a4d0b409511e85209bf032435f4a30726707e
7 // NOTE: no init() method here, since Heap has no specific initialization
9 Heap
* _heap_new(size_t dataSize
, OrderType hType
, UInt arity
)
11 Heap
* heap
= (Heap
*) safe_malloc(sizeof(Heap
));
14 heap
->items
= _vector_new(dataSize
);
15 heap
->values
= _vector_new(sizeof(Real
));
19 Heap
* heap_copy(Heap
* heap
)
21 Heap
* heapCopy
= (Heap
*) safe_malloc(sizeof(Heap
));
22 heapCopy
->arity
= heap
->arity
;
23 heapCopy
->hType
= heap
->hType
;
24 heapCopy
->items
= vector_copy(heap
->items
);
25 heapCopy
->values
= vector_copy(heap
->values
);
29 bool heap_empty(Heap
* heap
)
31 return vector_empty(heap
->items
);
34 UInt
heap_size(Heap
* heap
)
36 return vector_size(heap
->items
);
39 // NOTE: [perf] in two following methods, full heap[k] exchanges are
40 // not needed; we keep track of the moving element without assigning it at
41 // every step, thus saving array accesses and affectations + 'aux' tmp memory.
42 // --> this is not the most natural way of writing these functions.
44 void _heap_bubble_up(Heap
* heap
, UInt startIndex
)
47 // Nothing to do in this case
49 UInt currentIndex
= startIndex
;
50 void* startItem
= _vector_get(heap
->items
, startIndex
);
51 Real startValue
= *((Real
*)(_vector_get(heap
->values
, startIndex
)));
52 bool startItemReallocated
= false;
55 bool land
= (currentIndex
== 0), //at root: can't go up
59 // Get parent and compare to it
60 UInt nextIndex
= (currentIndex
- 1) / heap
->arity
;
61 Real nextValue
= *((Real
*)(_vector_get(heap
->values
, nextIndex
)));
63 (heap
->hType
== MIN_T
&& startValue
>= nextValue
) ||
64 (heap
->hType
== MAX_T
&& startValue
<= nextValue
)
68 // Move one level up: the parent goes one level down
69 if (currentIndex
== startIndex
)
71 // Save startItem (because *startItem is about to be changed)
72 void* newStartItem
= safe_malloc(heap
->items
->dataSize
);
73 memcpy(newStartItem
, startItem
, heap
->items
->dataSize
);
74 startItem
= newStartItem
;
75 startItemReallocated
= true;
77 void* nextItem
= _vector_get(heap
->items
, nextIndex
);
78 _vector_set(heap
->items
, currentIndex
, nextItem
);
79 _vector_set(heap
->values
, currentIndex
, &nextValue
);
80 currentIndex
= nextIndex
;
83 // At correct relative place: will now land
84 if (currentIndex
== startIndex
)
85 applyExchange
= false;
89 _vector_set(heap
->items
, currentIndex
, startItem
);
90 _vector_set(heap
->values
, currentIndex
, &startValue
);
94 if (startItemReallocated
)
98 void _heap_bubble_down(Heap
* heap
, UInt startIndex
)
100 if (startIndex
* heap
->arity
+ 1 >= heap
->items
->size
)
101 // Nothing to do: already in a leaf
103 UInt currentIndex
= startIndex
;
104 void* startItem
= _vector_get(heap
->items
, startIndex
);
105 Real startValue
= *((Real
*)(_vector_get(heap
->values
, startIndex
)));
106 bool startItemReallocated
= false;
109 bool land
= (currentIndex
* heap
->arity
+ 1 >= heap
->items
->size
),
110 applyExchange
= true;
113 // Find top child (min or max)
115 Real topChildValue
= (heap
->hType
== MIN_T
? INFINITY
: -INFINITY
);
116 for (UInt i
= 1; i
<= heap
->arity
; i
++)
118 UInt childIndex
= currentIndex
* heap
->arity
+ i
;
119 if (childIndex
>= heap
->items
->size
)
121 Real childValue
= *((Real
*)(_vector_get(heap
->values
, childIndex
)));
123 (heap
->hType
== MIN_T
&& childValue
< topChildValue
) ||
124 (heap
->hType
== MAX_T
&& childValue
> topChildValue
)
126 topChildIndex
= childIndex
;
127 topChildValue
= childValue
;
130 // Compare to top child
132 (heap
->hType
== MIN_T
&& startValue
<= topChildValue
) ||
133 (heap
->hType
== MAX_T
&& startValue
>= topChildValue
)
137 // Move one level down: the child goes one level up
138 if (currentIndex
== startIndex
)
140 // Save startItem (because *startItem is about to be changed)
141 void* newStartItem
= safe_malloc(heap
->items
->dataSize
);
142 memcpy(newStartItem
, startItem
, heap
->items
->dataSize
);
143 startItem
= newStartItem
;
144 startItemReallocated
= true;
146 void* topChildItem
= _vector_get(heap
->items
, topChildIndex
);
147 _vector_set(heap
->items
, currentIndex
, topChildItem
);
148 _vector_set(heap
->values
, currentIndex
, &topChildValue
);
149 currentIndex
= topChildIndex
;
152 // At correct relative place: will now land
153 if (currentIndex
== startIndex
)
154 applyExchange
= false;
158 // Moving element has landed (in a leaf): apply final affectation
159 _vector_set(heap
->items
, currentIndex
, startItem
);
160 _vector_set(heap
->values
, currentIndex
, &startValue
);
164 if (startItemReallocated
)
165 safe_free(startItem
);
168 void _heap_insert(Heap
* heap
, void* item
, Real value
)
170 _vector_push(heap
->items
, item
);
171 _vector_push(heap
->values
, &value
);
172 _heap_bubble_up(heap
, heap
->items
->size
- 1);
175 Int
_heap_get_index(Heap
* heap
, void* item
)
177 for (Int index
= 0; index
< heap
->items
->size
; index
++)
181 heap
->items
->datas
+ index
* heap
->items
->dataSize
,
183 heap
->items
->dataSize
192 void _heap_modify(Heap
* heap
, void* item
, Real newValue
)
194 // First, find index of the item:
195 const Int index
= _heap_get_index(heap
, item
);
199 Real oldValue
= *((Real
*)_vector_get(heap
->values
, index
));
200 _vector_set(heap
->values
, index
, &newValue
);
202 (heap
->hType
== MIN_T
&& newValue
> oldValue
) ||
203 (heap
->hType
== MAX_T
&& newValue
< oldValue
)
205 _heap_bubble_down(heap
, index
);
208 _heap_bubble_up(heap
, index
);
211 void _heap_remove_at_index(Heap
* heap
, Int index
)
213 const bool removeLast
= (index
== heap
->items
->size
- 1);
219 _vector_get(heap
->items
, heap
->items
->size
- 1));
223 _vector_get(heap
->values
, heap
->values
->size
- 1));
225 vector_pop(heap
->items
);
226 vector_pop(heap
->values
);
227 if (!removeLast
&& heap
->items
->size
> 0)
228 _heap_bubble_down(heap
, index
);
231 void _heap_remove(Heap
* heap
, void* item
)
233 // First, find index of the item:
234 const Int index
= _heap_get_index(heap
, item
);
236 _heap_remove_at_index(heap
, index
);
239 ItemValue
_heap_top(Heap
* heap
)
242 top
.item
= _vector_get(heap
->items
, 0);
243 vector_get(heap
->values
, 0, top
.value
);
247 void heap_pop(Heap
* heap
)
249 _heap_remove_at_index(heap
, 0);
252 void heap_clear(Heap
* heap
)
254 vector_clear(heap
->items
);
255 vector_clear(heap
->values
);
258 void heap_destroy(Heap
* heap
)
260 vector_destroy(heap
->items
);
261 vector_destroy(heap
->values
);