# 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; } ```