- Overall, LGTM. - A protection against negative indices being passed to `parent` doesn't worth the effort. `parent` is a private method, so you are in control of the indices at all times. A strong indication that the protection is not needed is the fact that `insert` doesn't bother to test the return value for validity. - Along the same line, `left()` and `right()` returning `-1` doesn't look like a good idea. Effectively, you test the same condition twice: `((2 * i) + 1) < heap.size() - 1` in `left`, and `l != -1` in `heapify`. - Notice that anytime `right` is valid, `left` is also valid. That allows a certain optimization (see below). - C is very good in recognizing tail recursion and optimizing it out. I strongly recommend to do it explicitly anyway. - Combining the three bullets above, consider void heapify(int i) { while ((r = right(i)) < heap.size()) { follow your swapping logic } if ((l = left(i)) < heap_size()) { // No need to loop - it may only happen once! if (heap[l] < heap[i]) { std::swap(heap[i], heap[l]); } } } - `MinHeap::heapify` is a misnomer, and somewhat confusing. Usually `heapify` refers to the process of turning an array into a heap. Your method is normally called `sift_down`. - Too many comments to my taste.