From f78e0eac6bd8a9f52bf32884c0a342847b5b945c Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Sun, 15 Dec 2024 22:28:05 +0530 Subject: [PATCH 1/7] feature: mst kruskal initial code --- ...0007_MinimumSpanningTreeKruskalAlgorithm.h | 43 +++++++++ ...007_MinimumSpanningTreeKruskalAlgorithm.cc | 87 +++++++++++++++++++ SourceCodes/0003_Graph/CMakeLists.txt | 2 + ...MinimumSpanningTreeKruskalAlgorithmTest.cc | 0 Tests/0003_Graph/CMakeLists.txt | 1 + 5 files changed, 133 insertions(+) create mode 100644 Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h create mode 100644 SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc create mode 100644 Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc diff --git a/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h new file mode 100644 index 0000000..b5ac1c5 --- /dev/null +++ b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +using namespace std; + +namespace MinimumSpanningTreeKruskalAlgorithm +{ + class Node + { + public: + int data; + Node* parent; + int rank; + Node(int data); + }; + + class Edge + { + public: + Node* nodeU; + Node* nodeV; + int weight; + Edge(Node* nodeU, Node* nodeV, int weight); + bool CompareEdges(Edge* edgeX, Edge* edgeY); + }; + + class Graph + { + private: + map> _adjlist; + map _nodeMap; + Node* MakeOrFindNode(int data); + void MakeSet(Node* node); + void Union(Node* nodeU, Node* nodeV); + void Link(Node* nodeU, Node* nodeV); + Node* FindSet(Node* node); + + public: + void PushUndirectedEdge(int valueU, int valueV); + void FindMinimumSpanningTreeKruskalAlgorithm(); + }; +} \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc new file mode 100644 index 0000000..202950a --- /dev/null +++ b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc @@ -0,0 +1,87 @@ +#include "../Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h" +#include +using namespace std; + +namespace MinimumSpanningTreeKruskalAlgorithm +{ + Node::Node(int data) + { + this->data = data; + this->parent = nullptr; + this->rank = INT_MAX; + } + + Edge::Edge(Node* nodeU, Node* nodeV, int weight) + { + this->nodeU = nodeU; + this->nodeV = nodeV; + this->weight = weight; + } + + bool Edge::CompareEdges(Edge* edgeX, Edge* edgeY) + { + return (edgeX->weight < edgeY->weight); + } + + // Graph Private Member Methods + Node* Graph::MakeOrFindNode(int data) + { + Node* node = nullptr; + if (this->_nodeMap.find(data) == this->_nodeMap.end()) + { + node = new Node(data); + this->_nodeMap[data] = node; + } + else + { + node = this->_nodeMap[data]; + } + return node; + } + + void Graph::MakeSet(Node* node) + { + node->parent = node; + node->rank = 0; + } + + void Graph::Union(Node* nodeU, Node* nodeV) + { + this->Link(this->FindSet(nodeU), this->FindSet(nodeV)); + } + + void Graph::Link(Node* nodeU, Node* nodeV) + { + if (nodeV->rank > nodeU->rank) + { + nodeU->parent = nodeV; + } + else + { + nodeV->parent = nodeU; + if (nodeU->rank == nodeV->rank) + { + nodeU->rank += 1; + } + } + } + + Node* Graph::FindSet(Node* node) + { + if (node != node->parent) + { + node->parent = this->FindSet(node->parent); + } + return node->parent; + } + + // Graph Public Member Methods + void Graph::PushUndirectedEdge(int dataU, int dataV) + { + Node* nodeU = this->MakeOrFindNode(dataU); + Node* nodeV = this->MakeOrFindNode(dataV); + + this->_adjlist[nodeU].push_back(nodeV); + this->_adjlist[nodeV].push_back(nodeU); + } +} \ No newline at end of file diff --git a/SourceCodes/0003_Graph/CMakeLists.txt b/SourceCodes/0003_Graph/CMakeLists.txt index 4391ac4..68612e3 100644 --- a/SourceCodes/0003_Graph/CMakeLists.txt +++ b/SourceCodes/0003_Graph/CMakeLists.txt @@ -6,6 +6,8 @@ set(0003GRAPH_SOURCES 0004_StronglyConnectedComponents.cc 0005_HamiltonianPathAndCycle.cc 0006_EulerianPathAndCircuit.cc + 0007_MinimumSpanningTreeKruskalAlgorithm.cc + ) # Create a library target diff --git a/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc b/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc new file mode 100644 index 0000000..e69de29 diff --git a/Tests/0003_Graph/CMakeLists.txt b/Tests/0003_Graph/CMakeLists.txt index 3810012..b355b1e 100644 --- a/Tests/0003_Graph/CMakeLists.txt +++ b/Tests/0003_Graph/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable( 0004_StronglyConnectedComponentsTest.cc 0005_HamiltonianPathAndCycleTest.cc 0006_EulerianPathAndCircuitTest.cc + 0007_MinimumSpanningTreeKruskalAlgorithmTest.cc ) target_link_libraries( From 6ab200ada53c051833a7ce8575ce55c9bfadc297 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Tue, 17 Dec 2024 01:41:05 +0530 Subject: [PATCH 2/7] feature: kruskal algo logic added --- ...0007_MinimumSpanningTreeKruskalAlgorithm.h | 8 +++- ...007_MinimumSpanningTreeKruskalAlgorithm.cc | 37 ++++++++++++++++--- ...MinimumSpanningTreeKruskalAlgorithmTest.cc | 30 +++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h index b5ac1c5..8441447 100644 --- a/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h +++ b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h @@ -2,6 +2,7 @@ #include #include +#include using namespace std; namespace MinimumSpanningTreeKruskalAlgorithm @@ -22,7 +23,6 @@ namespace MinimumSpanningTreeKruskalAlgorithm Node* nodeV; int weight; Edge(Node* nodeU, Node* nodeV, int weight); - bool CompareEdges(Edge* edgeX, Edge* edgeY); }; class Graph @@ -30,6 +30,8 @@ namespace MinimumSpanningTreeKruskalAlgorithm private: map> _adjlist; map _nodeMap; + vector _edgeList; + vector, int>> _minimumSpanningTree; Node* MakeOrFindNode(int data); void MakeSet(Node* node); void Union(Node* nodeU, Node* nodeV); @@ -37,7 +39,9 @@ namespace MinimumSpanningTreeKruskalAlgorithm Node* FindSet(Node* node); public: - void PushUndirectedEdge(int valueU, int valueV); + void PushUndirectedEdge(int valueU, int valueV, int weight); void FindMinimumSpanningTreeKruskalAlgorithm(); + vector, int>> GetMinimumSpanningTree(); + vector GetSortedEdgeList(); }; } \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc index 202950a..462982d 100644 --- a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc +++ b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc @@ -1,5 +1,6 @@ #include "../Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h" #include +#include using namespace std; namespace MinimumSpanningTreeKruskalAlgorithm @@ -17,11 +18,6 @@ namespace MinimumSpanningTreeKruskalAlgorithm this->nodeV = nodeV; this->weight = weight; } - - bool Edge::CompareEdges(Edge* edgeX, Edge* edgeY) - { - return (edgeX->weight < edgeY->weight); - } // Graph Private Member Methods Node* Graph::MakeOrFindNode(int data) @@ -76,12 +72,41 @@ namespace MinimumSpanningTreeKruskalAlgorithm } // Graph Public Member Methods - void Graph::PushUndirectedEdge(int dataU, int dataV) + void Graph::PushUndirectedEdge(int dataU, int dataV, int weight) { Node* nodeU = this->MakeOrFindNode(dataU); Node* nodeV = this->MakeOrFindNode(dataV); this->_adjlist[nodeU].push_back(nodeV); this->_adjlist[nodeV].push_back(nodeU); + this->_edgeList.push_back(new Edge(nodeU, nodeV, weight)); + } + void Graph::FindMinimumSpanningTreeKruskalAlgorithm() + { + for (auto iterator : this->_nodeMap) + { + this->MakeSet(iterator.second); + } + + sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) {return edgeX->weight < edgeY->weight; }); + + for (auto edge : this->_edgeList) + { + if (this->FindSet(edge->nodeU) != this->FindSet(edge->nodeV)) + { + this->Union(edge->nodeU, edge->nodeV); + this->_minimumSpanningTree.push_back({ {edge->nodeU->data, edge->nodeV->data}, edge->weight }); + } + } + } + + vector, int>> Graph::GetMinimumSpanningTree() + { + return this->_minimumSpanningTree; + } + + vector Graph::GetSortedEdgeList() + { + return this->_edgeList; } } \ No newline at end of file diff --git a/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc b/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc index e69de29..ed9c63d 100644 --- a/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc +++ b/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc @@ -0,0 +1,30 @@ +#include +#include<0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h> + +namespace MinimumSpanningTreeKruskalAlgorithm +{ + TEST(MST, Kruskal) + { + Graph graph; + + graph.PushUndirectedEdge(1, 2, 4); + graph.PushUndirectedEdge(1, 8, 8); + graph.PushUndirectedEdge(2, 8, 11); + graph.PushUndirectedEdge(2, 3, 8); + graph.PushUndirectedEdge(3, 4, 7); + graph.PushUndirectedEdge(3, 9, 2); + graph.PushUndirectedEdge(3, 6, 4); + graph.PushUndirectedEdge(4, 5, 9); + graph.PushUndirectedEdge(4, 6, 14); + graph.PushUndirectedEdge(5, 6, 10); + graph.PushUndirectedEdge(6, 7, 2); + graph.PushUndirectedEdge(7, 8, 1); + graph.PushUndirectedEdge(7, 9, 6); + graph.PushUndirectedEdge(8, 9, 7); + + graph.FindMinimumSpanningTreeKruskalAlgorithm(); + + auto res1 = graph.GetSortedEdgeList(); + auto res2 = graph.GetMinimumSpanningTree(); + } +} \ No newline at end of file From 09bd22f9ed996de7eccb2c35267c66655d37f521 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Wed, 18 Dec 2024 00:19:36 +0530 Subject: [PATCH 3/7] test: kruskal test added, test util updated --- ...0007_MinimumSpanningTreeKruskalAlgorithm.h | 1 - ...007_MinimumSpanningTreeKruskalAlgorithm.cc | 7 +------ Tests/0000_CommonUtilities/UnitTestHelper.h | 18 ++++++++++++++++ ...MinimumSpanningTreeKruskalAlgorithmTest.cc | 21 ++++++++++++++++--- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h index 8441447..5ee7753 100644 --- a/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h +++ b/Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h @@ -42,6 +42,5 @@ namespace MinimumSpanningTreeKruskalAlgorithm void PushUndirectedEdge(int valueU, int valueV, int weight); void FindMinimumSpanningTreeKruskalAlgorithm(); vector, int>> GetMinimumSpanningTree(); - vector GetSortedEdgeList(); }; } \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc index 462982d..ea9e767 100644 --- a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc +++ b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc @@ -88,7 +88,7 @@ namespace MinimumSpanningTreeKruskalAlgorithm this->MakeSet(iterator.second); } - sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) {return edgeX->weight < edgeY->weight; }); + sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) { return edgeX->weight < edgeY->weight; }); for (auto edge : this->_edgeList) { @@ -104,9 +104,4 @@ namespace MinimumSpanningTreeKruskalAlgorithm { return this->_minimumSpanningTree; } - - vector Graph::GetSortedEdgeList() - { - return this->_edgeList; - } } \ No newline at end of file diff --git a/Tests/0000_CommonUtilities/UnitTestHelper.h b/Tests/0000_CommonUtilities/UnitTestHelper.h index 6faf4e5..eae749a 100644 --- a/Tests/0000_CommonUtilities/UnitTestHelper.h +++ b/Tests/0000_CommonUtilities/UnitTestHelper.h @@ -136,4 +136,22 @@ class UnitTestHelper reverse(normalizedCycle2.begin() + 1, normalizedCycle2.end()); return (normalizedCycle1 == normalizedCycle2); } + + template + vector, T>> SortVectorOfPair(vector, T>> data) + { + for (auto& iterator : data) + { + if (iterator.first.first > iterator.first.second) + { + swap(iterator.first.first, iterator.first.second); + } + } + + sort(data.begin(), data.end(), [](const pair, T>& pairA, const pair, T>& pairB) + { + return pairA.second < pairB.second; + }); + return data; + } }; \ No newline at end of file diff --git a/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc b/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc index ed9c63d..c559123 100644 --- a/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc +++ b/Tests/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithmTest.cc @@ -1,8 +1,11 @@ #include -#include<0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h> +#include "../Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h" +#include "../0000_CommonUtilities/UnitTestHelper.h" namespace MinimumSpanningTreeKruskalAlgorithm { + UnitTestHelper unitTestHelper; + TEST(MST, Kruskal) { Graph graph; @@ -24,7 +27,19 @@ namespace MinimumSpanningTreeKruskalAlgorithm graph.FindMinimumSpanningTreeKruskalAlgorithm(); - auto res1 = graph.GetSortedEdgeList(); - auto res2 = graph.GetMinimumSpanningTree(); + vector, int>> actualMST = graph.GetMinimumSpanningTree(); + vector, int>> expectedMST = + { + {{7, 8}, 1}, + {{3, 9}, 2}, + {{6, 7}, 2}, + {{2, 1}, 4}, + {{3, 6}, 4}, + {{3, 4}, 7}, + {{8, 1}, 8}, + {{4, 5}, 9} + }; + + ASSERT_EQ(unitTestHelper.SortVectorOfPair(actualMST), unitTestHelper.SortVectorOfPair(expectedMST)); } } \ No newline at end of file From 5ec46b59155fccc37621cbf481e4a5cdccccb808 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Wed, 18 Dec 2024 00:26:52 +0530 Subject: [PATCH 4/7] fix: used references instead copy of obj --- .../0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc index ea9e767..0f67e58 100644 --- a/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc +++ b/SourceCodes/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.cc @@ -81,16 +81,17 @@ namespace MinimumSpanningTreeKruskalAlgorithm this->_adjlist[nodeV].push_back(nodeU); this->_edgeList.push_back(new Edge(nodeU, nodeV, weight)); } + void Graph::FindMinimumSpanningTreeKruskalAlgorithm() { - for (auto iterator : this->_nodeMap) + for (auto& iterator : this->_nodeMap) { this->MakeSet(iterator.second); } sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) { return edgeX->weight < edgeY->weight; }); - for (auto edge : this->_edgeList) + for (auto& edge : this->_edgeList) { if (this->FindSet(edge->nodeU) != this->FindSet(edge->nodeV)) { From f8512aa8dbd62dc2f43a81ff06621e6004f7ae03 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Sun, 22 Dec 2024 22:30:42 +0530 Subject: [PATCH 5/7] feature: prims algo initial draft --- .../0008_MinimumSpanningTreePrimAlgorithm.h | 42 +++++++++++++++++ .../0008_MinimumSpanningTreePrimAlgorithm.cc | 46 +++++++++++++++++++ SourceCodes/0003_Graph/CMakeLists.txt | 1 + ...08_MinimumSpanningTreePrimAlgorithmTest.cc | 0 Tests/0003_Graph/CMakeLists.txt | 1 + 5 files changed, 90 insertions(+) create mode 100644 Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h create mode 100644 SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc create mode 100644 Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc diff --git a/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h b/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h new file mode 100644 index 0000000..8d8bef1 --- /dev/null +++ b/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h @@ -0,0 +1,42 @@ +# pragma once + +#include +#include +#include +using namespace std; + +namespace MinimumSpanningTreePrimAlgorithm +{ + class Node + { + public: + int data; + Node* parent; + int key; + bool isInOperationalSet; + Node(int data); + }; + + class CompareNodeKey + { + public: + bool operator()(const Node* nodeU, const Node* nodeV) const + { + return nodeU->key < nodeV->key; + } + }; + + class Graph + { + private: + map>> _adjlist; + map _nodeMap; + vector, int>> _minimumSpanningTree; + set _operationalSet; + Node* MakeOrFindNode(int data); + public: + void PushUndirectedEdge(int valueU, int valueV, int weight); + void FindMinimumSpanningTreePrimAlgorithm(); + vector, int>> GetMinimumSpanningTree(); + }; +} \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc b/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc new file mode 100644 index 0000000..3f0fd95 --- /dev/null +++ b/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc @@ -0,0 +1,46 @@ +#include "../Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h" +#include +using namespace std; + + +namespace MinimumSpanningTreePrimAlgorithm +{ + Node::Node(int data) + { + this->data = data; + this->parent = nullptr; + this->key = INT_MAX; + this->isInOperationalSet = false; + } + + // Graph Private Member Methods + Node* Graph::MakeOrFindNode(int data) + { + Node* node = nullptr; + if (this->_nodeMap.find(data) == this->_nodeMap.end()) + { + node = new Node(data); + this->_nodeMap[data] = node; + } + else + { + node = this->_nodeMap[data]; + } + return node; + } + + // Graph Public Member Methods + void Graph::PushUndirectedEdge(int dataU, int dataV, int weight) + { + Node* nodeU = this->MakeOrFindNode(dataU); + Node* nodeV = this->MakeOrFindNode(dataV); + + this->_adjlist[nodeU].push_back({nodeV, weight}); + this->_adjlist[nodeV].push_back({nodeU, weight}); + } + + void Graph::FindMinimumSpanningTreePrimAlgorithm() + { + + } +} \ No newline at end of file diff --git a/SourceCodes/0003_Graph/CMakeLists.txt b/SourceCodes/0003_Graph/CMakeLists.txt index 68612e3..0837512 100644 --- a/SourceCodes/0003_Graph/CMakeLists.txt +++ b/SourceCodes/0003_Graph/CMakeLists.txt @@ -7,6 +7,7 @@ set(0003GRAPH_SOURCES 0005_HamiltonianPathAndCycle.cc 0006_EulerianPathAndCircuit.cc 0007_MinimumSpanningTreeKruskalAlgorithm.cc + 0008_MinimumSpanningTreePrimAlgorithm.cc ) diff --git a/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc b/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc new file mode 100644 index 0000000..e69de29 diff --git a/Tests/0003_Graph/CMakeLists.txt b/Tests/0003_Graph/CMakeLists.txt index b355b1e..b5e4144 100644 --- a/Tests/0003_Graph/CMakeLists.txt +++ b/Tests/0003_Graph/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable( 0005_HamiltonianPathAndCycleTest.cc 0006_EulerianPathAndCircuitTest.cc 0007_MinimumSpanningTreeKruskalAlgorithmTest.cc + 0008_MinimumSpanningTreePrimAlgorithmTest.cc ) target_link_libraries( From 4650c74c07109d5408b2b5514fbe19f8a29d23fd Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Tue, 24 Dec 2024 01:55:42 +0530 Subject: [PATCH 6/7] feature-fix: prims algo logic added, test util fix --- .../0008_MinimumSpanningTreePrimAlgorithm.h | 2 +- .../0008_MinimumSpanningTreePrimAlgorithm.cc | 39 ++++++++++++++++ Tests/0000_CommonUtilities/UnitTestHelper.h | 4 ++ ...08_MinimumSpanningTreePrimAlgorithmTest.cc | 45 +++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h b/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h index 8d8bef1..2f335ac 100644 --- a/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h +++ b/Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h @@ -32,7 +32,7 @@ namespace MinimumSpanningTreePrimAlgorithm map>> _adjlist; map _nodeMap; vector, int>> _minimumSpanningTree; - set _operationalSet; + multiset _operationalSet; Node* MakeOrFindNode(int data); public: void PushUndirectedEdge(int valueU, int valueV, int weight); diff --git a/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc b/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc index 3f0fd95..ce56ee1 100644 --- a/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc +++ b/SourceCodes/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.cc @@ -41,6 +41,45 @@ namespace MinimumSpanningTreePrimAlgorithm void Graph::FindMinimumSpanningTreePrimAlgorithm() { + Node* root = this->_nodeMap.begin()->second; + root->key = 0; + for (auto& iterator : this->_nodeMap) + { + iterator.second->isInOperationalSet = true; + this->_operationalSet.insert(iterator.second); + } + + while (!this->_operationalSet.empty()) + { + Node* nodeU = *(this->_operationalSet.begin()); + this->_operationalSet.erase(nodeU); + nodeU->isInOperationalSet = false; + + for (auto& iterator : this->_adjlist[nodeU]) + { + Node* nodeV = iterator.first; + int weight = iterator.second; + + if (nodeV->isInOperationalSet && weight < nodeV->key) + { + this->_operationalSet.erase(nodeV); + nodeV->key = weight; + nodeV->parent = nodeU; + this->_operationalSet.insert(nodeV); + + } + } + + if (nodeU->parent != nullptr) + { + this->_minimumSpanningTree.push_back({ {nodeU->parent->data, nodeU->data}, nodeU->key }); + } + } + } + + vector, int>> Graph::GetMinimumSpanningTree() + { + return this->_minimumSpanningTree; } } \ No newline at end of file diff --git a/Tests/0000_CommonUtilities/UnitTestHelper.h b/Tests/0000_CommonUtilities/UnitTestHelper.h index eae749a..c903d36 100644 --- a/Tests/0000_CommonUtilities/UnitTestHelper.h +++ b/Tests/0000_CommonUtilities/UnitTestHelper.h @@ -150,6 +150,10 @@ class UnitTestHelper sort(data.begin(), data.end(), [](const pair, T>& pairA, const pair, T>& pairB) { + if (pairA.second == pairB.second) + { + return pairA.first.first < pairB.first.first; + } return pairA.second < pairB.second; }); return data; diff --git a/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc b/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc index e69de29..2016d04 100644 --- a/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc +++ b/Tests/0003_Graph/0008_MinimumSpanningTreePrimAlgorithmTest.cc @@ -0,0 +1,45 @@ +#include +#include "../Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h" +#include "../0000_CommonUtilities/UnitTestHelper.h" + +namespace MinimumSpanningTreePrimAlgorithm +{ + UnitTestHelper unitTestHelper; + + TEST(MST, Prim) + { + Graph graph; + + graph.PushUndirectedEdge(1, 2, 4); + graph.PushUndirectedEdge(1, 8, 8); + graph.PushUndirectedEdge(2, 8, 11); + graph.PushUndirectedEdge(2, 3, 8); + graph.PushUndirectedEdge(3, 4, 7); + graph.PushUndirectedEdge(3, 9, 2); + graph.PushUndirectedEdge(3, 6, 4); + graph.PushUndirectedEdge(4, 5, 9); + graph.PushUndirectedEdge(4, 6, 14); + graph.PushUndirectedEdge(5, 6, 10); + graph.PushUndirectedEdge(6, 7, 2); + graph.PushUndirectedEdge(7, 8, 1); + graph.PushUndirectedEdge(7, 9, 6); + graph.PushUndirectedEdge(8, 9, 7); + + graph.FindMinimumSpanningTreePrimAlgorithm(); + + vector, int>> actualMST = graph.GetMinimumSpanningTree(); + vector, int>> expectedMST = + { + {{7, 8}, 1}, + {{3, 9}, 2}, + {{6, 7}, 2}, + {{2, 1}, 4}, + {{3, 6}, 4}, + {{3, 4}, 7}, + {{8, 1}, 8}, + {{4, 5}, 9} + }; + + ASSERT_EQ(unitTestHelper.SortVectorOfPair(actualMST), unitTestHelper.SortVectorOfPair(expectedMST)); + } +} \ No newline at end of file From c6238dda2245d96f3ed5bc141779c15f3c346776 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Fri, 27 Dec 2024 23:44:15 +0530 Subject: [PATCH 7/7] Update README.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index e69de29..10342c3 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,21 @@ +## Data Structures and Algorithms + +This repository contains a collection of **data structures and algorithms** implemented in **C++**. It is designed to provide efficient solutions to common algorithmic problems while adhering to clean coding practices and modular design. + +### Features + +- **Data Structures and Algorithms:** Implementations of data structures and algorithms based on the concepts from the book Introduction to Algorithms by Cormen, Leiserson, Rivest, and Stein (CLRS). +- **Modular Design:** Code is organized into manageable modules for better readability and reusability. +- **Testing:** + - Built with **CMake** as the build system for ease of compilation and dependency management. + - **Google Test** framework is integrated for comprehensive unit testing to ensure code correctness. + +### Folder Structure + +```plain text +datastructures-algorithms +├── Headers # Header Files +├── SourceCodes # Implementation of the solutions +├── Tests # Unit tests for implemented solutions +└── CMakeLists.txt # CMake configuration file +```