A C++ implementation of topological ordering - c++

This morning I was doing my C++ class assignment, an implementation of topological ordering. There's no error while compiling, but simply can't run. Since I'm not quite familiar with pointers or STL, nor the VS debugger...I just can't figure out where went wrong. It would help me a lot if someone can point out my errors. Tons of thanks!
Here's my code:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef struct Vertex{
int index;
int indegree; // indegree of vertex v is the total num of edges like(u,v)
vector<Vertex>adjacent;
int topoNum; // topological order of this vertex.
}Vertex;
typedef struct Edge{
Vertex start;
Vertex in;
}Edge;
Vertex*InDegrees(int numVertex,int numEdge,Edge*edges) // calculate indegrees of all vertices.
{
Vertex*vertices=new Vertex[numVertex];
for(int i=0;i<numVertex;i++){ vertices[i].index=i; vertices[i].indegree=0;}
for(int i=0;i<numEdge;i++)
{
int j=edges[i].in.index;
vertices[j].indegree++;
vertices[j].adjacent.push_back(edges[i].start);
}
return vertices;
}
int*topoSort(int numVertex,int numEdge,Edge*edges)
{
edges=new Edge[numEdge];
Vertex*Vertices=new Vertex[numVertex];
Vertices=InDegrees(numVertex,numEdge,edges);
queue<Vertex>q;
for(int i=0;i<numVertex;i++)
{
if(Vertices[i].indegree==0)
q.push(Vertices[i]);
}
int count=0;
while(!q.empty()) // Ordering completed when queue is empty.
{
Vertex v=q.front(); // get the vertex whose indegree==0
q.pop();
v.topoNum=++count;
vector<Vertex>::iterator iter;
for(iter=v.adjacent.begin();iter!=v.adjacent.end();iter++)
{
Vertex w=*iter;
if(--w.indegree==0)
q.push(w);
}
}
int*topoOrder=new int[numVertex];
for(int i=0;i<numVertex;i++)
{
int j=Vertices[i].topoNum;
topoOrder[j]=-1; // initial value, in case cycle existed.
topoOrder[j]=Vertices[i].index;
}
delete[]Vertices;
delete[]edges;
return topoOrder;
}
int main()
{
int numVertex,numEdge;
cin>>numVertex>>numEdge;
Edge*Edges=new Edge[numEdge];
int indexStart,indexIn;
for(int i=0;i<numEdge;i++)
{
cin>>indexStart>>indexIn;
Edges[i].in.index=--indexIn;
Edges[i].start.index=--indexStart;
}
int*topoOrder=new int[numVertex];
topoOrder=topoSort(numVertex,numEdge,Edges);
for(int i=0;i<numVertex-1;i++)
{
if(topoOrder[i]==-1)
{
cout<<"Cycle exists, not a DAG!";
return 0;
}
cout<<topoOrder[i]<<",";
}
cout<<topoOrder[numVertex-1]<<endl;
delete[]Edges;
return 0;
}

An obvious starting point for your problems is the allocation for Edges: the allocation uses the uninitialized value numEdge which is likely to be zero. That is, you'll get a pointer to no elements. You probably want to allocate Edges only after having read numEdge. I didn't really had a look at what happens in the actual algorithm.
I also strongly recommend that you verify that the input operations were successful:
if (std::cin >> numVertex >> numEdge) {
use_successfully_read(numVertex, numEdge);
}
If inputs fail the variable remain unchanged and the values will also lead to interesting behavior.

Related

C++- How to increase stack size to allow more recursion for Kosaraju's Algorithm to compute Strongly Connected Components

