Advertisement
TheLegend12

Untitled

Nov 10th, 2024
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.44 KB | None | 0 0
  1. prqueue.h code below:
  2. #pragma once
  3.  
  4. #include <iostream>
  5. #include <sstream>
  6. #include <string>
  7.  
  8. using namespace std;
  9.  
  10. template <typename T>
  11. class prqueue {
  12.  public:
  13.   struct NODE {
  14.     int priority;
  15.     T value;
  16.     NODE* parent;
  17.     NODE* left;
  18.     NODE* right;
  19.     NODE* link;  // Link to duplicates
  20.  
  21.     NODE(int p, T v)
  22.         : priority(p), value(v), parent(nullptr), left(nullptr), right(nullptr), link(nullptr) {}
  23.   };
  24.  
  25.  private:
  26.   NODE* root;
  27.   size_t sz;
  28.  
  29.  public:
  30.   // Default constructor
  31.   prqueue() : root(nullptr), sz(0) {}
  32.  
  33.   // size() function
  34.   size_t size() const {
  35.     return sz;
  36.   }
  37.  
  38.   // getRoot() function
  39.   NODE* getRoot() {
  40.     return root;
  41.   }
  42.  
  43.   // enqueue() function
  44.   void enqueue(T value, int priority) {
  45.     NODE* newNode = new NODE(priority, value);
  46.     if (root == nullptr) {
  47.       root = newNode;
  48.     } else {
  49.       NODE* current = root;
  50.       NODE* parent = nullptr;
  51.       while (current != nullptr) {
  52.         parent = current;
  53.         if (priority < current->priority) {
  54.           current = current->left;
  55.         } else if (priority > current->priority) {
  56.           current = current->right;
  57.         } else {
  58.           // Duplicate priority, add to link list
  59.           NODE* temp = current;
  60.           while (temp->link != nullptr) {
  61.             temp = temp->link;
  62.           }
  63.           temp->link = newNode;
  64.           sz++;
  65.           return;
  66.         }
  67.       }
  68.       newNode->parent = parent;
  69.       if (priority < parent->priority) {
  70.         parent->left = newNode;
  71.       } else {
  72.         parent->right = newNode;
  73.       }
  74.     }
  75.     sz++;
  76.   }
  77.  
  78.   // clear() function
  79.   void clear() {
  80.     clearHelper(root);
  81.     root = nullptr;
  82.     sz = 0;
  83.   }
  84.  
  85.   // Destructor
  86.   ~prqueue() {
  87.     clear();
  88.   }
  89.  
  90.   // peek() function
  91.   T peek() const {
  92.     if (root == nullptr) return T{};
  93.     return peekHelper(root);
  94.   }
  95.  
  96.   // dequeue() function
  97.   T dequeue() {
  98.     if (root == nullptr) return T{};
  99.     T retValue;
  100.     root = dequeueHelper(root, retValue);
  101.     if (root != nullptr)
  102.       root->parent = nullptr;
  103.     sz--;
  104.     return retValue;
  105.   }
  106.  
  107.   // as_string() function
  108.   string as_string() const {
  109.     ostringstream oss;
  110.     asStringHelper(root, oss);
  111.     return oss.str();
  112.   }
  113.  
  114.  private:
  115.   // Helper function for clear()
  116.   void clearHelper(NODE* node) {
  117.     if (node == nullptr) return;
  118.     clearHelper(node->left);
  119.     clearHelper(node->right);
  120.     // Delete linked duplicates
  121.     NODE* linkNode = node->link;
  122.     while (linkNode != nullptr) {
  123.       NODE* temp = linkNode;
  124.       linkNode = linkNode->link;
  125.       delete temp;
  126.     }
  127.     delete node;
  128.   }
  129.  
  130.   // Recursive helper for peek()
  131.   T peekHelper(NODE* node) const {
  132.     if (node->left == nullptr)
  133.       return node->value;
  134.     else
  135.       return peekHelper(node->left);
  136.   }
  137.  
  138.   // Recursive helper for dequeue()
  139.   NODE* dequeueHelper(NODE* node, T& retValue) {
  140.     if (node == nullptr)
  141.       return nullptr;
  142.  
  143.     if (node->left != nullptr) {
  144.       node->left = dequeueHelper(node->left, retValue);
  145.       if (node->left != nullptr)
  146.         node->left->parent = node;
  147.       return node;
  148.     } else {
  149.       // Found the node to remove
  150.       retValue = node->value;
  151.  
  152.       if (node->link != nullptr) {
  153.         // Promote the next node in the link chain
  154.         NODE* tempNode = node->link;
  155.         node->value = tempNode->value;
  156.         node->link = tempNode->link;
  157.         delete tempNode;
  158.         return node;
  159.       } else {
  160.         // No duplicates, need to remove this node
  161.         NODE* replacement = nullptr;
  162.         if (node->right != nullptr) {
  163.           replacement = node->right;
  164.           replacement->parent = node->parent;
  165.         }
  166.         delete node;
  167.         return replacement;
  168.       }
  169.     }
  170.   }
  171.  
  172.   // Recursive helper for as_string()
  173.   void asStringHelper(NODE* node, ostringstream& oss) const {
  174.     if (node == nullptr)
  175.       return;
  176.     asStringHelper(node->left, oss);
  177.     // Output current node
  178.     oss << node->priority << " value: " << node->value << "\n";
  179.     // Output linked duplicates
  180.     NODE* linkNode = node->link;
  181.     while (linkNode != nullptr) {
  182.       oss << linkNode->priority << " value: " << linkNode->value << "\n";
  183.       linkNode = linkNode->link;
  184.     }
  185.     asStringHelper(node->right, oss);
  186.   }
  187. };
  188.  
  189. prqueue_tests.cpp code below:
  190. // Don't change this or you will be sad :(
  191. #include <prqueue.h>
  192.  
  193. #include "gmock/gmock.h"
  194. #include "gtest/gtest.h"
  195.  
  196. using namespace std;
  197. using namespace testing;
  198.  
  199. // Test suite for PRQueueCore
  200. // You can run your own tests on your code using make test_core.
  201.  
  202. // Test for Default constructor for the prqueue
  203. TEST(PRQueueCore, DefaultConstructor) {
  204.   prqueue<int> pq;
  205.   // Test that size is 0
  206.   EXPECT_EQ(pq.size(), 0) << "Default constructor should set size to 0.";
  207.   // Test that root is nullptr
  208.   EXPECT_EQ(pq.getRoot(), nullptr) << "Default constructor should set root to nullptr.";
  209. }
  210.  
  211. // Test for size and getRoot functions
  212. TEST(PRQueueCore, SizeAndGetRoot) {
  213.   prqueue<int> pq;
  214.   // Initially size should be 0
  215.   EXPECT_EQ(pq.size(), 0) << "Initial size should be 0.";
  216.   EXPECT_EQ(pq.getRoot(), nullptr) << "Initial root should be nullptr.";
  217.  
  218.   // Enqueue one element
  219.   pq.enqueue(42, 1);
  220.   EXPECT_EQ(pq.size(), 1) << "Size should be 1 after one enqueue.";
  221.   EXPECT_NE(pq.getRoot(), nullptr) << "Root should not be nullptr after enqueue.";
  222.   EXPECT_EQ(pq.getRoot()->value, 42) << "Root node should have value 42.";
  223.   EXPECT_EQ(pq.getRoot()->priority, 1) << "Root node should have priority 1.";
  224.  
  225.   // Enqueue another element
  226.   pq.enqueue(84, 2);
  227.   EXPECT_EQ(pq.size(), 2) << "Size should be 2 after two enqueues.";
  228.  
  229.   // Check the structure
  230.   auto root = pq.getRoot();
  231.   EXPECT_EQ(root->value, 42);
  232.   EXPECT_EQ(root->priority, 1);
  233.   EXPECT_EQ(root->right->value, 84);
  234.   EXPECT_EQ(root->right->priority, 2);
  235. }
  236.  
  237. // Test for enqueue function
  238. TEST(PRQueueCore, Enqueue) {
  239.   prqueue<int> pq;
  240.  
  241.   // Enqueue elements
  242.   pq.enqueue(20, 2);
  243.   pq.enqueue(10, 1);
  244.   pq.enqueue(30, 3);
  245.  
  246.   // Check size
  247.   EXPECT_EQ(pq.size(), 3) << "Size should be 3 after three enqueues.";
  248.  
  249.   // Check root node
  250.   auto root = pq.getRoot();
  251.   EXPECT_NE(root, nullptr) << "Root should not be nullptr.";
  252.   EXPECT_EQ(root->priority, 2) << "Root priority should be 2.";
  253.   EXPECT_EQ(root->value, 20) << "Root value should be 20.";
  254.  
  255.   // Check left child
  256.   EXPECT_NE(root->left, nullptr) << "Root should have left child.";
  257.   EXPECT_EQ(root->left->priority, 1) << "Left child priority should be 1.";
  258.   EXPECT_EQ(root->left->value, 10) << "Left child value should be 10.";
  259.  
  260.   // Check right child
  261.   EXPECT_NE(root->right, nullptr) << "Root should have right child.";
  262.   EXPECT_EQ(root->right->priority, 3) << "Right child priority should be 3.";
  263.   EXPECT_EQ(root->right->value, 30) << "Right child value should be 30.";
  264.  
  265.   // Enqueue duplicate priority
  266.   pq.enqueue(25, 2);
  267.   EXPECT_EQ(pq.size(), 4) << "Size should be 4 after enqueuing duplicate priority.";
  268.  
  269.   // Check that duplicate is linked correctly
  270.   EXPECT_NE(root->link, nullptr) << "Root node should have link to duplicate.";
  271.   EXPECT_EQ(root->link->value, 25) << "Duplicate node should have value 25.";
  272.   EXPECT_EQ(root->link->priority, 2) << "Duplicate node should have priority 2.";
  273. }
  274.  
  275. // Test for clear function
  276. TEST(PRQueueCore, Clear) {
  277.   prqueue<int> pq;
  278.   // Enqueue elements
  279.   pq.enqueue(20, 2);
  280.   pq.enqueue(10, 1);
  281.   pq.enqueue(30, 3);
  282.  
  283.   // Clear the queue
  284.   pq.clear();
  285.  
  286.   // Check size
  287.   EXPECT_EQ(pq.size(), 0) << "Size should be 0 after clear.";
  288.  
  289.   // Check root
  290.   EXPECT_EQ(pq.getRoot(), nullptr) << "Root should be nullptr after clear.";
  291. }
  292.  
  293. // Test for destructor for prqueue
  294. TEST(PRQueueCore, Destructor) {
  295.   prqueue<int>* pq = new prqueue<int>();
  296.   pq->enqueue(10, 1);
  297.   pq->enqueue(20, 2);
  298.   pq->enqueue(30, 3);
  299.   delete pq;
  300.   SUCCEED() << "Destructor should not cause any memory leaks or crashes.";
  301. }
  302.  
  303. // Additional tests to catch buggy solutions
  304.  
  305. // Test default constructor sets size incorrectly
  306. TEST(PRQueueCore, DefaultConstructor_BuggySize) {
  307.   prqueue<int> pq;
  308.   EXPECT_EQ(pq.size(), 0) << "Default constructor should initialize size to 0.";
  309. }
  310.  
  311. // Test default constructor sets root incorrectly
  312. TEST(PRQueueCore, DefaultConstructor_BuggyRoot) {
  313.   prqueue<int> pq;
  314.   EXPECT_EQ(pq.getRoot(), nullptr) << "Default constructor should initialize root to nullptr.";
  315. }
  316.  
  317. // Test size returns incorrect value
  318. TEST(PRQueueCore, Size_BuggyImplementation) {
  319.   prqueue<int> pq;
  320.   pq.enqueue(1, 1);
  321.   pq.enqueue(2, 2);
  322.   pq.enqueue(3, 3);
  323.   EXPECT_EQ(pq.size(), 3) << "Size should be 3 after enqueuing 3 elements.";
  324. }
  325.  
  326. // Test enqueue does not update size properly
  327. TEST(PRQueueCore, Enqueue_BuggySizeUpdate) {
  328.   prqueue<int> pq;
  329.   pq.enqueue(1, 1);
  330.   EXPECT_EQ(pq.size(), 1) << "Size should be 1 after one enqueue.";
  331.   pq.enqueue(2, 2);
  332.   EXPECT_EQ(pq.size(), 2) << "Size should be 2 after two enqueues.";
  333. }
  334.  
  335. // Test enqueue finds incorrect node to insert as child
  336. TEST(PRQueueCore, Enqueue_WrongInsertion) {
  337.   prqueue<int> pq;
  338.   pq.enqueue(20, 2);
  339.   pq.enqueue(10, 3);  // Incorrect ordering if placed on left
  340.   auto root = pq.getRoot();
  341.   EXPECT_NE(root->right, nullptr) << "Second node should be right child.";
  342.   EXPECT_EQ(root->right->value, 10) << "Right child should have value 10.";
  343. }
  344.  
  345. // Test enqueue places new node in the wrong place
  346. TEST(PRQueueCore, Enqueue_WrongPlacement) {
  347.   prqueue<int> pq;
  348.   pq.enqueue(20, 2);
  349.   pq.enqueue(10, 1);
  350.   auto root = pq.getRoot();
  351.   EXPECT_NE(root->left, nullptr) << "Second node should be left child.";
  352.   EXPECT_EQ(root->left->value, 10) << "Left child should have value 10.";
  353. }
  354.  
  355. // Test clear resets the size incorrectly
  356. TEST(PRQueueCore, Clear_BuggySizeReset) {
  357.   prqueue<int> pq;
  358.   pq.enqueue(1, 1);
  359.   pq.clear();
  360.   EXPECT_EQ(pq.size(), 0) << "Size should be 0 after clear.";
  361. }
  362.  
  363. // Test clear does not reset the value of the root
  364. TEST(PRQueueCore, Clear_BuggyRootReset) {
  365.   prqueue<int> pq;
  366.   pq.enqueue(1, 1);
  367.   pq.clear();
  368.   EXPECT_EQ(pq.getRoot(), nullptr) << "Root should be nullptr after clear.";
  369. }
  370.  
  371. TEST(PRQueueUsing, AsStringIncludesAllElements) {
  372.   prqueue<string> pq;
  373.   pq.enqueue("Task1", 3);
  374.   pq.enqueue("Task2", 1);
  375.   pq.enqueue("Task3", 2);
  376.   pq.enqueue("Task4", 2);  // Duplicate priority
  377.  
  378.   string expected = "1 value: Task2\n2 value: Task3\n2 value: Task4\n3 value: Task1\n";
  379.   string actual = pq.as_string();
  380.  
  381.   EXPECT_EQ(actual, expected) << "as_string() should include all elements in the correct order and format.";
  382. }
  383.  
  384. TEST(PRQueueUsing, AsStringProperlyFormatted) {
  385.   prqueue<int> pq;
  386.   pq.enqueue(10, 2);
  387.   pq.enqueue(20, 1);
  388.   pq.enqueue(30, 3);
  389.  
  390.   string expected = "1 value: 20\n2 value: 10\n3 value: 30\n";
  391.   string actual = pq.as_string();
  392.  
  393.   EXPECT_EQ(actual, expected) << "as_string() should return a properly formatted string.";
  394. }
  395.  
  396. TEST(PRQueueUsing, AsStringEmptyQueue) {
  397.   prqueue<int> pq;
  398.   string expected = "";
  399.   string actual = pq.as_string();
  400.  
  401.   EXPECT_EQ(actual, expected) << "as_string() of an empty queue should return an empty string.";
  402. }
  403.  
  404. //
  405. // Test for peek function
  406. //
  407. TEST(PRQueueUsing, PeekReturnsCorrectValue) {
  408.   prqueue<string> pq;
  409.   pq.enqueue("Task1", 5);
  410.   pq.enqueue("Task2", 3);
  411.   pq.enqueue("Task3", 4);
  412.   pq.enqueue("Task4", 1);
  413.  
  414.   EXPECT_EQ(pq.peek(), "Task4") << "peek() should return the value with the smallest priority.";
  415. }
  416.  
  417. TEST(PRQueueUsing, PeekWithDuplicates) {
  418.   prqueue<string> pq;
  419.   pq.enqueue("Task1", 2);
  420.   pq.enqueue("Task2", 2);
  421.   pq.enqueue("Task3", 3);
  422.  
  423.   EXPECT_EQ(pq.peek(), "Task1") << "peek() should return the first value inserted among duplicates.";
  424. }
  425.  
  426. TEST(PRQueueUsing, PeekEmptyQueue) {
  427.   prqueue<int> pq;
  428.   EXPECT_EQ(pq.peek(), 0) << "peek() on an empty queue should return the default value.";
  429. }
  430.  
  431. //
  432. // Test for dequeue function
  433. //
  434. TEST(PRQueueUsing, DequeueReturnsCorrectValue) {
  435.   prqueue<string> pq;
  436.   pq.enqueue("Task1", 2);
  437.   pq.enqueue("Task2", 1);
  438.   pq.enqueue("Task3", 3);
  439.  
  440.   EXPECT_EQ(pq.dequeue(), "Task2") << "dequeue() should return the value with the smallest priority.";
  441.   EXPECT_EQ(pq.size(), 2) << "Size should be decremented after dequeue.";
  442. }
  443.  
  444. TEST(PRQueueUsing, DequeueUpdatesSize) {
  445.   prqueue<int> pq;
  446.   pq.enqueue(10, 1);
  447.   pq.enqueue(20, 2);
  448.  
  449.   pq.dequeue();
  450.   EXPECT_EQ(pq.size(), 1) << "Size should be updated after dequeue.";
  451.   pq.dequeue();
  452.   EXPECT_EQ(pq.size(), 0) << "Size should be zero after dequeuing all elements.";
  453. }
  454.  
  455. TEST(PRQueueUsing, DequeueRemovesNodeFromTree) {
  456.   prqueue<int> pq;
  457.   pq.enqueue(10, 2);
  458.   pq.enqueue(5, 1);
  459.   pq.enqueue(15, 3);
  460.  
  461.   pq.dequeue();  // Removes node with value 5
  462.   EXPECT_EQ(pq.peek(), 10) << "After dequeuing, peek() should return the next smallest priority.";
  463.   EXPECT_EQ(pq.size(), 2);
  464.  
  465.   // Ensure the node with value 5 is removed
  466.   auto root = pq.getRoot();
  467.   EXPECT_EQ(root->left, nullptr) << "Left child of root should be nullptr after removal.";
  468. }
  469.  
  470. // Test for dequeue function ensuring tree remains intact
  471. TEST(PRQueueUsing, DequeueDoesNotLoseTreeParts) {
  472.   prqueue<int> pq;
  473.   pq.enqueue(20, 4);
  474.   pq.enqueue(10, 2);
  475.   pq.enqueue(30, 6);
  476.   pq.enqueue(5, 1);
  477.   pq.enqueue(15, 3);
  478.   pq.enqueue(25, 5);
  479.   pq.enqueue(35, 7);
  480.  
  481.   pq.dequeue();  // Removes node with priority 1
  482.   pq.dequeue();  // Removes node with priority 2
  483.  
  484.   // Expected priorities and values after dequeues
  485.   vector<int> expected_values = {15, 20, 25, 30, 35};
  486.   vector<int> actual_values;
  487.  
  488.   // Collect remaining values using peek() and dequeue()
  489.   while (pq.size() > 0) {
  490.     actual_values.push_back(pq.peek());
  491.     pq.dequeue();
  492.   }
  493.  
  494.   EXPECT_EQ(actual_values, expected_values) << "Tree should not lose parts when nodes are dequeued.";
  495. }
  496. TEST(PRQueueUsing, DequeueWithDuplicates) {
  497.   prqueue<string> pq;
  498.   pq.enqueue("Task1", 1);
  499.   pq.enqueue("Task2", 1);
  500.   pq.enqueue("Task3", 2);
  501.  
  502.   EXPECT_EQ(pq.dequeue(), "Task1") << "dequeue() should return the first value among duplicates.";
  503.   EXPECT_EQ(pq.peek(), "Task2") << "peek() should return the next value among duplicates.";
  504.   EXPECT_EQ(pq.size(), 2);
  505.  
  506.   pq.dequeue();
  507.   EXPECT_EQ(pq.peek(), "Task3") << "After dequeuing duplicates, peek() should return the next smallest priority.";
  508.   EXPECT_EQ(pq.size(), 1);
  509. }
  510.  
  511. TEST(PRQueueUsing, DequeueEmptyQueue) {
  512.   prqueue<int> pq;
  513.   EXPECT_EQ(pq.dequeue(), 0) << "dequeue() on an empty queue should return the default value.";
  514.   EXPECT_EQ(pq.size(), 0) << "Size should remain zero after dequeuing from an empty queue.";
  515. }
  516.  
  517.  
  518.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement