From 4b47630548eb7006d5926ef5f045dbefb9eef9f6 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Wed, 13 Apr 2022 21:15:03 -0400 Subject: [PATCH] [cpp] Clean up graph implementations --- cpp/algorithms/graphs/object/graph.cpp | 5 +- cpp/algorithms/graphs/object/lib-graph.cpp | 6 +- cpp/algorithms/graphs/object/lib-graph.hpp | 106 +++++++------ cpp/algorithms/graphs/simple/graph.cpp | 2 +- cpp/algorithms/graphs/simple/lib-graph.cpp | 2 +- cpp/algorithms/graphs/simple/lib-graph.hpp | 4 +- cpp/algorithms/graphs/templated/graph.cpp | 4 +- cpp/algorithms/graphs/templated/lib-graph.hpp | 142 +++++++++--------- cpp/algorithms/graphs/weighted/graph.cpp | 7 +- cpp/algorithms/graphs/weighted/lib-graph.cpp | 6 +- cpp/algorithms/graphs/weighted/lib-graph.hpp | 128 +++++++++------- 11 files changed, 227 insertions(+), 185 deletions(-) diff --git a/cpp/algorithms/graphs/object/graph.cpp b/cpp/algorithms/graphs/object/graph.cpp index 990db59..e0632dd 100644 --- a/cpp/algorithms/graphs/object/graph.cpp +++ b/cpp/algorithms/graphs/object/graph.cpp @@ -1,8 +1,7 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: An example of an object graph implementation ## -## Algorithms in this example are found in MIT Intro to Algorithms ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: Driver program to test object graph implementation ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ################################################################################ diff --git a/cpp/algorithms/graphs/object/lib-graph.cpp b/cpp/algorithms/graphs/object/lib-graph.cpp index 33849e3..d83e7c9 100644 --- a/cpp/algorithms/graphs/object/lib-graph.cpp +++ b/cpp/algorithms/graphs/object/lib-graph.cpp @@ -1,7 +1,8 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: Driver program to test object graph implementation ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of an object graph implementation ## +## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ################################################################################ @@ -183,4 +184,3 @@ std::vector Graph::TopologicalSort(const Node &startNode) const // + Output is handled in main as FILO, similar to a stack return order; } - diff --git a/cpp/algorithms/graphs/object/lib-graph.hpp b/cpp/algorithms/graphs/object/lib-graph.hpp index 7246583..e93d2ba 100644 --- a/cpp/algorithms/graphs/object/lib-graph.hpp +++ b/cpp/algorithms/graphs/object/lib-graph.hpp @@ -1,6 +1,6 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## ## About: An example of an object graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## @@ -10,51 +10,14 @@ #ifndef LIB_GRAPH_HPP #define LIB_GRAPH_HPP -#include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include - - -/******************************************************************************/ -// Structures for tracking information gathered from various traversals -struct Node; -// Color represents the discovery status of any given node -// + White is undiscovered, Gray is in progress, Black is fully discovered -enum Color {White, Gray, Black}; - -// Information used in all searches -struct SearchInfo { - // Coloring of the nodes is used in both DFS and BFS - Color discovered = White; -}; - -// Information that is only used in BFS -struct BFS : SearchInfo { - // Used to represent distance from start node - int distance = 0; - // Used to represent the parent node that discovered this node - // + If we use this node as the starting point, this will remain a nullptr - const Node *predecessor = nullptr; -}; - -// Information that is only used in DFS -struct DFS : SearchInfo { - // Create a pair to track discovery / finish time - // + Discovery time is the iteration the node is first discovered - // + Finish time is the iteration the node has been checked completely - // ++ A finished node has considered all adjacent nodes - std::pair discoveryFinish; -}; - -// Store search information in unordered_maps so we can pass it around easily -// + Allows each node to store relative information on the traversal -using InfoBFS = std::unordered_map; -using InfoDFS = std::unordered_map; /******************************************************************************/ @@ -63,14 +26,16 @@ struct Node { public: // Constructors Node(const Node &rhs) = default; - Node & operator=(Node rhs) { + Node & operator=(Node rhs) + { if (this == &rhs) return *this; swap(*this, rhs); return *this; } Node(int num, std::vector adj) : number(num), adjacent(std::move(adj)) {} - friend void swap(Node &a, Node &b) { + friend void swap(Node &a, Node &b) + { std::swap(a.number, b.number); std::swap(a.adjacent, b.adjacent); } @@ -85,8 +50,61 @@ public: }; +/******************************************************************************/ +// Base struct for storing traversal information on all nodes + +// Color represents the discovery status of any given node +enum Color { + // Node is marked as undiscovered + White, + // Node discovery is in progress; Some adjacent nodes have not been checked + Gray, + // Node has been discovered; All adjacent nodes have been checked + Black +}; + +// Information used in all searches +struct SearchInfo { + // Coloring of the nodes is used in both DFS and BFS + Color discovered = White; +}; + + +/******************************************************************************/ +// BFS search information struct + +// Information that is only used in BFS +struct BFS : SearchInfo { + // Used to represent distance from start node + int distance = 0; + // Used to represent the parent node that discovered this node + // + If we use this node as the starting point, this will remain a nullptr + const Node *predecessor = nullptr; +}; + +// Store search information in unordered_maps so we can pass it around easily +// + Allows each node to store relative information on the traversal +using InfoBFS = std::unordered_map; + + +/******************************************************************************/ +// DFS search information struct + +// Information that is only used in DFS +struct DFS : SearchInfo { + // Create a pair to track discovery / finish time + // + Discovery time is the iteration the node is first discovered + // + Finish time is the iteration the node has been checked completely + // ++ A finished node has considered all adjacent nodes + std::pair discoveryFinish; +}; + +using InfoDFS = std::unordered_map; + + /******************************************************************************/ // Graph class declaration + class Graph { public: // Constructor diff --git a/cpp/algorithms/graphs/simple/graph.cpp b/cpp/algorithms/graphs/simple/graph.cpp index 2c7ebc8..c7fdc29 100644 --- a/cpp/algorithms/graphs/simple/graph.cpp +++ b/cpp/algorithms/graphs/simple/graph.cpp @@ -1,6 +1,6 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## ## About: Driver program to test a simple graph implementation ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## diff --git a/cpp/algorithms/graphs/simple/lib-graph.cpp b/cpp/algorithms/graphs/simple/lib-graph.cpp index fb43369..0da13c2 100644 --- a/cpp/algorithms/graphs/simple/lib-graph.cpp +++ b/cpp/algorithms/graphs/simple/lib-graph.cpp @@ -1,6 +1,6 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## ## About: An example of a simple graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## diff --git a/cpp/algorithms/graphs/simple/lib-graph.hpp b/cpp/algorithms/graphs/simple/lib-graph.hpp index ec445fc..885ab45 100644 --- a/cpp/algorithms/graphs/simple/lib-graph.hpp +++ b/cpp/algorithms/graphs/simple/lib-graph.hpp @@ -1,6 +1,6 @@ /*############################################################################# ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## ## About: An example of a simple graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## @@ -12,9 +12,9 @@ #include #include -#include #include #include +#include class Graph { diff --git a/cpp/algorithms/graphs/templated/graph.cpp b/cpp/algorithms/graphs/templated/graph.cpp index ed22f64..4b7e0ec 100644 --- a/cpp/algorithms/graphs/templated/graph.cpp +++ b/cpp/algorithms/graphs/templated/graph.cpp @@ -1,7 +1,7 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: An example of a weighted graph implementation ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: Driver program to test templated object graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## diff --git a/cpp/algorithms/graphs/templated/lib-graph.hpp b/cpp/algorithms/graphs/templated/lib-graph.hpp index 1f83cc9..2d4b843 100644 --- a/cpp/algorithms/graphs/templated/lib-graph.hpp +++ b/cpp/algorithms/graphs/templated/lib-graph.hpp @@ -1,7 +1,7 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: An example of an object graph implementation ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of a templated object graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## @@ -10,24 +10,74 @@ #ifndef LIB_GRAPH_HPP #define LIB_GRAPH_HPP -#include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include + + +/******************************************************************************/ +// Node structure for representing a graph + +template +struct Node { +public: + template friend class Graph; + template friend class InfoMST; + + // Constructors + Node(const Node &rhs) = default; + Node & operator=(Node rhs) + { + if (this == &rhs) return *this; + swap(*this, rhs); + return *this; + } + Node(T data, const std::vector> &adj) : data_(data) + { + // Place each adjacent node in vector into our unordered_map of edges + for (const auto &i : adj) adjacent_.emplace(i.first, i.second); + } + + friend void swap(Node &a, Node &b) + { + std::swap(a.data_, b.data_); + std::swap(a.adjacent_, b.adjacent_); + } + + // Operators + // Define operator== for std::find; And comparisons between nodes + bool operator==(const Node &b) const { return this->data_ == b.data_;} + // Define an operator!= for comparing nodes for inequality + bool operator!=(const Node &b) const { return this->data_ != b.data_;} + + // Accessors + inline T GetData() const { return data_;} + inline std::unordered_map GetAdjacent() const { return adjacent_;} + +private: + T data_; + // Adjacent stored in an unordered_map + std::unordered_map adjacent_; +}; /******************************************************************************/ // Base struct for storing traversal information on all nodes -template struct Node; - // Color represents the discovery status of any given node -// + White is undiscovered, Gray is in progress, Black is fully discovered -enum Color {White, Gray, Black}; +enum Color { + // Node is marked as undiscovered + White, + // Node discovery is in progress; Some adjacent nodes have not been checked + Gray, + // Node has been discovered; All adjacent nodes have been checked + Black +}; // Information used in all searches struct SearchInfo { @@ -37,7 +87,7 @@ struct SearchInfo { /******************************************************************************/ -// BFS search information structs +// BFS search information struct // Information that is only used in BFS template @@ -49,9 +99,13 @@ struct BFS : SearchInfo { const Node *predecessor = nullptr; }; +// Store search information in unordered_maps so we can pass it around easily +// + Allows each node to store relative information on the traversal +template using InfoBFS = std::unordered_map>; + /******************************************************************************/ -// DFS search information structs +// DFS search information struct // Information that is only used in DFS struct DFS : SearchInfo { @@ -62,21 +116,15 @@ struct DFS : SearchInfo { std::pair discoveryFinish; }; +template using InfoDFS = std::unordered_map; + /******************************************************************************/ -// Alias types for storing search information structures +// MST search information struct -// Store search information in unordered_maps so we can pass it around easily -// + Allows each node to store relative information on the traversal -template using InfoBFS = std::unordered_map>; -template using InfoDFS = std::unordered_map; // Edges stored as multimap> template using Edges = std::multimap>; - -/******************************************************************************/ -// MST search information structs - struct MST : SearchInfo { int32_t parent = INT32_MIN; int rank = 0; @@ -86,8 +134,9 @@ template struct InfoMST { template friend class Graph; - explicit InfoMST(const std::vector> &nodes) { - for (const auto &node : nodes){ + explicit InfoMST(const std::vector> &nodes) + { + for (const auto &node : nodes) { // Initialize the default values for forest tracked by this struct // + This data is used in KruskalMST() to find the MST MakeSet(node.data_); @@ -157,51 +206,6 @@ private: }; -/******************************************************************************/ -// Node structure for representing a graph - -template -struct Node { -public: - template friend class Graph; - template friend class InfoMST; - - // Constructors - Node(const Node &rhs) = default; - Node & operator=(Node rhs) { - if (this == &rhs) return *this; - swap(*this, rhs); - return *this; - } - Node(T data, const std::vector> &adj) - : data_(data) - { - // Place each adjacent node in vector into our unordered_map of edges - for (const auto &i : adj) adjacent_.emplace(i.first, i.second); - } - - friend void swap(Node &a, Node &b) { - std::swap(a.data_, b.data_); - std::swap(a.adjacent_, b.adjacent_); - } - - // Operators - // Define operator== for std::find; And comparisons between nodes - bool operator==(const Node &b) const { return this->data_ == b.data_;} - // Define an operator!= for comparing nodes for inequality - bool operator!=(const Node &b) const { return this->data_ != b.data_;} - - // Accessors - inline T GetData() const { return data_;} - inline std::unordered_map GetAdjacent() const { return adjacent_;} - -private: - T data_; - // Adjacent stored in an unordered_map - std::unordered_map adjacent_; -}; - - /******************************************************************************/ // Templated graph class @@ -209,7 +213,7 @@ template class Graph { public: // Constructor - Graph(std::vector> nodes) : nodes_(std::move(nodes)) {} + explicit Graph(std::vector> nodes) : nodes_(std::move(nodes)) {} // Breadth First Search InfoBFS BFS(const Node& startNode) const; diff --git a/cpp/algorithms/graphs/weighted/graph.cpp b/cpp/algorithms/graphs/weighted/graph.cpp index 97dd446..f31679d 100644 --- a/cpp/algorithms/graphs/weighted/graph.cpp +++ b/cpp/algorithms/graphs/weighted/graph.cpp @@ -1,8 +1,7 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: An example of a weighted graph implementation ## -## Algorithms in this example are found in MIT Intro to Algorithms ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: Driver program to test weighted graph implementation ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ################################################################################ @@ -105,7 +104,7 @@ int main (const int argc, const char * argv[]) // + Chapter 22, Figure 22.4 on DFS // Unlike the simple-graph example, this final result matches MIT Algorithms // + Aside from the placement of the watch node, which is not connected - // + This is because the node is visited after all other nodes are finished + // + This is because the node is visited after all other nodes are finished std::vector order = topologicalGraph.TopologicalSort(topologicalGraph.GetNodeCopy(6)); std::cout << "\nTopological order: "; diff --git a/cpp/algorithms/graphs/weighted/lib-graph.cpp b/cpp/algorithms/graphs/weighted/lib-graph.cpp index cc92072..f04d78b 100644 --- a/cpp/algorithms/graphs/weighted/lib-graph.cpp +++ b/cpp/algorithms/graphs/weighted/lib-graph.cpp @@ -1,7 +1,8 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: Driver program to test object graph implementation ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of a weighted graph implementation ## +## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ################################################################################ @@ -212,4 +213,3 @@ InfoMST Graph::KruskalMST() const return searchInfo; } - diff --git a/cpp/algorithms/graphs/weighted/lib-graph.hpp b/cpp/algorithms/graphs/weighted/lib-graph.hpp index 3944a14..334075c 100644 --- a/cpp/algorithms/graphs/weighted/lib-graph.hpp +++ b/cpp/algorithms/graphs/weighted/lib-graph.hpp @@ -1,7 +1,7 @@ /*############################################################################## ## Author: Shaun Reed ## -## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## -## About: An example of an object graph implementation ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of a weighted graph implementation ## ## Algorithms in this example are found in MIT Intro to Algorithms ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## @@ -10,56 +10,14 @@ #ifndef LIB_GRAPH_HPP #define LIB_GRAPH_HPP -#include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include - - -/******************************************************************************/ -// Structures for tracking information gathered from various traversals -struct Node; -// Color represents the discovery status of any given node -// + White is undiscovered, Gray is in progress, Black is fully discovered -enum Color {White, Gray, Black}; - -// Information used in all searches -struct SearchInfo { - // Coloring of the nodes is used in both DFS and BFS - Color discovered = White; -}; - -// Information that is only used in BFS -struct BFS : SearchInfo { - // Used to represent distance from start node - int distance = 0; - // Used to represent the parent node that discovered this node - // + If we use this node as the starting point, this will remain a nullptr - const Node *predecessor = nullptr; -}; - -// Information that is only used in DFS -struct DFS : SearchInfo { - // Create a pair to track discovery / finish time - // + Discovery time is the iteration the node is first discovered - // + Finish time is the iteration the node has been checked completely - // ++ A finished node has considered all adjacent nodes - std::pair discoveryFinish; -}; - -struct MST : SearchInfo { - int32_t parent = INT32_MIN; - int rank = 0; -}; - -// Store search information in unordered_maps so we can pass it around easily -// + Allows each node to store relative information on the traversal -using InfoBFS = std::unordered_map; -using InfoDFS = std::unordered_map; /******************************************************************************/ @@ -69,7 +27,8 @@ struct Node { public: // Constructors Node(const Node &rhs) = default; - Node & operator=(Node rhs) { + Node & operator=(Node rhs) + { if (this == &rhs) return *this; swap(*this, rhs); return *this; @@ -80,7 +39,8 @@ public: for (const auto &i : adj) adjacent.emplace(i.first, i.second); } - friend void swap(Node &a, Node &b) { + friend void swap(Node &a, Node &b) + { std::swap(a.number, b.number); std::swap(a.adjacent, b.adjacent); } @@ -95,10 +55,71 @@ public: bool operator!=(const Node &b) const { return this->number != b.number;} }; + +/******************************************************************************/ +// Base struct for storing traversal information on all nodes + +// Color represents the discovery status of any given node +enum Color { + // Node is marked as undiscovered + White, + // Node discovery is in progress; Some adjacent nodes have not been checked + Gray, + // Node has been discovered; All adjacent nodes have been checked + Black +}; + +// Information used in all searches +struct SearchInfo { + // Coloring of the nodes is used in both DFS and BFS + Color discovered = White; +}; + + +/******************************************************************************/ +// BFS search information struct + +// Information that is only used in BFS +struct BFS : SearchInfo { + // Used to represent distance from start node + int distance = 0; + // Used to represent the parent node that discovered this node + // + If we use this node as the starting point, this will remain a nullptr + const Node *predecessor = nullptr; +}; + +// Store search information in unordered_maps so we can pass it around easily +// + Allows each node to store relative information on the traversal +using InfoBFS = std::unordered_map; + + +/******************************************************************************/ +// DFS search information struct + +// Information that is only used in DFS +struct DFS : SearchInfo { + // Create a pair to track discovery / finish time + // + Discovery time is the iteration the node is first discovered + // + Finish time is the iteration the node has been checked completely + // ++ A finished node has considered all adjacent nodes + std::pair discoveryFinish; +}; + + +/******************************************************************************/ +// MST search information struct + +struct MST : SearchInfo { + int32_t parent = INT32_MIN; + int rank = 0; +}; +using InfoDFS = std::unordered_map; + using Edges = std::multimap>; struct InfoMST { - explicit InfoMST(const std::vector &nodes) { - for (const auto &node : nodes){ + explicit InfoMST(const std::vector &nodes) + { + for (const auto &node : nodes) { // Initialize the default values for forest tracked by this struct // + This data is used in KruskalMST() to find the MST MakeSet(node.number); @@ -154,11 +175,12 @@ struct InfoMST { } return searchInfo[x].parent; } - }; + /******************************************************************************/ // Graph class declaration + class Graph { public: // Constructor