I am using a mac, 4GB of RAM and CLion IDE. Compiler is Clang. I need to allow more recursion in this recursive implementation of Depth First Search (currently fails on a graph with 80k nodes).
typedef unordered_map <int, vector<int>> graph;
void DFS (graph &G, int i, vector <bool> &visited) {
visited[i] = true;
for (int j = 0; i < G[i].size(); j++) {
if (!visited[G[i][j]]) {
DFS(G, G[i][j], visited);
}
}
t++;
finishingTime[t] = i; //important step
}
This is for an implementation of Kosaraju's algorithm to compute strongly connected components in a graph. https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm I know it is possible to implement DFS as iterative instead but the last step is important, and I can't find a way to include it using iteration. This is because that step is done when DFS fails and backtracking occurs, and recursion provides a very natural way to do this.
So currently I have only two options:
Increase the stack size to allow more recursion
Or find an iterative solution
Any ideas how to do either?
As suggested by a comment you can put each call to DFS on a stack allocated on heap made from the parameter list of DFS and then iterate through the stack. Each entry in the stack is essentially a task.
Pseudo-like code:
Start and run "recursion":
nr_of_recursions = 0;
dfs_task_stack.push(first_task_params)
while dfs_task_stack not empty
DFS(dfs_task_stack.pop)
nr_of_recursions += 1
end while;
true_finishingtime[] = nr_of_recursions - finishingtime[];
DFS:
for each recursion found
dfs_task_stack.push(task_params)
end for;
t++; finishingtime...
Not sure of your algorithm but it may be significant which order you push your tasks to the stack, i.e. the order of "for each ...".
I took the liberty of redefining the meaning of "finishingtime" to its inverse. To get the original definition substract the new finishingtime with the total number of recursions made.
I don't know if this is the best solution but you can build the list of finished times using just a stack and a visited state array, by having more than one visited state.
The following code is just to illustrate the algorithm. I didn't actually tested it a lot (just a little {{0, {1}}, {1, <>}, {2, <>}} small test) but I already used this technique in the very same way in the past for bigger graphs and I know it works.
The idea is to keep the visited node in the stack after it's being visited until all visited before it are pop, thus emulating the recursive call but with less data pushed and in a stack object.
#include <iostream>
#include <vector>
#include <stack>
#include <cassert>
#include <unordered_map>
using namespace std;
typedef enum {
vssClean,
vssPushed,
vssVisited
} VerticeStackState;
typedef unordered_map <int, vector<int>> graph;
void kosarajuBuildFinishOrder(const int inital, graph &G, vector<int> &finish, vector<VerticeStackState> &state, int &lastFinished) {
assert(vssClean == state[inital]);
std::stack<int> stack;
stack.push(inital);
state[inital] = vssPushed;
int current;
while (!stack.empty())
{
current = stack.top();
if (vssPushed == state[current])
{
state[current] = vssVisited;
for (const auto to: G[current])
{
if (state[to]==vssClean)
{
state[to] = vssPushed;
stack.push(to);
}
}
}
else {
assert(vssVisited == state[current]);
stack.pop();
finish[--lastFinished] = current;
}
}
}
int main() {
graph G;
G.insert({0, vector<int>(1, 1)});
G.insert({1, vector<int>()});
G.insert({2, vector<int>()});
vector<int> finish(G.size(), 0);
vector <VerticeStackState> state(G.size(), vssClean);
int lastFinished = G.size();
for (int i=0; i < G.size(); ++i) {
if (vssClean == state[i]){
kosarajuBuildFinishOrder(i, G, finish, state, lastFinished);
}
}
for (auto i: finish) {
cout << i << " ";
}
return 0;
}
For one of the options you mentioned about increasing the stack size, you can do as such:
g++ -Wl,--stack,16777216 -o kosaraju.exe kosaraju_stl.cpp
This increases the stack size to 16MiB. While as mentioned in earlier answers, it's just postponing the problem.
typedef unordered_map <int, vector<int>> graph;
void DFS (graph &G, vector <bool> &visited) {
std::stack<int> stack;
stack.push(0); // root
int i, j;
while(!stack.empty())
{
i = stack.pop_back();
visited[i] = true;
for (j= (int) G[i].size() -1; j >= 0; j--)
{
if (!visited[G[i][j]])
{
stack.push_back(G[i][j]);
}
}
t++;
finishingTime[t] = i; //important step
} // end while.
}
Anyone can make a programming error and since I don't have your test data I can't test this, but is output the same?

