# 5. The Heap in Practice: The C++ Standard Template Library (STL)

<span class="ng-star-inserted">While understanding how to build Heap Sort from scratch is crucial for algorithmic knowledge, in modern C++, we often leverage the powerful abstractions provided by the Standard Template Library (STL). The concepts of a heap are primarily exposed through </span><span class="inline-code ng-star-inserted">std::priority\_queue</span><span class="ng-star-inserted">.</span>

#### **<span class="inline-code ng-star-inserted">std::priority\_queue</span><span class="ng-star-inserted">: A Ready-to-Use Heap</span>**

<span class="ng-star-inserted">The C++ STL provides a container adapter called </span><span class="inline-code ng-star-inserted">std::priority\_queue</span><span class="ng-star-inserted"> that is an implementation of a Heap.</span>

- **<span class="ng-star-inserted">Default Behavior:</span>**<span class="ng-star-inserted"> By default, </span><span class="inline-code ng-star-inserted">std::priority\_queue&lt;int&gt;</span><span class="ng-star-inserted"> is a </span>**<span class="ng-star-inserted">Max-Heap</span>**<span class="ng-star-inserted">. This means that when you call </span><span class="inline-code ng-star-inserted">top()</span><span class="ng-star-inserted">, it returns the largest element, and when you </span><span class="inline-code ng-star-inserted">pop()</span><span class="ng-star-inserted">, it removes the largest element while maintaining the heap property.</span>
- **<span class="ng-star-inserted">Core Operations:</span>**
    
    
    - <span class="inline-code ng-star-inserted">push()</span><span class="ng-star-inserted">: Adds an element to the queue (heap). This internally performs a </span><span class="ng-star-inserted">sift-up</span><span class="ng-star-inserted"> operation. Complexity: </span>**<span class="ng-star-inserted">O(log n)</span>**<span class="ng-star-inserted">.</span>
    - <span class="inline-code ng-star-inserted">pop()</span><span class="ng-star-inserted">: Removes the top element. Complexity: </span>**<span class="ng-star-inserted">O(log n)</span>**<span class="ng-star-inserted">.</span>
    - <span class="inline-code ng-star-inserted">top()</span><span class="ng-star-inserted">: Returns a reference to the top element without removing it. Complexity: </span>**<span class="ng-star-inserted">O(1)</span>**<span class="ng-star-inserted">.</span>

#### **<span class="ng-star-inserted">Working with Custom Data Types</span>**

<span class="ng-star-inserted">What happens if we want to create a priority queue of custom objects, like a </span><span class="inline-code ng-star-inserted">struct</span><span class="ng-star-inserted"> for patients in a hospital?</span>

```c++
struct Patient {
    std::string name;
    int triage_level; // Level 1 is highest priority
};

// This will cause a compile error!
std::priority_queue<Patient> er_queue; 
```

<span class="ng-star-inserted">The compiler doesn't know how to compare two </span><span class="inline-code ng-star-inserted">Patient</span><span class="ng-star-inserted"> objects. To solve this, we must provide our own custom comparison logic.</span>

#### **<span class="ng-star-inserted">Custom Comparators: Functors and Lambda Expressions</span>**

<span class="ng-star-inserted">We can tell </span><span class="inline-code ng-star-inserted">std::priority\_queue</span><span class="ng-star-inserted"> how to order our custom types using a </span>**<span class="ng-star-inserted">custom comparator</span>**<span class="ng-star-inserted">. There are two common ways to do this in modern C++:</span>

1. **<span class="ng-star-inserted">Functor (Function Object):</span>**<span class="ng-star-inserted"> A </span><span class="inline-code ng-star-inserted">struct</span><span class="ng-star-inserted"> or </span><span class="inline-code ng-star-inserted">class</span><span class="ng-star-inserted"> that overloads the function call operator </span><span class="inline-code ng-star-inserted">operator()</span><span class="ng-star-inserted">. The </span><span class="inline-code ng-star-inserted">priority\_queue</span><span class="ng-star-inserted"> will create an object of this type and use its </span><span class="inline-code ng-star-inserted">operator()</span><span class="ng-star-inserted"> to compare elements. This is a powerful, stateful way to define comparison logic.  
    </span>
    
    ```c++
    struct ComparePatients {
        bool operator()(const Patient& a, const Patient& b) {
            // Because priority_queue is a Max-Heap, it puts the "larger"
            // element on top. We want level 1 to be the highest priority,
            // so we tell the queue that 'a' is "less than" 'b' if its
            // triage level is numerically greater.
            return a.triage_level > b.triage_level;
        }
    };
    
    // Usage:
    std::priority_queue<Patient, std::vector<Patient>, ComparePatients> er_queue;
    ```
2. <span class="ng-star-inserted">**Lambda Expression:** An inline, anonymous function that can be defined on the spot. Lambdas are often more concise and readable for simple, stateless comparison logic. They are commonly used with algorithms like <span class="inline-code ng-star-inserted">std::sort</span>.  
    </span>```c++
    auto compare_lambda = [](const Patient& a, const Patient& b) {
        return a.triage_level > b.triage_level;
    };
    
    // Usage with priority_queue is slightly more verbose
    std::priority_queue<Patient, std::vector<Patient>, decltype(compare_lambda)> er_queue(compare_lambda);
    ```

<span class="ng-star-inserted">By providing these comparators, we can leverage the highly optimized and safe implementation of a heap provided by the STL for any data type we need.</span>