[C++]Project #3 – Traversing Property Graphs EDIT: in reply to the comment, what
ID: 3913947 • Letter: #
Question
[C++]Project #3 – Traversing Property Graphs
EDIT: in reply to the comment, what excerpt are you talking about?
EDIT #2 : Need to construct a directed graph, where the property names label edges connecting nodes; either using array or linked list implementation.
Learning Objectives
Implement a data structure to meet given specifications
Design, implement, and use a graph data structure
Perform analysis of algorithm performance
Utilize Dijkstra's algorithm
Overview
Your task for this assignment is to implement a graph data structure and find appropriate shortest paths, while accounting for property-labelled edges.
The Graph class
At this point in the course, I leave it to your discretion to choose an appropriate implementation (i.e. array vs linked). Note that you may need a class for Nodes or Edges. Furthermore, you may use vectors, hashtables, or any other data structure used in class. Any manually implemented classes beyond the Graph shall be inline.
The first block consists of an integer telling the reader how many people (nodes) to expect, followed by that many names. It is not guaranteed that only first names will be in the file. The second block consists of an integer that tells the reader how many properties to expect. Then, for that many properties, the property name is given, followed by an adjacency matrix for that property. Of course the adjacency matrix is square, with rows and columns equal to the number of nodes in the graph. No property is reflexive.
Using the information in this file, you are to construct a directed graph, where the property names label edges connecting nodes.
I obviously made up the property names after drawing the graph... hahaha
bool Graph::construct(string filename) – construct the graph from the file called filename and return false if the graph construction failed. The file will have the following structure.
Node Graph::findPerson(string name) – If there is a node with the given name in the graph, it is returned, otherwise the function returns nullptr.
bool Graph::findPath(string name, string other) – If both people are in the graph, find the shortest path between them.
Your Graph should overload operator<< such that cout << myGraph prints all the nodes in the graph, along with their related nodes. See below for an excerpt.
Your Graph also should overload operator== such that mG1 == mG2 is accurately determined.
Turn in and Grading
The Graph class should be implemented as an inline class in the file Graph.h.
This project is worth 50 points, distributed as follows:
Task Points Graph::construct properly constructs the graph from the given file. 10 Graph::findPerson successfully determines if a person is in a graph. 5 Graph::findPath correctly finds the shortest path between two nodes. It shall print out the path or state that no path could be found. 15 operator<< is correctly overloaded to print the graph. Each node and their relationship to other nodes shall be printed. 5 operator== is correctly overloaded to determine equivalence between two graphs. 5 Code is well organized, well documented, and properly formatted. Variable names are clear, and readable. 10Explanation / Answer
need for construct a directed graph, where the property names label edges connecting nodes; either using array or linked list implementation.
Digraph(directed graph) objects represent directed graphs, which have directional edges connecting the nodes. After you create a digraph object, you can learn more about the graph by using the object functions to perform queries against the object. For example, you can add or remove nodes or edges, determine the shortest path between two nodes, or locate a specific node or edge.
G = digraph([1 1], [2 3])
e = G.Edges
G = addedge(G,2,3)
G = addnode(G,4)
plot(G)
Syntax
G = digraph
G = digraph(A)
G = digraph(A,nodenames)
G = digraph(A,NodeTable)
G = digraph(A,___,'OmitSelfLoops')
G = digraph(s,t)
G = digraph(s,t,weights)
G = digraph(s,t,weights,nodenames)
G = digraph(s,t,weights,NodeTable)
G = digraph(s,t,weights,num)
G = digraph(s,t,___,'OmitSelfLoops')
G = digraph(s,t,EdgeTable,___)
G = digraph(EdgeTable)
G = digraph(EdgeTable,NodeTable)
G = digraph(EdgeTable,___,'OmitSelfLoops')
2.Implement a data structure to meet given specifications
Design, implement, and use a graph data structure
Code::-
// Program to print BFS traversal from a given
// source vertex. BFS(int s) traverses vertices
// reachable from s.
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Breadth First Traversal "
<< "(starting from vertex 2) ";
g.BFS(2);
return 0;
}
Run on IDE
3.
Perform analysis of algorithm performance
How long does breadth-first search take for a graph with vertex set VVV and edge set EEE? The answer is O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis time.
Let's see what O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis time means. Assume for the moment that |E| geq |V|?E???V?vertical bar, E, vertical bar, is greater than or equal to, vertical bar, V, vertical bar, which is the case for most graphs, especially those for which we run breadth-first search. Then |V| + |E| leq |E| + |E| = 2 cdot |E|?V?+?E???E?+?E?=2??E?vertical bar, V, vertical bar, plus, vertical bar, E, vertical bar, is less than or equal to, vertical bar, E, vertical bar, plus, vertical bar, E, vertical bar, equals, 2, dot, vertical bar, E, vertical bar. Because we ignore constant factors in asymptotic notation, we see that when |E| geq |V|?E???V?vertical bar, E, vertical bar, is greater than or equal to, vertical bar, V, vertical bar, O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis really means O(E)O(E)O, left parenthesis, E, right parenthesis. If, however, we have |E| < |V|?E?<?V?vertical bar, E, vertical bar, is less than, vertical bar, V, vertical bar, then |V| + |E| leq |V| + |V| = 2 cdot |V|?V?+?E???V?+?V?=2??V?vertical bar, V, vertical bar, plus, vertical bar, E, vertical bar, is less than or equal to, vertical bar, V, vertical bar, plus, vertical bar, V, vertical bar, equals, 2, dot, vertical bar, V, vertical bar, and so O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis really means O(V)O(V)O, left parenthesis, V, right parenthesis. We can put both cases together by saying that O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis really means O(max(V,E))O(max(V,E)). In general, if we have parameters xxxand yyy, then O(x+y)O(x+y)O, left parenthesis, x, plus, y, right parenthesis really means O(max(x,y))O(max(x,y)).
(Note, by the way, that a graph is connected if there is a path from every vertex to all other vertices. The minimum number of edges that a graph can have and still be connected is |V|-1?V??1vertical bar, V, vertical bar, minus, 1. A graph in which |E| = |V|-1?E?=?V??1vertical bar, E, vertical bar, equals, vertical bar, V, vertical bar, minus, 1 is called a free tree.)
How is it that breadth-first search runs in O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis time? It takes O(V)O(V)O, left parenthesis, V, right parenthesis time to initialize the distance and predecessor for each vertex (Theta(V)?(V) time, actually). Each vertex is visited at most one time, because only the first time that it is reached is its distance null, and so each vertex is enqueued at most one time. Since we examine the edges incident on a vertex only when we visit from it, each edge is examined at most twice, once for each of the vertices it's incident on. Thus, breadth-first search spends O(V+E)O(V+E)O, left parenthesis, V, plus, E, right parenthesis time visiting vertices.
4.Utilize Dijkstra's algorithm
5. graph class
Building a simple tree
Now let’s look how to build a tree in ActionScript. First we create the root of the tree and get an iterator pointing to this node:
var tree:TreeNode = new TreeNode("root");
var itr:TreeIterator = tree.getTreeIterator();
The root has three children, so lets add them:
for (var i:int = 0; i < 3; i++)
{
itr.appendChild("node" + i);
}
Now the root’s second child (‘node1’) has children by itself. To insert them, we first have to adjust the vertical iterator so it points to ‘node1’. First one step to the right, then one step down the tree:
itr.nextChild();
itr.down();
Now we can add ‘node3’ and ‘node4’, this time in a reverse order:
itr.prependChild("node" + 3);
itr.prependChild("node" + 4);
The first time we add a child node to an empty node, the horizontal iterator is automatically initialized to point to the first child, which in this case is ‘node4’. So to create ‘node5’ and ‘node6’ we only need to go another step down.
itr.down();
itr.appendChild("node" + 5);
itr.appendChild("node" + 6);
Finally we want to add ‘node7’. Therefore we ‘bubble up’ the tree until we arrive at the root node, go to the rightmost child, one step down and add it:
itr.root();
itr.childEnd();
itr.down();
itr.appendChild("node" + 7);
The dump() method invoked on the root node prints out the complete tree, as you can see it matches the tree above.
[TreeNode > (root) has 3 child nodes, data=root]
+---[TreeNode > (leaf), data=node0]
+---[TreeNode > has 2 child nodes, data=node1]
| +---[TreeNode > has 2 child nodes, data=node4]
| | +---[TreeNode > (leaf), data=node5]
| | +---[TreeNode > (leaf), data=node6]
| +---[TreeNode > (leaf), data=node3]
+---[TreeNode > has 1 child nodes, data=node2]
| +---[TreeNode > (leaf), data=node7]
Preorder and postorder traversal
Now that you have created a tree structure, you need a way of traversing the nodes so you access the node’s data. There are two common recursive algorithms for doing this. The preorder function first visits the node that is passed to the function and then loops through each child calling the preorder function on each child. The postorder on the other hand does the opposite: It visits the current node after its child nodes.
To see this in action just click a node in the demo below. The numbers indicate the order in which the nodes are visited.
The TreeNode class also supports a regular iterator using hasNext() and next(). This matches the preorder iterator, but is implemented in a non-recursive way.
// Program to print BFS traversal from a given
// source vertex. BFS(int s) traverses vertices
// reachable from s.
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Breadth First Traversal "
<< "(starting from vertex 2) ";
g.BFS(2);
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.