Problems in evaluating subgraphs of a graph

Here is the question link.
Given an undirected graph. Density of a graph is |E|⁄|V|. Your task is to choose non-empty set of vertices V such that subgraph induced on V has maximal density and print this density. But if maximal density is strictly greater than 1, just print ">1".
Maximum number of vertices: 105
Maximum number of edges: 105
I just made a simple solution, but in this solution I can keep track of the whole graph, but how do I get the value of density for smaller subGraphs?
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[1000002]; // adjacency lists adj for storing graph edges
int node=0; // initializing for node value(vertices)
bool visited[100001]={false}; // keeps track of visited nodes(vertices)
int edge=-1;
int ans=-1;
int n; // keeps optimum value of no. of nodes
int e; // keeps optimum value of no. of edges
void dfs(int s)
{
node++;
edge++;
if(edge>0)
{
float dummy=(float)edge/(float)node;
if(dummy>ans)
{ans=dummy;
e=edge;
n=node;
}
}
visited[s]=true;
int t;
for(int i=0;i!=adj[s].size();i++)
{ t=adj[s][i];
if(visited[t]==false)
{
dfs(t);
}
}
}
int main()
{
long long v,ed,i,j,x,y;
cin>>v>>ed;
for(long long k=0;k<ed;k++)
{
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
if(ed>v)
cout<<">1"<<endl;
else{
for(i=1;i<=v;i++)
{
if(visited[i]==false)
{
node=0;
edge=-1;
dfs(i);
//cout<<e<<"/"<<n<<endl;
}
}
cout<<e<<"/"<<n<<endl;}
}
Follow these steps to get better result:
1.Do a dfs on each component to get the answer.
2.Avoid the floating point calculation you are doing and try all integer calculation.
3.No reason to use long long here with that range
Change the code to something like this should work:
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[1000002]; // adjacency lists adj for storing graph edges
int node=0; // initializing for node value(vertices)
bool visited[100001]={false}; // keeps track of visited nodes(vertices)
int edge=0;
void dfs(int s)
{
node++;
visited[s]=true;
int t;
edge+=adj[s].size();
for(int i=0;i!=adj[s].size();i++)
{
t=adj[s][i];
if(visited[t]==false)
{
dfs(t);
}
}
}
int main()
{
int v,ed,i,j,x,y;
cin>>v>>ed;
for(int k=0;k<ed;k++)
{
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
int mark[3]; mark[0]=mark[1]=mark[2]=0;
int mx_node=0;
for(i=1;i<=v;i++)
{
if(visited[i]==false)
{
node=0;
edge=0;
dfs(i);
edge/=2;
if(node>edge){
mark[0]=1;
mx_node=mx_node<node?node:mx_node;
}
else if(node==edge) mark[1]=1;
else mark[2]=1;
}
}
if(mark[2]) printf(">1\n");
else if(mark[1]) printf("1\n");
else printf("%d/%d\n",mx_node-1,mx_node);
}

Segmentation Fault C++

The input is in the following format
5
1 2 9.0
1 3 12.0
2 4 18.0
2 3 6.0
2 5 20.0
3 5 15.0
0
1 5
The first number is the number of vertexes in the graph. Then next lines up to 0 are the edges of the graph. With the first and second numbers being the vertexes and the third being how far the edge is between them. Trying to read in the data and store the edges into there locations in the List adjacency for that vertex. This example would make a graph with five vertexes with edges from 1 to 2&3. 2 to 4&3&1 etc.
I am getting a Segmentation fault after entering four numbers. The fault is happening on line myGraph.vertexInfo[p1].adjacency -> vertex=p2; where is starts trying to store the information. Why am I getting this fault?
#include <cstdio>
using namespace std;
struct ListCell
{
ListCell* next;
int vertex;
double weight;
ListCell(int v, double w, ListCell* nxt)
{
vertex = v;
weight = w;
next = nxt;
}
};
typedef ListCell* List;
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
struct Graph
{
int numVertices;
Vertex* vertexInfo;
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
}
}
};
//==============================================================
// readIn
//==============================================================
//
//==============================================================
void readIn()
{
int g;
int p1;
int p2;
float edge;
scanf("%i ", &g);
Graph myGraph(g);
scanf("%i", &p1);
while(p1 != 0)
{
scanf("%i", &p2);
scanf("%f", &edge);
myGraph.vertexInfo[p1].adjacency -> vertex=p2;
myGraph.vertexInfo[p2].adjacency -> vertex=p1;
myGraph.vertexInfo[p1].adjacency -> weight=edge;
myGraph.vertexInfo[p2].adjacency -> weight=edge;
scanf("%i", &p1);
}
}
//==============================================================
// main
//==============================================================
int main(int argc, char** argv)
{
readIn();
return 0;
}
You are not following some of the fundamental principles of object construction and intialization for Vertex.
When you construct an instance of Vertex, there is nothing predictable about the values of the member data. I would suggest adding a default constructor that initializes the member data to something sane.
struct Vertex
{
Vertex() : signaled(false), distance(0), adjacency(NULL) {}
bool signaled;
long distance;
List adjacency;
};
Once you do that, the constructor for Graph can be simplified to:
Graph(int n) : numVertices(n)
{
vertexInfo = new Vertex[n+1];
}
Let's look at what adjacency is:
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
And now let's look at what List is:
typedef ListCell* List;
So, adjacency is actually a pointer to a ListCell. That's fine, we can work with that. But before we can, we must make sure that adjacency actually points to something. The question then becomes what does adjacency point to in your code?
The answer is: who knows? You never make it point to anything, so it's pointing somewhere randomly. And what happens when you try to write to some random area of memory? Well, if you're lucky, you crash.
So, how do you solve this problem? Simple: initialize and manipulate adjacency correctly. You may wish to look into dynamic memory allocation in C++ and the standard library which provides a rather nifty and working implementation of a linked list.
Sidenote: you seem to treat adjacency as a linked list. However, you ought to note that adjacency is a pointer to a node in a linked list. Again, now would a great time to learn about std::list.
The adjacency pointer is uninitialized, so you run into problems when dereferencing it.
You have to initialize your adjacency member:
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
vertexInfo[i].adjacency = new ListCell(i, 0.0, 0);
}
}

