Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- prqueue.h code below:
- #pragma once
- #include <iostream>
- #include <sstream>
- #include <string>
- using namespace std;
- template <typename T>
- class prqueue {
- public:
- struct NODE {
- int priority;
- T value;
- NODE* parent;
- NODE* left;
- NODE* right;
- NODE* link; // Link to duplicates
- NODE(int p, T v)
- : priority(p), value(v), parent(nullptr), left(nullptr), right(nullptr), link(nullptr) {}
- };
- private:
- NODE* root;
- size_t sz;
- public:
- // Default constructor
- prqueue() : root(nullptr), sz(0) {}
- // size() function
- size_t size() const {
- return sz;
- }
- // getRoot() function
- NODE* getRoot() {
- return root;
- }
- // enqueue() function
- void enqueue(T value, int priority) {
- NODE* newNode = new NODE(priority, value);
- if (root == nullptr) {
- root = newNode;
- } else {
- NODE* current = root;
- NODE* parent = nullptr;
- while (current != nullptr) {
- parent = current;
- if (priority < current->priority) {
- current = current->left;
- } else if (priority > current->priority) {
- current = current->right;
- } else {
- // Duplicate priority, add to link list
- NODE* temp = current;
- while (temp->link != nullptr) {
- temp = temp->link;
- }
- temp->link = newNode;
- sz++;
- return;
- }
- }
- newNode->parent = parent;
- if (priority < parent->priority) {
- parent->left = newNode;
- } else {
- parent->right = newNode;
- }
- }
- sz++;
- }
- // clear() function
- void clear() {
- clearHelper(root);
- root = nullptr;
- sz = 0;
- }
- // Destructor
- ~prqueue() {
- clear();
- }
- // peek() function
- T peek() const {
- if (root == nullptr) return T{};
- return peekHelper(root);
- }
- // dequeue() function
- T dequeue() {
- if (root == nullptr) return T{};
- T retValue;
- root = dequeueHelper(root, retValue);
- if (root != nullptr)
- root->parent = nullptr;
- sz--;
- return retValue;
- }
- // as_string() function
- string as_string() const {
- ostringstream oss;
- asStringHelper(root, oss);
- return oss.str();
- }
- private:
- // Helper function for clear()
- void clearHelper(NODE* node) {
- if (node == nullptr) return;
- clearHelper(node->left);
- clearHelper(node->right);
- // Delete linked duplicates
- NODE* linkNode = node->link;
- while (linkNode != nullptr) {
- NODE* temp = linkNode;
- linkNode = linkNode->link;
- delete temp;
- }
- delete node;
- }
- // Recursive helper for peek()
- T peekHelper(NODE* node) const {
- if (node->left == nullptr)
- return node->value;
- else
- return peekHelper(node->left);
- }
- // Recursive helper for dequeue()
- NODE* dequeueHelper(NODE* node, T& retValue) {
- if (node == nullptr)
- return nullptr;
- if (node->left != nullptr) {
- node->left = dequeueHelper(node->left, retValue);
- if (node->left != nullptr)
- node->left->parent = node;
- return node;
- } else {
- // Found the node to remove
- retValue = node->value;
- if (node->link != nullptr) {
- // Promote the next node in the link chain
- NODE* tempNode = node->link;
- node->value = tempNode->value;
- node->link = tempNode->link;
- delete tempNode;
- return node;
- } else {
- // No duplicates, need to remove this node
- NODE* replacement = nullptr;
- if (node->right != nullptr) {
- replacement = node->right;
- replacement->parent = node->parent;
- }
- delete node;
- return replacement;
- }
- }
- }
- // Recursive helper for as_string()
- void asStringHelper(NODE* node, ostringstream& oss) const {
- if (node == nullptr)
- return;
- asStringHelper(node->left, oss);
- // Output current node
- oss << node->priority << " value: " << node->value << "\n";
- // Output linked duplicates
- NODE* linkNode = node->link;
- while (linkNode != nullptr) {
- oss << linkNode->priority << " value: " << linkNode->value << "\n";
- linkNode = linkNode->link;
- }
- asStringHelper(node->right, oss);
- }
- };
- prqueue_tests.cpp code below:
- // Don't change this or you will be sad :(
- #include <prqueue.h>
- #include "gmock/gmock.h"
- #include "gtest/gtest.h"
- using namespace std;
- using namespace testing;
- // Test suite for PRQueueCore
- // You can run your own tests on your code using make test_core.
- // Test for Default constructor for the prqueue
- TEST(PRQueueCore, DefaultConstructor) {
- prqueue<int> pq;
- // Test that size is 0
- EXPECT_EQ(pq.size(), 0) << "Default constructor should set size to 0.";
- // Test that root is nullptr
- EXPECT_EQ(pq.getRoot(), nullptr) << "Default constructor should set root to nullptr.";
- }
- // Test for size and getRoot functions
- TEST(PRQueueCore, SizeAndGetRoot) {
- prqueue<int> pq;
- // Initially size should be 0
- EXPECT_EQ(pq.size(), 0) << "Initial size should be 0.";
- EXPECT_EQ(pq.getRoot(), nullptr) << "Initial root should be nullptr.";
- // Enqueue one element
- pq.enqueue(42, 1);
- EXPECT_EQ(pq.size(), 1) << "Size should be 1 after one enqueue.";
- EXPECT_NE(pq.getRoot(), nullptr) << "Root should not be nullptr after enqueue.";
- EXPECT_EQ(pq.getRoot()->value, 42) << "Root node should have value 42.";
- EXPECT_EQ(pq.getRoot()->priority, 1) << "Root node should have priority 1.";
- // Enqueue another element
- pq.enqueue(84, 2);
- EXPECT_EQ(pq.size(), 2) << "Size should be 2 after two enqueues.";
- // Check the structure
- auto root = pq.getRoot();
- EXPECT_EQ(root->value, 42);
- EXPECT_EQ(root->priority, 1);
- EXPECT_EQ(root->right->value, 84);
- EXPECT_EQ(root->right->priority, 2);
- }
- // Test for enqueue function
- TEST(PRQueueCore, Enqueue) {
- prqueue<int> pq;
- // Enqueue elements
- pq.enqueue(20, 2);
- pq.enqueue(10, 1);
- pq.enqueue(30, 3);
- // Check size
- EXPECT_EQ(pq.size(), 3) << "Size should be 3 after three enqueues.";
- // Check root node
- auto root = pq.getRoot();
- EXPECT_NE(root, nullptr) << "Root should not be nullptr.";
- EXPECT_EQ(root->priority, 2) << "Root priority should be 2.";
- EXPECT_EQ(root->value, 20) << "Root value should be 20.";
- // Check left child
- EXPECT_NE(root->left, nullptr) << "Root should have left child.";
- EXPECT_EQ(root->left->priority, 1) << "Left child priority should be 1.";
- EXPECT_EQ(root->left->value, 10) << "Left child value should be 10.";
- // Check right child
- EXPECT_NE(root->right, nullptr) << "Root should have right child.";
- EXPECT_EQ(root->right->priority, 3) << "Right child priority should be 3.";
- EXPECT_EQ(root->right->value, 30) << "Right child value should be 30.";
- // Enqueue duplicate priority
- pq.enqueue(25, 2);
- EXPECT_EQ(pq.size(), 4) << "Size should be 4 after enqueuing duplicate priority.";
- // Check that duplicate is linked correctly
- EXPECT_NE(root->link, nullptr) << "Root node should have link to duplicate.";
- EXPECT_EQ(root->link->value, 25) << "Duplicate node should have value 25.";
- EXPECT_EQ(root->link->priority, 2) << "Duplicate node should have priority 2.";
- }
- // Test for clear function
- TEST(PRQueueCore, Clear) {
- prqueue<int> pq;
- // Enqueue elements
- pq.enqueue(20, 2);
- pq.enqueue(10, 1);
- pq.enqueue(30, 3);
- // Clear the queue
- pq.clear();
- // Check size
- EXPECT_EQ(pq.size(), 0) << "Size should be 0 after clear.";
- // Check root
- EXPECT_EQ(pq.getRoot(), nullptr) << "Root should be nullptr after clear.";
- }
- // Test for destructor for prqueue
- TEST(PRQueueCore, Destructor) {
- prqueue<int>* pq = new prqueue<int>();
- pq->enqueue(10, 1);
- pq->enqueue(20, 2);
- pq->enqueue(30, 3);
- delete pq;
- SUCCEED() << "Destructor should not cause any memory leaks or crashes.";
- }
- // Additional tests to catch buggy solutions
- // Test default constructor sets size incorrectly
- TEST(PRQueueCore, DefaultConstructor_BuggySize) {
- prqueue<int> pq;
- EXPECT_EQ(pq.size(), 0) << "Default constructor should initialize size to 0.";
- }
- // Test default constructor sets root incorrectly
- TEST(PRQueueCore, DefaultConstructor_BuggyRoot) {
- prqueue<int> pq;
- EXPECT_EQ(pq.getRoot(), nullptr) << "Default constructor should initialize root to nullptr.";
- }
- // Test size returns incorrect value
- TEST(PRQueueCore, Size_BuggyImplementation) {
- prqueue<int> pq;
- pq.enqueue(1, 1);
- pq.enqueue(2, 2);
- pq.enqueue(3, 3);
- EXPECT_EQ(pq.size(), 3) << "Size should be 3 after enqueuing 3 elements.";
- }
- // Test enqueue does not update size properly
- TEST(PRQueueCore, Enqueue_BuggySizeUpdate) {
- prqueue<int> pq;
- pq.enqueue(1, 1);
- EXPECT_EQ(pq.size(), 1) << "Size should be 1 after one enqueue.";
- pq.enqueue(2, 2);
- EXPECT_EQ(pq.size(), 2) << "Size should be 2 after two enqueues.";
- }
- // Test enqueue finds incorrect node to insert as child
- TEST(PRQueueCore, Enqueue_WrongInsertion) {
- prqueue<int> pq;
- pq.enqueue(20, 2);
- pq.enqueue(10, 3); // Incorrect ordering if placed on left
- auto root = pq.getRoot();
- EXPECT_NE(root->right, nullptr) << "Second node should be right child.";
- EXPECT_EQ(root->right->value, 10) << "Right child should have value 10.";
- }
- // Test enqueue places new node in the wrong place
- TEST(PRQueueCore, Enqueue_WrongPlacement) {
- prqueue<int> pq;
- pq.enqueue(20, 2);
- pq.enqueue(10, 1);
- auto root = pq.getRoot();
- EXPECT_NE(root->left, nullptr) << "Second node should be left child.";
- EXPECT_EQ(root->left->value, 10) << "Left child should have value 10.";
- }
- // Test clear resets the size incorrectly
- TEST(PRQueueCore, Clear_BuggySizeReset) {
- prqueue<int> pq;
- pq.enqueue(1, 1);
- pq.clear();
- EXPECT_EQ(pq.size(), 0) << "Size should be 0 after clear.";
- }
- // Test clear does not reset the value of the root
- TEST(PRQueueCore, Clear_BuggyRootReset) {
- prqueue<int> pq;
- pq.enqueue(1, 1);
- pq.clear();
- EXPECT_EQ(pq.getRoot(), nullptr) << "Root should be nullptr after clear.";
- }
- TEST(PRQueueUsing, AsStringIncludesAllElements) {
- prqueue<string> pq;
- pq.enqueue("Task1", 3);
- pq.enqueue("Task2", 1);
- pq.enqueue("Task3", 2);
- pq.enqueue("Task4", 2); // Duplicate priority
- string expected = "1 value: Task2\n2 value: Task3\n2 value: Task4\n3 value: Task1\n";
- string actual = pq.as_string();
- EXPECT_EQ(actual, expected) << "as_string() should include all elements in the correct order and format.";
- }
- TEST(PRQueueUsing, AsStringProperlyFormatted) {
- prqueue<int> pq;
- pq.enqueue(10, 2);
- pq.enqueue(20, 1);
- pq.enqueue(30, 3);
- string expected = "1 value: 20\n2 value: 10\n3 value: 30\n";
- string actual = pq.as_string();
- EXPECT_EQ(actual, expected) << "as_string() should return a properly formatted string.";
- }
- TEST(PRQueueUsing, AsStringEmptyQueue) {
- prqueue<int> pq;
- string expected = "";
- string actual = pq.as_string();
- EXPECT_EQ(actual, expected) << "as_string() of an empty queue should return an empty string.";
- }
- //
- // Test for peek function
- //
- TEST(PRQueueUsing, PeekReturnsCorrectValue) {
- prqueue<string> pq;
- pq.enqueue("Task1", 5);
- pq.enqueue("Task2", 3);
- pq.enqueue("Task3", 4);
- pq.enqueue("Task4", 1);
- EXPECT_EQ(pq.peek(), "Task4") << "peek() should return the value with the smallest priority.";
- }
- TEST(PRQueueUsing, PeekWithDuplicates) {
- prqueue<string> pq;
- pq.enqueue("Task1", 2);
- pq.enqueue("Task2", 2);
- pq.enqueue("Task3", 3);
- EXPECT_EQ(pq.peek(), "Task1") << "peek() should return the first value inserted among duplicates.";
- }
- TEST(PRQueueUsing, PeekEmptyQueue) {
- prqueue<int> pq;
- EXPECT_EQ(pq.peek(), 0) << "peek() on an empty queue should return the default value.";
- }
- //
- // Test for dequeue function
- //
- TEST(PRQueueUsing, DequeueReturnsCorrectValue) {
- prqueue<string> pq;
- pq.enqueue("Task1", 2);
- pq.enqueue("Task2", 1);
- pq.enqueue("Task3", 3);
- EXPECT_EQ(pq.dequeue(), "Task2") << "dequeue() should return the value with the smallest priority.";
- EXPECT_EQ(pq.size(), 2) << "Size should be decremented after dequeue.";
- }
- TEST(PRQueueUsing, DequeueUpdatesSize) {
- prqueue<int> pq;
- pq.enqueue(10, 1);
- pq.enqueue(20, 2);
- pq.dequeue();
- EXPECT_EQ(pq.size(), 1) << "Size should be updated after dequeue.";
- pq.dequeue();
- EXPECT_EQ(pq.size(), 0) << "Size should be zero after dequeuing all elements.";
- }
- TEST(PRQueueUsing, DequeueRemovesNodeFromTree) {
- prqueue<int> pq;
- pq.enqueue(10, 2);
- pq.enqueue(5, 1);
- pq.enqueue(15, 3);
- pq.dequeue(); // Removes node with value 5
- EXPECT_EQ(pq.peek(), 10) << "After dequeuing, peek() should return the next smallest priority.";
- EXPECT_EQ(pq.size(), 2);
- // Ensure the node with value 5 is removed
- auto root = pq.getRoot();
- EXPECT_EQ(root->left, nullptr) << "Left child of root should be nullptr after removal.";
- }
- // Test for dequeue function ensuring tree remains intact
- TEST(PRQueueUsing, DequeueDoesNotLoseTreeParts) {
- prqueue<int> pq;
- pq.enqueue(20, 4);
- pq.enqueue(10, 2);
- pq.enqueue(30, 6);
- pq.enqueue(5, 1);
- pq.enqueue(15, 3);
- pq.enqueue(25, 5);
- pq.enqueue(35, 7);
- pq.dequeue(); // Removes node with priority 1
- pq.dequeue(); // Removes node with priority 2
- // Expected priorities and values after dequeues
- vector<int> expected_values = {15, 20, 25, 30, 35};
- vector<int> actual_values;
- // Collect remaining values using peek() and dequeue()
- while (pq.size() > 0) {
- actual_values.push_back(pq.peek());
- pq.dequeue();
- }
- EXPECT_EQ(actual_values, expected_values) << "Tree should not lose parts when nodes are dequeued.";
- }
- TEST(PRQueueUsing, DequeueWithDuplicates) {
- prqueue<string> pq;
- pq.enqueue("Task1", 1);
- pq.enqueue("Task2", 1);
- pq.enqueue("Task3", 2);
- EXPECT_EQ(pq.dequeue(), "Task1") << "dequeue() should return the first value among duplicates.";
- EXPECT_EQ(pq.peek(), "Task2") << "peek() should return the next value among duplicates.";
- EXPECT_EQ(pq.size(), 2);
- pq.dequeue();
- EXPECT_EQ(pq.peek(), "Task3") << "After dequeuing duplicates, peek() should return the next smallest priority.";
- EXPECT_EQ(pq.size(), 1);
- }
- TEST(PRQueueUsing, DequeueEmptyQueue) {
- prqueue<int> pq;
- EXPECT_EQ(pq.dequeue(), 0) << "dequeue() on an empty queue should return the default value.";
- EXPECT_EQ(pq.size(), 0) << "Size should remain zero after dequeuing from an empty queue.";
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement