Execution time of creating a graph adt in C++ - c++

Generally, is creating an undirected graph adt supposed to take a long time?
If I have a graph of 40 nodes, and each node is connected to 20% of the other nodes, my program will stall when it tries to link the nodes together.
The max I can really get up to is 20% density of 20 nodes. My code to link vertexes together looks like this:
while(CalculateDensity()){
LinkRandom();
numLinks++;
}
void LinkRandom(){
int index = rand()%edgeList.size();
int index2 = rand()%edgeList.size();
edgeList.at(index).links.push_back(edgeList.at(index2));
edgeList.at(index2).links.push_back(edgeList.at(index));
}
Is there any way to do this faster?
EDIT: Here is where the data structure declaration:
for(int i=0; i<TOTAL_NODES; i++){
Node *ptr = new Node();
edgeList.push_back(*ptr); //populate edgelist with nodes
}
cout<<"edgelist populated"<<endl;
cout<<"linking nodes..."<<endl;
while(CalculateDensity()){
LinkRandom();
numLinks++;
}

Seems to me that you're copying a growing structure with each push_back.
That could be the cause of slowness.
If you could show the data structure declaration I could try to be more specific.
edit I still miss the Node declaration, nevertheless I would try to change the edgeList to a list of pointers to Node. Then
// hypothetic declaration
class Node {
list<Node*> edgeList;
}
//populate edgelist with nodes
for(int i=0; i<TOTAL_NODES; i++)
edgeList.push_back(new Node());
....
void LinkRandom(){
int index = rand()%edgeList.size();
int index2 = rand()%edgeList.size();
edgeList.at(index)->links.push_back(edgeList.at(index2));
edgeList.at(index2)->links.push_back(edgeList.at(index));
}

Related

DFS traversal and cycle in directed graph

