I have a heap using std::make_heap:
std::vector v{1,2,3,5,9,20,3};
std::make_heap(v.begin(), v.end());
now I update
It's not possible to modify an arbitrary element of the heap in logarithmic running time without violating the heap property by just using the function templates std::pop_heap() and std::push_heap() that the standard library provides.
However, you can define your own STL-like function template, set_heap_element(), for that purpose:
template
void set_heap_element(RandomIt first, RandomIt last, RandomIt pos, T value, Cmp cmp)
{
const auto n = last - first;
*pos = std::move(value); // replace previous value
auto i = pos - first;
using std::swap;
// percolate up
while (i > 0) { // non-root node
auto parent_it = first + (i-1)/2;
if (cmp(*pos, *parent_it))
break; // parent node satisfies the heap-property
swap(*pos, *parent_it); // swap with parent
pos = parent_it;
i = pos - first;
}
// percolate down
while (2*i + 1 < n) { // non-leaf node, since it has a left child
const auto lidx = 2*i + 1, ridx = 2*i + 2;
auto lchild_it = first + lidx;
auto rchild_it = ridx < n? first + ridx: last;
auto it = pos;
if (cmp(*it, *lchild_it))
it = lchild_it;
if (rchild_it != last && cmp(*it, *rchild_it))
it = rchild_it;
if (pos == it)
break; // node satisfies the heap-property
swap(*pos, *it); // swap with child
pos = it;
i = pos - first;
}
}
Then, you can provide the following simplified overload of set_heap_element() for a max heap:
#include // std::less
template
void set_heap_element(RandomIt first, RandomIt last, RandomIt pos, T value) {
return set_heap_element(first, last, pos, value, std::less{});
}
This overload uses a std::less object as the comparison function object for the original function template.
In your max-heap example, set_heap_element() could be used as follows:
std::vector v{1,2,3,5,9,20,3};
std::make_heap(v.begin(), v.end());
// set 4th element to 35 in O(log n)
set_heap_element(v.begin(), v.end(), v.begin() + 3, 35);
You could use std::is_heap(), which takes linear time, whenever you want to check whether the max-heap property is still satisfied by v after setting an element with the set_heap_element() function template above:
assert(std::is_heap(v.begin(), v.end()));
You can achieve the same for a min heap by passing a std::greater object as the last argument of the function calls to std::make_heap(), set_heap_element() and std::is_heap():
std::vector v{1,2,3,5,9,20,3};
// create a min heap
std::make_heap(v.begin(), v.end(), std::greater{});
// set 4th element to 35 in O(log n)
set_heap_element(v.begin(), v.end(), v.begin() + 3, 35, std::greater{});
// is the min-heap property satisfied?
assert(std::is_heap(v.begin(), v.end(), std::greater{}));