How store class objects in vector<vector<class *>> and access and pass them to function either by reference or value

#ifndef BINARY_TREE_H
#define BINARY_TREE_H
#include<iostream>
#include<vector>
using namespace std;
class Binary_Tree;
static int levelCount=0;
extern vector<vector<Binary_Tree*>> vec;
extern vector<Binary_Tree*> tempVec;
class Binary_Tree
{
public:
Binary_Tree()
{
childNum=0;
data=0;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
};
Binary_Tree(int d)
{
childNum=0;
data=d;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
levelCount++;
}
void insert_node(int,int,int);
int get_level();
int get_childCount();
friend int set_childNum(Binary_Tree*);
private:
int childNum;
int data;
int level;
Binary_Tree *prev;
Binary_Tree *next[2];
};
#endif // BINARY_TREE_H
Here is the implementation file
#include<iostream>
#include<cmath>
#include "Binary_Tree.h"
using namespace std;
void Binary_Tree::insert_node(int lev, int d, int sib)
{
if(vec.empty())
{
cout<<"You Have to create Root first";
}
else
{
if(set_childNum(vec[lev][sib-1])==0)
{
cout<<"Child cant be created parent Node already has two childs.";
}
else
{
childNum=set_childNum(vec[lev][sib-1]);
data=d;
level=lev+1;
prev=vec[lev][sib];
next[0]=NULL;
next[1]=NULL;
tempVec.clear();
for(int i=0; i<pow(2,(lev+1)); i++)
{
if(i==childNum-1)
{
tempVec.push_back(this);
}
else
tempVec.push_back(vec[lev][i]);
}
vector<vector<Binary_Tree*>>::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
}
}
}
int set_childNum(Binary_Tree *lstNdAdr)
{
if(lstNdAdr->get_childCount()==0)
return 1;
else if(lstNdAdr->get_childCount()==1)
return 2;
else
return 0;
}
int Binary_Tree::get_level()
{
return level;
}
int Binary_Tree::get_childCount()
{
if(next[0]==NULL)
{
return 0;
}
else if(next[0]!=NULL && next[1]==NULL)
{
return 1;
}
else
{
return 2;
}
}
MAIN.cpp
#include <iostream>
#include<cmath>
#include"Binary_Tree.h"
using namespace std;
vector<vector<Binary_Tree*>> vec;
vector<Binary_Tree*> tempVec;
int main()
{
Binary_Tree tree;
here:
cout<<"Enter your Choice:1.Create Root Of Tree\n"
<<"2.Insert node\n"<<endl;
int choice;
cin>>choice;
switch(choice)
{
case 1:
{
int d;
cout<<"Enter Data to insert: ";
cin>>d;
Binary_Tree treeDummy(d);
tree=treeDummy;
tempVec.push_back(&tree);
vec.push_back(tempVec);
}
break;
case 2:
{
int lev;
int sibbling;
int d;
cout<<"Enter at which level and data and parent's sibling-no.: ";
cin>>lev;
cin>>d;
cin>>sibbling;
if(sibbling>pow(2,lev))
cout<<"Illegal Sibbling Number."<<endl;
else
tree.insert_node(lev,d,sibbling);
}
break;
}
int x;
cin>>x;
if(x==5)
{
cout<<endl<<endl;
goto here;
}
return 0;
}
in above code i am trying to create a binary tree type structure which can be manipulated and traversed dynamically that is any node can be inserted and can be removed at run time (although its incomplete because i am stuck at a problem). While pushing back the tempVec vector the code produces a segmentation fault and i am also doubtful in passing the object stored in vetcor> vec to the functions in the implementation (I am new to Stl and first time dealing with vector of vectors containing pointer to the class types)
The nested vector's entries are only filled if i is set to 1. But you attempt to access its element [0][0] regardless. You have out of bounds access when i is not 1.
There are numerous problems present in your code, that and combined with the poor style and formatting makes it not so fun to debug.
Binary_Tree treeDummy(d);
tree = treeDummy;
tempVec.push_back(&tree);
I'm not sure what you're trying to do here but the above looks wrong. You are shallow copying treeDummy's data over to tree. You'll lose the link to whatever child node tree points to. Afterwards you're pushing that same tree instance into your temporary vector. That means all the elements in your vector ends up pointing to the local variable tree in main. So even if no segfault occurred you would run into aliasing problems since they all refer to the same tree object and not a separate unique BinaryTree instance.
vector< vector<Binary_Tree*> >::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
Your BinaryTree::insert_node is using an invalidated iterator after performing erase which is undefined behavior.
childNum = set_childNum(vec[lev][sib-1]);
// ...
prev = vec[lev][sib];
The above can access an out-of-bound index in your vector. eg. You push_back a tempVec with only 1 element in it and then call insert_node with sib = 1.
// ...
if(x == 5)
{
cout<<endl<<endl;
goto here;
}
The use of goto is also completely unnecessary here and should be replaced with a traditional while loop that checks for condition != 5.
The higher level problem in your program, however, is that there's no clear constraints and invariants in its design. What assumptions and preconditions do each of those functions need to work? Why use vectors to hold BinaryTree nodes when the class itself should be dealing with that. You should get the overall design sorted out first, otherwise you'll just play whack-a-mole as other bugs crop up.