I have a directed graph. Initially, all nodes are assumed to be unvisited and flag is -1 in vector<int>flag. Now we start from a source node & push into stack<int>s and make flag[source]=0 . Now I do DFS traversal & push nodes if(flag[node]==-1)& make flag[node]=0. if all the DFS directed links are visited I pop the element of the stack and mark it flag[s.top()]=1; while pushing if we encounter a node with flag[nodes]==0, the cycle is detected and i do an increment in int final variable;`
you can see in my code, I am storing DFS traversal in a temp vector, which I think is garbage, how can I directly pass these connected nodes directly to check the flag and detect the cycle. currently my code works but fails for larger input. kindly looking for help.
#include<iostream>
#include<vector>
#include<stack>
#include<map>
using namespace std;
int mx=1e5+5;
vector<bool>vist(mx);
vector<vector<int>>Graph(mx);
void dfs(int node,vector<int>&dfs_vec){
vist[node]=true;
dfs_vec.push_back(node);
for(int neigh: Graph[node]){
if(!vist[neigh]){
dfs(neigh,dfs_vec);
}
}
}
//my temp vector is in while loop of main.
int main(){
int num_vertex;int num_edge;
cin>>num_vertex>>num_edge;
int u,v;
for(int i=0;i<num_edge;i++){
cin>>u>>v;
Graph[u].push_back(v);
}
vector<int>flag(num_vertex+1,-1);
stack<int>s;
int source=1;
s.push(source);
flag[source]=0;
int final=0;
while(!s.empty()){
int x=s.top();
vector<int>temp;
dfs(Graph[x][0],temp);
for(auto y:temp){
if(flag[y]==-1){
s.push(y);
flag[y]=0;
}
else if(flag[y]==0){
final++;
}
}
flag[s.top()]=1;
s.pop();
vist.clear();
vist.resize(mx);
}
if(final>0){
std::cout<<"Graph is cyclic";
}
else{
std::cout<<"Graph is not cyclic";
}
}
It is important to minimize the parameters in the signature of a recursive function if you want to handle large datasets. Each call requires the parameters to be kept on the stack, a fairly limited resource.
To minimize the parameters, use a method on a class which stores just one copy of the parameter data as an attribute whenever possible. For DFS, everything except the index of the currently visited node can be moved out of the parameter list.
Here is a straight forward implementation of DFS which I have used successfully on graphs containing hundreds of thousands of vertices.
void cPathFinder::depthRecurse(
int v )
{
visitor(v);
// remember this node has been visited
myPath[v] = 1;
// look for new adjacent nodes
for (int w : adjacent(v))
if (!myPath[w])
{
// search from new node
depthRecurse(w, visitor);
}
}
FYI here is brief discussion of some of the issues to think about when designing a class to implement graph theory algorithms. https://github.com/JamesBremner/PathFinder2/wiki/cGraph-Class-Design

How to std::move class with std::vector<class> member into another vector<class>?

I'm trying to linearize a hierarchy of 'Node' classes into a single (std::vector) array. This is a complete c++ program code demonstrating the problem, minimalized as much as I think is possible:
#include <iostream>
#include <vector>
struct Node;
struct B{
int nvar1;
std::vector<Node> Children;
};
struct Node{
B bvar1;
};
void Linearize(Node & NODE, std::vector<Node> & ArrayOfNodes){
std::cout<<"Linearizing started.\n";
ArrayOfNodes.push_back(std::move(NODE));
Node & node = ArrayOfNodes.back();
for(int n = 0; n < node.bvar1.Children.size(); n++){
std::cout<<"Running loop "<<n<<" of "<<node.bvar1.Children.size()<<"\n";
Linearize(node.bvar1.Children[n], ArrayOfNodes);
}
std::cout<<"Done with node linearization.\n";
}
int main(){
Node ParentNode;
//Fill the ParentNode
ParentNode.bvar1.nvar1 = 0;
ParentNode.bvar1.Children.resize(2);
ParentNode.bvar1.Children[0].bvar1.Children.resize(2);
ParentNode.bvar1.Children[0].bvar1.Children[0].bvar1.nvar1 = 1;
ParentNode.bvar1.Children[0].bvar1.Children[1].bvar1.nvar1 = 2;
ParentNode.bvar1.Children[1].bvar1.nvar1 = 3;
std::cout<<"I do get to the linearizing.\n";
std::vector<Node> ArrayOfNodes;
Linearize(ParentNode, ArrayOfNodes);
std::cout<<"I do get to the displaying part.\n";
for(int n = 0; n < ArrayOfNodes.size(); n++){
std::cout<<ArrayOfNodes[n].bvar1.nvar1<<"\n";
}
return 0;
}
This crashes the program. The output until the crash is:
I do get to the linearizing.
Linearizing started.
Running loop 0 of 2
Linearizing started.
Runnning loop 0 of 2
Linearizing started.
Done with node linearization.
Done with node linearization.
Running loop 1 of 18446744073709191157
Linearizing started.
Running loop 0 of 1011712
Linearizing started.
I'm trying to get an elegant and efficient solution here. The 'Node' class can get large and contains many other classes and vectors. Given the data size, I'm reluctant to construct move constructors/assignments to cover all that data structure.
What I want to do would work with this code:
void Linearize(Node & NODE, std::vector<Node> & ArrayOfNodes){
std::cout<<"Linearizing started.\n";
ArrayOfNodes.push_back(NODE);
Node & node = ArrayOfNodes.back();
for(int n = 0; n < NODE.bvar1.Children.size(); n++){
std::cout<<"Running loop "<<n<<" of "<<node.bvar1.Children.size()<<"\n";
Linearize(NODE.bvar1.Children[n], ArrayOfNodes);
}
std::cout<<"Done with node linearization.\n";
}
But that would copy stuff, when I want to move it. I want it to be more efficient than this.
Basically two question(s/ groups):
If default move constructer is called, why aren't the Nodes moved properly to ArrayOfNodes? Doesn't the default move constructor call the move constructor of every member, and std::vector has pointers inside anyway, so it should still point to the same data when moved? What part of the process am I misunderstanding?
What would be a standard/good/veteran coder solution to this kind of situation (linearization)?
Any and all comments welcome, this is my first question, if I'm doing something wrong or could just do better, tell me. Thanks!
What happens is that node is a reference (i.e. pointer) to an item in the std::vector that you are constructing. After taking the reference, you use push_back on the vector, which will grow the underlying array and hence might invalidate all pointers to it (growing the array often means a new, larger memory block is allocated and all data is moved to it). When you then want to access the next child of the node, you are referencing freed memory.
There are 3 ways to solve this. First, pre-allocate the array before starting the linearization process:
std::vector<Node> ArrayOfNodes;
ArrayOfNodes.reserve(numberOfNodes); // <-- you need to be able to determine this
Linearize(ParentNode, ArrayOfNodes);
A second solution would be to push the children on the vector before you move the node:
void Linearize(Node & NODE, std::vector<Node> & ArrayOfNodes){
std::cout<<"Linearizing started.\n";
for(int n = 0; n < NODE.bvar1.Children.size(); n++){
std::cout<<"Running loop "<<n<<" of "<< NODE.bvar1.Children.size()<<"\n";
Linearize(NODE.bvar1.Children[n], ArrayOfNodes);
}
ArrayOfNodes.push_back(std::move(NODE));
std::cout<<"Done with node linearization.\n";
}
A third solution would be to not take a reference to the node in the vector, but to take its index:
void Linearize(Node & NODE, std::vector<Node> & ArrayOfNodes){
std::cout<<"Linearizing started.\n";
size_t index = ArrayOfNodes.size();
ArrayOfNodes.push_back(std::move(NODE));
for(int n = 0; n < ArrayOfNodes[index].bvar1.Children.size(); n++){
std::cout<<"Running loop "<<n<<" of "<<ArrayOfNodes[index].bvar1.Children.size()<<"\n";
Linearize(ArrayOfNodes[index].bvar1.Children[n], ArrayOfNodes);
}
std::cout<<"Done with node linearization.\n";
}
A totally different approach would be to not move the nodes at all, but to construct a std::vector<Node*>, and fill it with pointers to the nodes. But that might not be what you're after.

Randomly shuffling a linked list

I'm currently working on a project and the last piece of functionality I have to write is to shuffle a linked list using the rand function.
I'm very confused on how it works.
Could someone clarify on how exactly I could implement this?
I've looked at my past code examples and what I did to shuffle an array but the arrays and linked lists are pretty different.
Edit:
For further clarifications my Professor is making us shuffle using a linked list because he is 'awesome' like that.
You can always add another level of indirection... ;)
(see Fundamental theorem of software engineering in Wikipedia)
Just create an array of pointers, sized to the list's length, unlink items from the list and put their pointers to the array, then shuffle the array and re-construct the list.
EDIT
If you must use lists you might use an approach similar to merge-sort:
split the list into halves,
shuffle both sublists recursively,
merge them, picking randomly next item from one or the other sublist.
I don't know if it gives a reasonable random distribution :D
bool randcomp(int, int)
{
return (rand()%2) != 0;
}
mylist.sort(randcomp);
You can try iterate over list several times and swap adjacent nodes with certain probablity. Something like this:
const float swapchance = 0.25;
const int itercount = 100;
struct node
{
int val;
node *next;
};
node *fisrt;
{ // Creating example list
node *ptr = 0;
for (int i = 0; i < 20; i++)
{
node *tmp = new node;
tmp.val = i;
tmp.next = ptr;
ptr = tmp;
}
}
// Shuffling
for (int i = 0; i < itercount; i++)
{
node *ptr = first;
node *prev = 0;
while (ptr && ptr->next)
{
if (std::rand() % 1000 / 1000.0 < swapchance)
{
prev->next = ptr->next;
node *t = ptr->next->next;
ptr->next->next = ptr;
ptr->next = t;
}
prev = ptr;
ptr = ptr->next;
}
}
The big difference between an array and a linked list is that when you use an array you can directly access a given element using pointer arithmetic which is how the operator[] works.
That however does not preclude you writing your own operator[] or similar where you walk the list and count out the nth element of the list. Once you got this far, removing the element and placing it into a new list is quite simple.
The big difference is where the complexity is O(n) for an array it becomes O(n^2) for a linked list.

Prim's Algorithm with matrices

I am trying to implement Prim's algorithm with C++ and matrices.
Here is my problem:
int node[] = {11, 11, 0, 11, 11, 11, 11, 11};
int nodeCon[8];
void generatePrims() {
int cNode = 3;
for (int i = 1; i <= 8; i++) {
if (graph[cNode][i] != 0){
if (node[i] > graph[cNode][i]) {
node[i] = graph[cNode][i];
nodeCon[i] = cNode;
}
}
}
};
cNode is the starting node.
graph[][] is the 2d matrices that holds the connections.
nodeCon[] is the array that will hold the connections for the MST (which node is connected with other)
node[]= holds the cost-value for the nodeCon.
My question is how I am going to continue to the next hop? Let's say that I found the minimum connection and I will set the value cNode= minConnection how the loop is going to look? How I know that I had examine all the nodes?
Thanks in advance
Something like this:
int node[]={11,11,0,11,11,11,11,11};
int used[]={0,0,0,0,0,0,0,0,0,0};
int nodeCon[8];
void generatePrims(){
int cNode = 3;
int next, min_now;
for(int i=0; i<8; ++i) {
used[cNode] = 1;
min_now = MAX_INT;
for(int i=1;i<=8;i++){
if(!used[i]){
if(node[i] > graph[cNode][i]){
node[i] = graph[cNode][i];
nodeCon[i]= cNode;
}
if(node[i] < min_now) {
min_now = node[i];
next = i;
}
}
}
cNode = next;
}
};
Also worth noting: it will be faster if instead of array 'used' you will use a list of unused vertices.
I can't currently comment on the previous answer (as I don't have enough reputation) so I will do it through another answer. Piotr solution is almost correct however I believe Prim's algorithm takes into account more than just the current node. An example can be seen here Prim's Algorithm. What this essentially means is you need to check the path from nodes you have visited not just the most recent node.
This means you will need to store a vector containing the nodes you have visited and "for each" through them as opposed to just checking the paths from the last node you visited.
The following site has the algorithm inplemented and a junit test class. So it should be what you are looking for. The unit test class has an actual matrix, of course. And the implementation class has the code.
http://www.geekviewpoint.com/java/graph/mst

BFS implementation

i was recently solving a bfs problem where each node is a different arrangement of elements of an array. but i was unable to come up with a suitable data structure to keep track of the visited nodes in the expanded tree. generally the nodes are different strings so we can just use a map to mark a node as visited but what DS should i use in the above case?
Consider the following pseudocode:
type Node; // information pertaining to a node
type Path; // an ordered list of nodes
type Area; // an area containing linked neighboring nodes
type Queue; // a FIFO queue structure
function Traverse(Area a, Node start, Node end) returns Path:
Queue q;
Node n;
// traverse backwards, from finish to start
q.push(end); // add initial node to queue
end.parent = end; // set first node's parent to itself
while (not q.empty()):
n = q.pop(); // remove first element
if (n == start) // if element is the final element, we're done
break;
for (Node neighbor in a.neighbors(n)): // for each neighboring node
if (neighbor.parent != Null): // if already visited, skip
continue;
neighbor.parent = n; // otherwise, visit
q.push(neighbor); // then add to queue
Path p; // prepare to build path from visited list
for (Node previous = Null, current = n;
previous != current;
previous = current, current = current.parent):
p.add(current); // for each node from start to end, add node to p
// Note that the first node's parent is itself
// thus dissatisfying the loop condition
return p;
The "visited list" is stored as the node's parent. Coding this to C++, you would probably handle most of the nodes as references or pointers since this pseudocode relies on referential behavior.
You start with an Area, which is a field of Nodes. The area knows where each node is in relation to the others. You start at one specific Node, the "start" node, and push it into a queue.
Traversing the area is as simple as getting the list of neighboring nodes from the Area, skipping them if they're already visited, and setting their parent and adding them to the queue otherwise. Traversal ends when a node removed from the queue equals the destination node. You could speed up the algorithm a little by doing this check during the neighbor loop, when the node is initially encountered.
NOTE: You do not need to generate every possible node within the area before beginning the traversal, the Area requires only that once it has created a node, it keeps track of it. This might help your situation where it appears you use permutations of strings or arrays: you could push the starting and ending nodes into the Area, and it could generate and cache neighbor nodes on the fly. You might store them as vectors, which can be compared for equality based on their order and contents with the == operator. See this example.
The traversal goes backwards rather than forwards because it makes rebuilding the path easier (rather than ending up at the end node, with each parent the node before it, you end up at the start node, with each parent the node after it)
Data Structure Summary
Node would need to keep track of enough information for Area to identify it uniquely (via an array index or a name or something), as well as a parent node. The parent nodes should be set to NULL before the traversal to avoid weird behavior, since traversal will ignore any node with its parent set. This keeps track of the visited state too: visited is equivalent to (parent != NULL). Doing it this way also keeps you from having to keep track of the entire path in the queue, which would be very computationally intensive.
Area needs to maintain a list of Node, and needs a neighbor map, or a mapping of which nodes neighbor which other nodes. It's possible that this mapping could be generated on the fly with a function rather than being looked up from a table or some more typical approach. It should be able to provide the neighbors of a node to a caller. It might help to have a helper method that clears the parents of every node as well.
Path is basically a list type, containing an ordered list of nodes.
Queue is whatever FIFO queue is available. You could do it with a linked list.
I like how the syntax highlighting worked on my Wuggythovasp++.
At least as a start, you could try using/implementing something like Java's Arrays.toString() and using a map. Each arrangement would result in a different string, and thus it'll at least get somewhere.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author VAISAKH N
*/
public class BFSME {
public static String path = "";
public static String add = "";
public static void findrec(String temp, String end, String[][] m, int j) {
if (temp.equals(m[j][1])) {
add = m[j][0] + temp + end + "/";
end = temp + end;
System.out.println(end);
path = path + add;
temp = "" + add.charAt(0);
System.out.println("Temp" + temp);
for (int k = 0; k < m.length; k++) {
findrec(temp, end, m, k);
}
}
}
public static void main(String[] args) {
String[][] data = new String[][]{{"a", "b"}, {"b", "c"}, {"b", "d"}, {"a", "d"}};
String[][] m = new String[data.length][2];
for (int i = 0; i < data.length; i++) {
String temp = data[i][0];
String end = data[i][1];
m[i][0] = temp;
m[i][1] = end;
path = path + temp + end + "/";
for (int j = 0; j < m.length; j++) {
findrec(temp, end, m, j);
}
}
System.out.println(path);
}
}
Just for the purpose of understanding, i have provided my sample code here (its in C#)
private void Breadth_First_Travers(Node node)
{
// First Initialize a queue -
// it's retrieval mechanism works as FIFO - (First in First Out)
Queue<Node> myQueue = new Queue<Node>();
// Add the root node of your graph into the Queue
myQueue.Enqueue(node);
// Now iterate through the queue till it is empty
while (myQueue.Count != 0)
{
// now, retrieve the first element from the queue
Node item = myQueue.Dequeue();
Console.WriteLine("item is " + item.data);
// Check if it has any left child
if (item.left != null)
{
// If left child found - Insert/Enqueue into the Queue
myQueue.Enqueue(item.left);
}
// Check if it has right child
if (item.right != null)
{
// If right child found Insert/Enqueue into the Queue
myQueue.Enqueue(item.right);
}
// repeat the process till the Queue is empty
}
}
Here sample code is give with reference of http://en.wikipedia.org/wiki/Binary_tree
as tree is a type of graph it self.
Here is BFS implementation using C++ STL(adjacency lists) for Graph. Here three Array and a Queue is used for complete implementation.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//Adding node pair of a Edge in Undirected Graph
void addEdge( vector<int> adj[], int u, int v){
adj[u].push_back(v); // 1st push_back
adj[v].push_back(u); //2nd push_back
//for Directed Graph use only one push_back i.e., 1st push_back() rest is same
}
//Traversing through Graph from Node 0 in Adjacency lists way
void showGraph( vector<int>adj[], int size){
cout<<"Graph:\n";
for(int i=0; i<size ; i++){
cout<<i;
for( vector<int>::iterator itr= adj[i].begin() ; itr!=adj[i].end(); itr++){
cout<<" -> "<<*itr;
}
cout<<endl;
}
}
//Prints Array elements
void showArray(int A[]){
for(int i=0; i< 6; i++){
cout<<A[i]<<" ";
}
}
void BFS( vector<int>adj[], int sNode, int N){
// Initialization
list<int>queue; //Queue declaration
int color[N]; //1:White, 2:Grey, 3:Black
int parentNode[N]; //Stores the Parent node of that node while traversing, so that you can reach to parent from child using this
int distLevel[N]; //stores the no. of edges required to reach the node,gives the length of path
//Initialization
for(int i=0; i<N; i++){
color[i] = 1; //Setting all nodes as white(1) unvisited
parentNode[i] = -1; //setting parent node as null(-1)
distLevel[i] = 0; //initializing dist as 0
}
color[sNode] = 2; //since start node is visited 1st so its color is grey(2)
parentNode[sNode] = -1; //parent node of start node is null(-1)
distLevel[sNode] = 0; //distance is 0 since its a start node
queue.push_back(sNode); //pushing start node(sNode) is queue
// Loops runs till Queue is not empty if queue is empty all nodes are visited
while( !queue.empty()){
int v = queue.front(); //storing queue's front(Node) to v
// queue.pop_front();//Dequeue poping element from queue
//Visiting all nodes connected with v-node in adjacency list
for(int i=0; i<adj[v].size() ;i++){
if( color[ adj[v][i] ] == 1){// if node is not visited, color[node]==1 which is white
queue.push_back(adj[v][i]); //pushing that node to queue
color[adj[v][i]]=2; //setting as grey(2)
parentNode[ adj[v][i] ] = v; //parent node is stored distLevel[ adj[v][i] ] = distLevel[v]+1; //level(dist) is incremented y from dist(parentNode)
}
}//end of for
color[v]=3;
queue.pop_front();//Dequeue
}
printf("\nColor: \n");showArray(color);
printf("\nDistLevel:\n");showArray(distLevel);
printf("\nParentNode:\n");showArray(parentNode);
}
int main(){
int N,E,u,v;//no of nodes, No of Edges, Node pair for edge
cout<<"Enter no of nodes"<<endl;
cin>>N;
vector<int> adj[N]; //vector adjacency lists
cout<<"No. of edges"<<endl;
cin>>E;
cout<<"Enter the node pair for edges\n";
for( int i=0; i<E;i++){
cin>>u>>v;
addEdge(adj, u, v); //invoking addEdge function
}
showGraph(adj,N); //Printing Graph in Adjacency list format
BFS(adj,0,N); /invoking BFS Traversal
}