diff --git a/Headers/0003_Graph/0001_BreadthFirstSearch.h b/Headers/0003_Graph/0001_BreadthFirstSearch.h index bb670f1..6f5326e 100644 --- a/Headers/0003_Graph/0001_BreadthFirstSearch.h +++ b/Headers/0003_Graph/0001_BreadthFirstSearch.h @@ -2,29 +2,31 @@ #include #include +#include #include +#include using namespace std; enum color { WHITE, GRAY, BLACK }; -class Node +class BFSNode { public: char data; int distance; int color; - Node* parent; - Node(char value); + BFSNode* parent; + BFSNode(char value); }; class BFSGraph { private: - map> _adjlist; - map _nodeMap; - Node* MakeOrFindNode(char value); - void BreadthFirstSearch(Node* node); + map> _adjlist; + map _nodeMap; + BFSNode* MakeOrFindNode(char value); + void BreadthFirstSearch(BFSNode* node); public: void PushUndirectedEdge(char valueU, char valueV); void BFS(char value); - string ShowBFSResult(); + vector> ShowBFSResult(); }; \ No newline at end of file diff --git a/Headers/0003_Graph/0002_DepthFirstSearch.h b/Headers/0003_Graph/0002_DepthFirstSearch.h new file mode 100644 index 0000000..d3b7544 --- /dev/null +++ b/Headers/0003_Graph/0002_DepthFirstSearch.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include +using namespace std; +enum color { WHITE, GRAY, BLACK }; + +class DFSNode +{ +public: + char data; + int color; + int discoveredTime; + int finishingTime; + DFSNode* parent; + DFSNode(char value); +}; + +class DFSGraph +{ +private: + int time; + map> _adjlist; + map _nodeMap; + DFSNode* MakeOrFindNode(char value); + void DepthFirstSearch(DFSNode* DFSNode); +public: + void PushDirectedEdge(char valueU, char valueV); + void DFS(); + vector>> ShowDFSResult(); +}; \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0001_BreadthFirstSearch.cc b/SourceCodes/0003_Graph/0001_BreadthFirstSearch.cc index fa88deb..d88c04f 100644 --- a/SourceCodes/0003_Graph/0001_BreadthFirstSearch.cc +++ b/SourceCodes/0003_Graph/0001_BreadthFirstSearch.cc @@ -1,24 +1,26 @@ #include "../Headers/0003_Graph/0001_BreadthFirstSearch.h" #include #include +#include +#include #include #include using namespace std; -Node::Node(char value) +BFSNode::BFSNode(char value) { this->data = value; - distance = INT_MAX; - color = WHITE; - parent = NULL; + this->distance = INT_MAX; + this->color = WHITE; + this->parent = nullptr; } -Node* BFSGraph::MakeOrFindNode(char value) +BFSNode* BFSGraph::MakeOrFindNode(char value) { - Node* node = NULL; + BFSNode* node = nullptr; if (this->_nodeMap.find(value) == this->_nodeMap.end()) { - node = new Node(value); + node = new BFSNode(value); this->_nodeMap[value] = node; } else @@ -28,21 +30,21 @@ Node* BFSGraph::MakeOrFindNode(char value) return node; } -void BFSGraph::BreadthFirstSearch(Node* node) +void BFSGraph::BreadthFirstSearch(BFSNode* node) { node->color = WHITE; node->distance = 0; - node->parent = NULL; + node->parent = nullptr; - queue nodeQueue; + queue nodeQueue; nodeQueue.push(node); while (nodeQueue.empty()!=true) { - Node* currentNode = nodeQueue.front(); + BFSNode* currentNode = nodeQueue.front(); nodeQueue.pop(); - for (auto adjacentNode : this->_adjlist[currentNode]) + for (auto &adjacentNode : this->_adjlist[currentNode]) { if (adjacentNode->color == WHITE) { @@ -58,8 +60,8 @@ void BFSGraph::BreadthFirstSearch(Node* node) void BFSGraph::PushUndirectedEdge(char valueU, char valueV) { - Node* nodeU = this->MakeOrFindNode(valueU); - Node* nodeV = this->MakeOrFindNode(valueV); + BFSNode* nodeU = this->MakeOrFindNode(valueU); + BFSNode* nodeV = this->MakeOrFindNode(valueV); this->_adjlist[nodeU].push_back(nodeV); this->_adjlist[nodeV].push_back(nodeU); @@ -70,12 +72,12 @@ void BFSGraph::BFS(char value) this->BreadthFirstSearch(this->_nodeMap[value]); } -string BFSGraph::ShowBFSResult() +vector> BFSGraph::ShowBFSResult() { - string result = ""; - for (auto value : this->_nodeMap) + vector> result; + for (auto& node : this->_nodeMap) { - result = result + " " + value.first + "(" + to_string(value.second->distance) + ")"; + result.push_back(make_pair(node.first, node.second->distance)); } return result; } \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0002_DepthFirstSearch.cc b/SourceCodes/0003_Graph/0002_DepthFirstSearch.cc new file mode 100644 index 0000000..c5641d9 --- /dev/null +++ b/SourceCodes/0003_Graph/0002_DepthFirstSearch.cc @@ -0,0 +1,76 @@ +#include "../Headers/0003_Graph/0002_DepthFirstSearch.h" +#include +#include +#include +using namespace std; + +DFSNode::DFSNode(char value) +{ + this->data = value; + this->discoveredTime = INT_MAX; + this->finishingTime = INT_MAX; + this->color = WHITE; + this->parent = nullptr; +} + +DFSNode* DFSGraph::MakeOrFindNode(char value) +{ + DFSNode* node = nullptr; + if (this->_nodeMap.find(value) == this->_nodeMap.end()) + { + node = new DFSNode(value); + this->_nodeMap[value] = node; + } + else + { + node = this->_nodeMap[value]; + } + return node; +} +void DFSGraph::DepthFirstSearch(DFSNode* nodeU) +{ + this->time++; + nodeU->discoveredTime = this->time; + nodeU->color = GRAY; + for (auto nodeV : this->_adjlist[nodeU]) + { + if (nodeV->color == WHITE) + { + nodeV->parent = nodeU; + this->DepthFirstSearch(nodeV); + } + } + nodeU->color = BLACK; + this->time++; + nodeU->finishingTime = time; +} + +void DFSGraph::PushDirectedEdge(char valueU, char valueV) +{ + DFSNode* nodeU = this->MakeOrFindNode(valueU); + DFSNode* nodeV = this->MakeOrFindNode(valueV); + + this->_adjlist[nodeU].push_back(nodeV); +} + +void DFSGraph::DFS() +{ + this->time = 0; + for (auto& iterator:this->_nodeMap) + { + if (iterator.second->color == WHITE) + { + this->DepthFirstSearch(iterator.second); + } + } +} + +vector>> DFSGraph::ShowDFSResult() +{ + vector>> result; + for (auto& node : this->_nodeMap) + { + result.push_back(make_pair(node.first, make_pair(node.second->discoveredTime, node.second->finishingTime))); + } + return result; +} \ No newline at end of file diff --git a/SourceCodes/0003_Graph/CMakeLists.txt b/SourceCodes/0003_Graph/CMakeLists.txt index 525b75d..4da8e98 100644 --- a/SourceCodes/0003_Graph/CMakeLists.txt +++ b/SourceCodes/0003_Graph/CMakeLists.txt @@ -1,6 +1,7 @@ # Specify the source files set(0003GRAPH_SOURCES 0001_BreadthFirstSearch.cc + 0002_DepthFirstSearch.cc ) # Create a library target diff --git a/Tests/0000_CommonUtilities/UnitTestHelper.h b/Tests/0000_CommonUtilities/UnitTestHelper.h index af1fbc0..f6c24aa 100644 --- a/Tests/0000_CommonUtilities/UnitTestHelper.h +++ b/Tests/0000_CommonUtilities/UnitTestHelper.h @@ -12,11 +12,11 @@ class UnitTestHelper string VerifyVectorResult(vector vector) { string result = ""; - for (auto iterator : vector) + for (auto& iterator : vector) { result += to_string(iterator) + " "; } result.pop_back(); return result; } -}; +}; \ No newline at end of file diff --git a/Tests/0000_CommonUtilities/UnitTestHelperVectorOfPair.h b/Tests/0000_CommonUtilities/UnitTestHelperVectorOfPair.h new file mode 100644 index 0000000..f2deab1 --- /dev/null +++ b/Tests/0000_CommonUtilities/UnitTestHelperVectorOfPair.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include +using namespace std; + +template +class UnitTestHelperVectorOfPair +{ +public: + string VerifyVectorOfPair(vector> vector) + { + string result = ""; + for (auto& iterator : vector) + { + result += string(1, iterator.first) + "(" + to_string(iterator.second) + ")" + " "; + } + + if (!result.empty()) + { + result.pop_back(); + } + return result; + } + + string VerifyVectorOfPairOfTwo(vector>> vector) + { + string result = ""; + for (auto& iterator : vector) + { + result += string(1, iterator.first) + "(" + to_string(iterator.second.first) + "," + to_string(iterator.second.second) + ")" + " "; + } + + if (!result.empty()) + { + result.pop_back(); + } + return result; + } +}; \ No newline at end of file diff --git a/Tests/0003_Graph/0001_BreadthFirstSearchTest.cc b/Tests/0003_Graph/0001_BreadthFirstSearchTest.cc index a7e8f0f..b87ad99 100644 --- a/Tests/0003_Graph/0001_BreadthFirstSearchTest.cc +++ b/Tests/0003_Graph/0001_BreadthFirstSearchTest.cc @@ -1,11 +1,14 @@ #include #include #include "../Headers/0003_Graph/0001_BreadthFirstSearch.h" +#include "../0000_CommonUtilities/UnitTestHelperVectorOfPair.h" -// Demonstrate some basic assertions. namespace BreadthFirstSearchTest { - TEST(BFSTesting, ShowBFSResultTest) { + UnitTestHelperVectorOfPair unitTestHelperVectorOfPair; + + TEST(BFSTesting, ShowBFSResultTest01) + { BFSGraph graph; graph.PushUndirectedEdge('s', 'r'); @@ -21,8 +24,21 @@ namespace BreadthFirstSearchTest graph.BFS('s'); - string actualResult = graph.ShowBFSResult(); - string expectedResult = " r(1) s(0) t(2) u(3) v(2) w(1) x(2) y(3)"; + string actualResult = unitTestHelperVectorOfPair.VerifyVectorOfPair(graph.ShowBFSResult()); + string expectedResult = "r(1) s(0) t(2) u(3) v(2) w(1) x(2) y(3)"; EXPECT_EQ(actualResult, expectedResult); } + + TEST(BFSTesting, ShowBFSResultTest02) + { + BFSGraph graph; + + graph.PushUndirectedEdge('s', 'r'); + + graph.BFS('s'); + + string actualResult = unitTestHelperVectorOfPair.VerifyVectorOfPair(graph.ShowBFSResult()); + string expectedResult = "r(1) s(0)"; + EXPECT_EQ(actualResult, expectedResult); + } } \ No newline at end of file diff --git a/Tests/0003_Graph/0002_DepthFirstSearchTest.cc b/Tests/0003_Graph/0002_DepthFirstSearchTest.cc new file mode 100644 index 0000000..34083bc --- /dev/null +++ b/Tests/0003_Graph/0002_DepthFirstSearchTest.cc @@ -0,0 +1,28 @@ +#include +#include "../Headers/0003_Graph/0002_DepthFirstSearch.h" +#include "../0000_CommonUtilities/UnitTestHelperVectorOfPair.h" + +namespace DepthFirstSearchTest +{ + UnitTestHelperVectorOfPair unitTestHelperVectorOfPair; + + TEST(DFSTesting, ShowDFSResultTest01) + { + DFSGraph graph; + + graph.PushDirectedEdge('u', 'v'); + graph.PushDirectedEdge('u', 'x'); + graph.PushDirectedEdge('v', 'y'); + graph.PushDirectedEdge('w', 'y'); + graph.PushDirectedEdge('w', 'z'); + graph.PushDirectedEdge('x', 'v'); + graph.PushDirectedEdge('y', 'x'); + graph.PushDirectedEdge('z', 'z'); + + graph.DFS(); + + string actualResult = unitTestHelperVectorOfPair.VerifyVectorOfPairOfTwo(graph.ShowDFSResult()); + string expectedResult = "u(1,8) v(2,7) w(9,12) x(4,5) y(3,6) z(10,11)"; + EXPECT_EQ(actualResult, expectedResult); + } +} \ No newline at end of file diff --git a/Tests/0003_Graph/CMakeLists.txt b/Tests/0003_Graph/CMakeLists.txt index 836aa3c..b42277b 100644 --- a/Tests/0003_Graph/CMakeLists.txt +++ b/Tests/0003_Graph/CMakeLists.txt @@ -11,19 +11,16 @@ FetchContent_MakeAvailable(googletest) enable_testing() add_executable( - 0003-Graph-Tests - 0001_BreadthFirstSearchTest.cc) - -target_link_libraries( - 0003-Graph-Tests - GTest::gtest_main + 0003GraphTests + 0001_BreadthFirstSearchTest.cc + 0002_DepthFirstSearchTest.cc ) target_link_libraries( - 0003-Graph-Tests + 0003GraphTests + GTest::gtest_main 0003GRAPH ) - include(GoogleTest) -gtest_discover_tests(0003-Graph-Tests) \ No newline at end of file +gtest_discover_tests(0003GraphTests) \ No newline at end of file