---
# System prepended metadata

title: Min-Max Heap (Double-ended Priority Queue)

---

# Min-Max Heap (Double-ended Priority Queue)

https://medium.com/%E7%8B%97%E5%A5%B4%E5%B7%A5%E7%A8%8B%E5%B8%AB/%E5%9C%96%E8%A7%A3-double-ended-priority-queue-%E9%80%B2%E9%9A%8E%E6%A8%B9-1ae18d2ca402

```
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

class minmax_heap{
public:
    vector<int> mmheap;
    minmax_heap(){
        mmheap.push_back(INT_MAX);
    }

    void print(){
        for(const auto &h: mmheap){
            cout << h << " ";
        }
        cout << endl;
    }

    int mmheap_size(){
        return mmheap.size() - 1;
    }

    void VerifyMin_upward(int idx){
        int grand_idx;
        while(1){
            grand_idx = idx / 4;
            if(grand_idx == 0){
                break;
            }
            if(mmheap[idx] < mmheap[grand_idx]){
                swap(mmheap[idx], mmheap[grand_idx]);
                idx = grand_idx;
            }else{
                break;
            }
        }
    }

    void VerifyMax_upward(int idx){
        int grand_idx;
        while(1){
            grand_idx = idx / 4;
            if(grand_idx == 0){
                break;
            }
            if(mmheap[idx] > mmheap[grand_idx]){
                swap(mmheap[idx], mmheap[grand_idx]);
                idx = grand_idx;
            }else{
                break;
            }
        }
    }

    void mmheap_insert(int a){
        mmheap.push_back(a);
        int idx = mmheap.size() - 1;
        int level = log2(idx);
        int parent_level = level - 1;
        int parent_idx = idx / 2;
        if(level % 2){      // parent in min_level
            if(a < mmheap[parent_idx]){
                swap(mmheap[idx], mmheap[parent_idx]);
                VerifyMin_upward(parent_idx);
            }else{
                VerifyMax_upward(idx);
            }
        }else{              // parent in max_level
            if(a > mmheap[parent_idx]){
                swap(mmheap[idx], mmheap[parent_idx]);
                VerifyMax_upward(parent_idx);
            }else{
                VerifyMin_upward(idx);
            }
        }

    }

    void VerifyMin_downward(int idx){
        // idx had no child
        if(idx * 2 > mmheap.size() - 1){
            return;
        }

        // idx had no grand child
        int child_idx1 = idx * 2;
        int child_idx2 = idx * 2 + 1;
        if(idx * 4 > mmheap.size() - 1){
            int k;
            if(child_idx2 == mmheap.size()){
                k = mmheap[child_idx1];
            }else{
                k = min(mmheap[child_idx1], mmheap[child_idx2]);
            }

            if(k < mmheap[idx]){
                if(k == mmheap[child_idx1]){
                    swap(mmheap[idx], mmheap[child_idx1]);
                }else{
                    swap(mmheap[idx], mmheap[child_idx2]);
                }
            }
            return;
        }

        //int grand_child_idx1 = idx * 4;
        //int grand_child_idx2 = idx * 4 + 1;
        //int grand_child_idx3 = idx * 4 + 2;
        //int grand_child_idx4 = idx * 4 + 3;
        int min_idx = -1;
        int min_val = INT_MAX;
        for(int i=0;i<4;++i){
            int idx_tmp = idx * 4 + i;
            if(idx_tmp == mmheap.size()){
                break;
            }
            if(mmheap[idx_tmp] < min_val){
                min_val = mmheap[idx_tmp];
                min_idx = idx_tmp;
            }
        }

        if(mmheap[idx] > min_val){
            swap(mmheap[idx], mmheap[min_idx]);
            if(mmheap[min_idx / 2] < mmheap[min_idx]){
                swap(mmheap[min_idx / 2], mmheap[min_idx]);
                VerifyMin_downward(min_idx);
            }
        }
    }

    void VerifyMax_downward(int idx){
        // idx had no child
        if(idx * 2 > mmheap.size() - 1){
            return;
        }

        // idx had no grand child
        int child_idx1 = idx * 2;
        int child_idx2 = idx * 2 + 1;
        if(idx * 4 > mmheap.size() - 1){
            int k;
            if(child_idx2 == mmheap.size()){
                k = mmheap[child_idx1];
            }else{
                k = max(mmheap[child_idx1], mmheap[child_idx2]);
            }

            if(k > mmheap[idx]){
                if(k == mmheap[child_idx1]){
                    swap(mmheap[idx], mmheap[child_idx1]);
                }else{
                    swap(mmheap[idx], mmheap[child_idx2]);
                }
            }
            return;
        }

        //int grand_child_idx1 = idx * 4;
        //int grand_child_idx2 = idx * 4 + 1;
        //int grand_child_idx3 = idx * 4 + 2;
        //int grand_child_idx4 = idx * 4 + 3;
        int max_idx = -1;
        int max_val = INT_MIN;
        for(int i=0;i<4;++i){
            int idx_tmp = idx * 4 + i;
            if(idx_tmp == mmheap.size()){
                break;
            }
            if(mmheap[idx_tmp] > max_val){
                max_val = mmheap[idx_tmp];
                max_idx = idx_tmp;
            }
        }

        if(mmheap[idx] < max_val){
            swap(mmheap[idx], mmheap[max_idx]);
            if(mmheap[max_idx / 2] > mmheap[max_idx]){
                swap(mmheap[max_idx / 2], mmheap[max_idx]);
                VerifyMax_downward(max_idx);
            }
        }
    }

    int mmheap_extract_min(){
        int res = mmheap[1];
        swap(mmheap[1], mmheap[mmheap.size()-1]);
        mmheap.pop_back();
        VerifyMin_downward(1);
        return res;
    }

    int mmheap_extract_max(){
        int res = max(mmheap[2], mmheap[3]);
        if(res == mmheap[2]){
            swap(mmheap[2], mmheap[mmheap.size()-1]);
            mmheap.pop_back();
            VerifyMax_downward(2);
        }else{
            swap(mmheap[3], mmheap[mmheap.size()-1]);
            mmheap.pop_back();
            VerifyMax_downward(3);
        }
        return res;
    }

    int mmheap_min_top(){
        return mmheap[1];
    }

    int mmheap_max_top(){
        if(mmheap.size() == 2){
            return mmheap[1];
        }
        if(mmheap.size() == 3){
            return mmheap[2];
        }
        return max(mmheap[2], mmheap[3]);
    }

};

int main(){
	
    minmax_heap heap;
    int a[11] = {2,6,0,7,6,5,1,6,12,14,9};
    vector<int> A(a,a+11);

    for(const auto &b: A){
        heap.mmheap_insert(b);
        heap.print();
    }

    cout << heap.mmheap_extract_max() << endl;
    heap.print();
    cout << heap.mmheap_extract_min() << endl;
    heap.print();
    cout << heap.mmheap_extract_max() << endl;
    heap.print();
    cout << heap.mmheap_extract_min() << endl;
    heap.print();
    cout << heap.mmheap_extract_max() << endl;
    heap.print();


    return 0;
}

```

