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
->dataSize
= dataSize
;
15 heap
->array
= _vector_new(sizeof(ItemValue
));
19 Heap
* heap_copy(Heap
* heap
)
21 Heap
* heapCopy
= _heap_new(heap
->dataSize
, heap
->hType
, heap
->arity
);
22 // HACK: vector_copy is not enough,
23 // since we also have to allocate ItemValue(->item)
24 heapCopy
->array
->size
= heap
->array
->size
;
25 heapCopy
->array
->capacity
= heap
->array
->capacity
;
26 heapCopy
->array
->datas
=
27 (void**)safe_malloc(heap
->array
->capacity
*sizeof(void*));
28 for (UInt i
=0; i
<heap
->array
->size
; i
++)
30 heapCopy
->array
->datas
[i
] = safe_malloc(sizeof(ItemValue
));
31 ItemValue itemValueCopy
= (ItemValue
){
32 .item
=safe_malloc(heap
->dataSize
),
33 .value
=((ItemValue
*)(heap
->array
->datas
[i
]))->value
};
36 ((ItemValue
*)(heap
->array
->datas
[i
]))->item
,
38 memcpy(heapCopy
->array
->datas
[i
], &itemValueCopy
, sizeof(ItemValue
));
43 bool heap_empty(Heap
* heap
)
45 return vector_empty(heap
->array
);
48 UInt
heap_size(Heap
* heap
)
50 return vector_size(heap
->array
);
53 // NOTE: [perf] in two following methods, full heap[k] exchanges are
54 // not needed; we keep track of the moving element without assigning it at
55 // every step, thus saving array accesses and affectations + 'aux' tmp memory.
56 // --> this is not the most natural way of writing these functions.
58 void _heap_bubble_up(Heap
* heap
, UInt startIndex
)
60 UInt currentIndex
= startIndex
;
61 ItemValue
* startItemValue
= heap
->array
->datas
[startIndex
];
65 UInt nextIndex
= currentIndex
/ heap
->arity
;
66 Real nextValue
= ((ItemValue
*)(heap
->array
->datas
[nextIndex
]))->value
;
67 // compare to parent (if applicable)
68 if (currentIndex
== 0 ||
69 (heap
->hType
== MIN_T
&& startItemValue
->value
>= nextValue
) ||
70 (heap
->hType
== MAX_T
&& startItemValue
->value
<= nextValue
))
72 // moving element has landed: apply final affectation
73 heap
->array
->datas
[currentIndex
] = startItemValue
;
76 // move one level up: the parent goes one level down
77 heap
->array
->datas
[currentIndex
] = heap
->array
->datas
[nextIndex
];
78 currentIndex
= nextIndex
;
82 void _heap_bubble_down(Heap
* heap
, UInt startIndex
)
84 UInt currentIndex
= startIndex
;
85 ItemValue
* startItemValue
= heap
->array
->datas
[startIndex
];
88 if (currentIndex
* heap
->arity
>= heap
->array
->size
)
90 // moving element has landed (in a leaf): apply final affectation
91 heap
->array
->datas
[currentIndex
] = startItemValue
;
94 // find top child (min or max)
96 Real topChildValue
= (heap
->hType
== MIN_T
? INFINITY
: -INFINITY
);
97 for (Int i
=0; i
<heap
->arity
; i
++)
99 UInt childIndex
= i
+ currentIndex
* heap
->arity
;
100 if (childIndex
>= heap
->array
->size
)
102 Real childValue
= ((ItemValue
*)(heap
->array
->datas
[childIndex
]))->value
;
103 if ((heap
->hType
== MIN_T
&& childValue
< topChildValue
) ||
104 (heap
->hType
== MAX_T
&& childValue
> topChildValue
))
106 topChildIndex
= childIndex
;
107 topChildValue
= childValue
;
110 // compare to top child
111 if ((heap
->hType
== MIN_T
&& startItemValue
->value
> topChildValue
) ||
112 (heap
->hType
== MAX_T
&& startItemValue
->value
< topChildValue
))
114 // move one level down: the child goes one level up
115 heap
->array
->datas
[currentIndex
] = heap
->array
->datas
[topChildIndex
];
119 // moving element has landed: apply final affectation
120 heap
->array
->datas
[currentIndex
] = startItemValue
;
123 currentIndex
= topChildIndex
;
127 void _heap_insert(Heap
* heap
, void* item
, Real value
)
129 ItemValue itemValue
=
130 (ItemValue
){.item
=safe_malloc(heap
->dataSize
), .value
=value
};
131 memcpy(itemValue
.item
, item
, heap
->dataSize
);
132 _vector_push(heap
->array
, &itemValue
);
133 _heap_bubble_up(heap
, heap
->array
->size
-1);
136 void _heap_modify(Heap
* heap
, UInt index
, Real newValue
)
138 double oldValue
= ((ItemValue
*)(heap
->array
->datas
[index
]))->value
;
139 ((ItemValue
*)(heap
->array
->datas
[index
]))->value
= newValue
;
140 if ((heap
->hType
== MIN_T
&& newValue
> oldValue
) ||
141 (heap
->hType
== MAX_T
&& newValue
< oldValue
))
143 _heap_bubble_down(heap
, index
);
146 _heap_bubble_up(heap
, index
);
149 void _heap_remove(Heap
* heap
, UInt index
)
151 safe_free(((ItemValue
*)(heap
->array
->datas
[index
]))->item
);
152 ItemValue
* tmp
= heap
->array
->datas
[index
];
153 heap
->array
->datas
[index
] = heap
->array
->datas
[heap_size(heap
)-1];
154 heap
->array
->datas
[heap_size(heap
)-1] = tmp
;
155 vector_pop(heap
->array
);
156 if (heap
->array
->size
> 0)
157 _heap_bubble_down(heap
, index
);
160 ItemValue
* heap_top_raw(Heap
* heap
)
162 return (ItemValue
*)(heap
->array
->datas
[0]);
165 void heap_pop(Heap
* heap
)
167 _heap_remove(heap
, 0);
170 void heap_clear(Heap
* heap
)
172 for (UInt i
= 0; i
< heap
->array
->size
; i
++)
174 // Extra memory releases which wouldn't be done in vector_clear()
175 safe_free(((ItemValue
*)(heap
->array
->datas
[i
]))->item
);
176 //safe_free((ItemValue*)heap->array->datas[i]);
178 vector_clear(heap
->array
);
181 void heap_destroy(Heap
* heap
)
184 safe_free(heap
->array
);