I'm working on implementing a Double-Ended Priority Queue (DEAP) data structure in C++. I'm having trouble with establishing the correct implementation of node partnerships between the min and max heaps. The paragraph below shows properties of a DEAP:
- The root contains no element.
- The left subtree is a minimum heap.
- The right subtree is a maximum heap.
- If the right subtree is not empty, then let
ibe any node in the left subtree. Letjbe the corresponding node in the right subtree. If such ajdoes not exist, thenjis the node in the right subtree that corresponds to the parent ofi. The key in nodeiis less than or equal to that inj.
The exercise/assignment asks me by using a two-array representation for a DEAP, consisting of arrays A and B, write a function that initializes the arrays A (for minimum heap) and B (for maximum heap) with elements containing their corresponding keys. Assume that nA be the number of elements in A and nB the number of elements in B, so the number of elements n in the DEAP is nA + nB.
Expected Output:
Here's an example of the correct structure I'm trying to achieve:
=========================================================== Expected behavior: Test 2-1: Initialization of two-array deap with 11 elements. Data set: Level 1: 5, 45 Level 2: 10, 8, 25, 40 Level 3: 15, 19, 9, 30, 20
Min heap: root: 5 10(under 5), 8(under 5) 15(under 10), 19(under 10), 15(under 8), 19(under 8)
Max heap: root: 45 25(under 45), 40(under 45) 20(under 25)
=========================================================== Current (Actual) behavior: Test 2-1: Initialization of two-array deap with 11 elements. Data set: Level 1: 5, 45 Level 2: 8, 9, 25, 40 Level 3: 10, 15, 19, 20, 30
Min heap: root: 5 8(under 5), 9(under 5) 10(under 8), 15(under 8), 19(under 9), 20(under 9)
Max heap: root: 45 25(under 45), 40(under 45) 30(under 25)
===========================================================
Minimal Reproducible Example: Below is my attempt at the implementation which populates nodes with their keys in the minimum heap (left subtree) and maximum heap (right subtree).
#include <iostream> #include <stdexcept> #include <algorithm> #include <vector> #include <cmath> // Element structure template template <typename KeyType> struct Element { KeyType key; }; // Constants namespace constants { static const int DefaultHeapSize = 10000; }; // TwoArrayDeap class template template <typename KeyType> class TwoArrayDeap { private: Element<KeyType> *A; // Min heap array Element<KeyType> *B; // Max heap array int nA; // Number of elements in min heap int nB; // Number of elements in max heap int n; // Total number of elements int MaxSize; // Maximum allowable size public: // Constructor TwoArrayDeap(const int sz = constants::DefaultHeapSize) : MaxSize(sz), n(0) { A = new Element<KeyType>[MaxSize/2 + 2]; B = new Element<KeyType>[MaxSize/2 + 2]; nA = nB = 0; } // Destructor ~TwoArrayDeap() { delete[] A; delete[] B; } void Initialize(const Element<KeyType>* input, int size) { if (size > MaxSize) { throw std::overflow_error("Input size exceeds maximum deap size"); } // Setting the size of the heaps n = size; // Calculate the size of the min heap (A) // it should be the largest perfect binary tree that fits the height of the // binary tree. nA = (1 << static_cast<int>(floor(log2(size + 1)))) - 1; nB = n - nA; // First, copy all elements to arrays A and B for (int i = 0; i < nA; i++) { A[i + 1] = input[i]; } for (int i = 0; i < nB; i++) { B[i + 1] = input[nA + i]; } // Step 1: Establish min-max partnerships // For each node in A, ensure its partner in B (if it exists) is larger for (int i = 1; i <= nA; i++) { int partner = MinPartner(i); if (partner <= nB && A[i].key > B[partner].key) { std::swap(A[i], B[partner]); } } // Step 2: Heapify both trees while maintaining partnerships // Start from the bottom-most level and work up // Step 3: Heapify min heap (A) for (int i = nA; i >= 1; i--) { int current = i; Element<KeyType> temp = A[current]; // Bubble up in min heap while (current > 1) { int parent = current / 2; if (A[parent].key <= temp.key) break; A[current] = A[parent]; current = parent; } A[current] = temp; // Check and fix partnership after each swap int partner = MinPartner(current); if (partner <= nB && A[current].key > B[partner].key) { std::swap(A[current], B[partner]); } } // Step 4: Heapify max heap (B) for (int i = nB; i >= 1; i--) { int current = i; Element<KeyType> temp = B[current]; // Bubble up in max heap while (current > 1) { int parent = current / 2; if (B[parent].key >= temp.key) break; B[current] = B[parent]; current = parent; } B[current] = temp; // Check and fix partnership after each swap int partner = MaxPartner(current); if (partner <= nA && B[current].key < A[partner].key) { std::swap(B[current], A[partner]); } } } // For a node in array A (min heap), returns its partner index in array B (max heap) int MaxPartner(int i) { if (i <= 0) return 0; // Get the level and position in level int level = static_cast<int>(floor(log2(i))); int posInLevel = i - (1 << level); // Partner is in the same relative position in its level return (1 << level) + posInLevel; } // For a node in array B (max heap), returns its partner index in array A (min heap) int MinPartner(int i) { if (i <= 0) return 0; // Get the level and position in level int level = static_cast<int>(floor(log2(i))); int posInLevel = i - (1 << level); // Partner is in the same level but earlier position return (1 << level) + posInLevel; } // Print function to validate correctness void printTwoArrayDeap() { if (n == 0) { std::cout << "Empty deap" << std::endl; return; } int totalElements = nA + nB; int levels = static_cast<int>(std::ceil(std::log2(totalElements + 1))); std::cout << "Data set:" << std::endl; int elementsPrinted = 0; for (int level = 1; level < levels + 1; level++) { std::cout << "Level " << level << ": "; int start = 1 << (level - 1); int end = 1 << level; bool firstInLevel = true; for (int i = start; i < end && i <= nA; i++) { if (!firstInLevel) std::cout << ", "; std::cout << A[i].key; firstInLevel = false; elementsPrinted++; } for (int i = start; i < end && i <= nB; i++) { if (!firstInLevel) std::cout << ", "; std::cout << B[i].key; firstInLevel = false; elementsPrinted++; } std::cout << std::endl; if (elementsPrinted >= totalElements) break; } std::cout << std::endl; // Print Min heap std::cout << "Min heap:" << std::endl; if (nA > 0) { std::cout << "root: " << A[1].key << std::endl; for (int level = 1; level < levels; level++) { int start = 1 << level; int end = 1 << (level + 1); bool firstInLevel = true; bool hasElementsInLevel = false; for (int i = start; i < end && i <= nA; i++) { if (!firstInLevel) std::cout << ", "; if (!hasElementsInLevel) hasElementsInLevel = true; int parent = i / 2; std::cout << A[i].key << "(under " << A[parent].key << ")"; firstInLevel = false; } if (hasElementsInLevel) std::cout << std::endl; } } std::cout << std::endl; // Print Max heap std::cout << "Max heap:" << std::endl; if (nB > 0) { std::cout << "root: " << B[1].key << std::endl; for (int level = 1; level < levels; level++) { int start = 1 << level; int end = 1 << (level + 1); bool firstInLevel = true; bool hasElementsInLevel = false; for (int i = start; i < end && i <= nB; i++) { if (!firstInLevel) std::cout << ", "; if (!hasElementsInLevel) hasElementsInLevel = true; int parent = i / 2; std::cout << B[i].key << "(under " << B[parent].key << ")"; firstInLevel = false; } if (hasElementsInLevel) std::cout << std::endl; } } std::cout << std::endl; } }; int main() { std::cout << "TEST 2: Testing Correctness of Two-Array Deap.\n" << std::endl; TwoArrayDeap<int> twoArrayDeap(20); Element<int> twoArrayInput[] = { {5}, {8}, {9}, {10}, {15}, {19}, {20}, {25}, {30}, {40}, {45} }; std::cout << "Test 2-1: Initialization of two-array deap with 11 elements.\n"; twoArrayDeap.Initialize(twoArrayInput, 11); twoArrayDeap.printTwoArrayDeap(); return 0; } The Problem: I was able to establish the upper and lower bound for nA as a function of nB, which was nB <= nA <= 2nB + 1. However, I have a hard time determining which node of maximum heap B corresponds to the node of minimum heap A. In my MinPartner and MaxPartner functions, I attempted to write the partnership functions using level-based calculations. When initializing the DEAP, I'm noticing that the partnerships between nodes aren't being established correctly. For example, in the image, node 5 should partner with 45, node 10 with 25, and node 8 with 40, but my current implementation isn't achieving this.
How can I modify the Initialize function, the MinPartner and the MaxPartner functions to correctly establish partnerships between nodes at the same level in the min and max heaps?

#include <vector>, but failed to actually use it for things like this:Element<KeyType> *A; Element<KeyType> *B;