Constructor issue <Unable to read memory>

I have to create a class Histogram and make operations on this class. The input can be one dimensional array or a two dimensional array. The problem appears when i convert the array into a matrix. This what i have tried so far. The error is <Unable to read memory>
histrogram.h
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include<iostream>
class Histogram
{
private:
int** matrix;
int lines;
void SortMatrix();
public:
Histogram(){ }
Histogram(int elements[], int elementsNr);
Histogram(int** m, int l);
void Print();
};
#endif
historgram.cpp
#include"histogram.h"
using namespace std;
Histogram::Histogram(int** m, int l)
{
matrix=m;
lines=l;
SortMatrix();
}
Histogram::Histogram(int elements[], int elementsNr)
{
lines=0;
//initialize matrix : elementrNr lines and 2 columns
int** matrix=new int*[elementsNr];
for(int i=0;i<elementsNr;i++)
{
matrix[i]=new int[2];
matrix[i][0]=INT_MIN;
matrix[i][1]=INT_MIN;
}
//search each element from the array in the matrix
bool found=false;
for(int i=0;i<elementsNr;i++)
{
found=false;
for(int j=0;j<elementsNr;j++)
{
//the element was found in the matrix ( on the first column )
if(matrix[j][0] == elements[i])
{
matrix[j][1]++;
found=true;
break;
}
}
if(!found)
{
matrix[lines][0]=elements[i];
matrix[lines][1]=1;
lines++;
}
}
SortMatrix();
}
void Histogram::SortMatrix()
{
bool flag=true;
int temp;
for(int i=0;(i<lines) && flag;i++)
{
flag=false;
if(matrix[i+1][0]>matrix[i][0])
{
temp=matrix[i][0];
matrix[i][0]=matrix[i+1][0];
matrix[i+1][0]=temp;
flag=true;
}
}
}
void Histogram::Print()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : " <<matrix[i][1]<<endl;
}
}
main.cpp
#include"histogram.h"
#include<iostream>
using namespace std;
int main()
{
int arr[]={6,7,3,1,3,2,4,4,7,5,1,1,5,6,6,4,5};
Histogram h(arr,17);
h.Print();
}
Here
int** matrix=new int*[elementsNr];
replace with
matrix=new int*[elementsNr];
becausematrix is already a member variable. You are creating a new temporary variable double pointer named matrix and allocating memory to it rather than your member variable matrix
A couple of people have already given you advice about how to fix some of the problems with this code. I'll give slightly different advice that may initially seem a bit brutal by comparison, but I'll try to demonstrate how it's honestly useful rather than nasty.
I would throw out your existing code with the possible exception of what you have in main, and start over, using an std::map. What you're doing right now is basically trying to re-create the capabilities that std::map already provides (and even when your code is fixed, it's not doing the job as well as std::map does right out of the box).
Using map, your whole program comes out to something like this:
std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) {
return os << d.first << " : " << d.second;
}
int main() {
std::map<int, int> h;
for (int i=0; i<17; i++)
++h[arr[i]];
std::copy(h.begin(), h.end(),
std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
return 0;
}
If you want to maintain virtually the same interface as your histogram class provided, it's pretty easy to do that -- the for loop goes into the constructor, the copy into print (and SortMatrix disappears, because a map is always sorted).
By doing this, you change from an O(N2) algorithm to an O(N log N) algorithm. The bugs others have pointed out disappear completely, because the code that contained them is no longer needed. The only real disadvantage I can see is that the result will probably use a bit more memory -- it uses a balanced tree with individually allocated nodes, which is likely to introduce a fair amount of overhead for nodes that only contain 2 ints (and a bit for balancing). I can't quite imagine worrying about this though -- long before you have enough nodes for the memory usage to become significant, you have way too many to present to even consider presenting to the user.
#mathematician1975 already provided an answer for the main problem. There's another bug in SortMatrix(): you only swap the elements of the first column, therefore after sorting, the counts (in the second column) will not be correct anymore. You'll have to insert
temp=matrix[i][1];
matrix[i][1]=matrix[i+1][1];
matrix[i+1][1]=temp;
to get it working.