algorithm implementation error (DFS) - c++

I was trying to implementing dfs to print paths from starting node . I followed algorithm from Coremen 's book . Here is my code :
DFS
#include<iostream>
#include<stack>
using namespace std;
int vertex,edge,source,time,adjacency_matrix[100][100],parent[100],Distance[100],Finishing_time[100];
string color[100];
stack<int> result;
void inputGraph();
void initialize();
void doDFS();
void doDFSvisit(int);
void printPath();
//void printAll();
//void printAdjacencyMatrix();
//void printColor();
//void printDistance();
//void printParent();
int main(void)
{
inputGraph();
//initialize();
doDFS();
printPath();
//printAll();
return 0;
}
void inputGraph()
{
cout<<"Total vertex : ";
cin>>vertex;
cout<<"Total edge : ";
cin>>edge;
int i,j;
for(i=1; i<=edge; i++)
{
int start,finish;
cout<<"Enter start and end node for edge "<<i<<" : ";
cin>>start;
cin>>finish;
adjacency_matrix[start][finish]=1;
}
cout<<"The adjacency matrix is : "<<endl;
for(i=1; i<=vertex; i++)
{
for(j=1; j<=vertex; j++)
{
cout<<adjacency_matrix[i][j]<<" ";
}
cout<<endl;
}
}
void initialize()
{
cout<<"Enter source node : ";
cin>>source;
}
void doDFS()
{
int i,j;
for(i=1;i<=vertex;i++)
{
color[i]="white";
parent[i]=0;
}
time=0;
for(i=1;i<=vertex;i++)
{
if(color[i]=="white")
{
doDFSvisit(i);
}
}
}
void doDFSvisit(int node)
{
int i;
time=time+1;
Distance[node]=time;
color[node]="grey";
for(i=1;i<=vertex;i++)
{
if(adjacency_matrix[node][i]==1)
{
if(color[i]=="white")
{
parent[i]=node;
doDFSvisit(i);
}
}
}
color[node]="black";
//extra line for result
result.push(node);
//
time=time+1;
Finishing_time[node]=time;
}
void printPath()
{
cout<<"Path :"<<endl;
int i;
for(i=0;i<=result.size();i++)
{
cout<<result.top()<<" -> ";
result.pop();
}
cout<<" End"<<endl;
}
My problem :
for input :
6
6
1 2
1 4
2 3
3 4
5 3
5 6
my output should be :
5 6 1 2 3 4 end
but my output is :
5 6 1 2 end
it seems printing values from stacks creates problem . please correct me where i did mistake , Thanks in advance .
[ P.S. : Pic of the directed graph that I used for input , http://imgur.com/fYsICiQ ]

There is mistake in the print_path function.
Your for-loop termination condition checks result(stack)'s size which decrements each loop-iteration by pop calling.
Your print_path function should look like something like this:
void printPath(){
cout<<"Path :"<<endl;
int i;
while(!result.empty()){
cout << result.top() << " -> ";
result.pop();
}
cout<<" End"<<endl;
}
Additionally consider this DFS implementation:
list<size_t> l[N];
bool used[N];
void DFS(size_t s){
if (used[s])
return;
used[s] = true;
for(auto i = l[s].begin(); i != l[s].end(); i++)
if(!used[*i]){
DFS(*i);
}
}
used is global bool array indicating i'th vertex is visited or not. We have no need to color vertexes. We have to know is it already visited or not.
l is adjacency list (see http://www.geeksforgeeks.org/graph-and-its-representations/ )
We run DFS on some vertex.
If it's visited we do nothing.
Else we mark this vertex as visited. And then go deeper running DFS on each vertex adjacent current vertex.
For more information about DFS see https://en.wikipedia.org/wiki/Depth-first_search

Here's how I would implement DFS in C++. First some observations:
I'll use adjacency lists (std::vectors) rather than an adjacency matrix.
Nodes aren't owned by their neighbors. They're assumed to be owned by a parent Graph object.
So, without further ado:
struct Node {
std::vector<Node *> neighbors;
// Other fields may go here.
}
void process(Node * node)
{
// Actual logic for processing a single node.
}
// Of course, in idiomatic C++, this would be a template
// parameterized by a function object, rather than contain
// a hard-coded call to a fixed `process` function.
void depth_first(Node * start)
{
std::stack <Node *> pending = { start };
std::unordered_set<Node *> visited;
while (!pending.empty()) {
Node * current = pending.pop();
process(current);
for (Node * neighbor : current->neighbors)
if (visited.find(neighbor) == visited.end()) {
pending.push (neighbor);
visited.insert(neighbor);
}
}
}
A nice thing about this implementation is that, in order to get BFS, you only need to replace std::stack with std::queue, and leave the rest of the code exactly as is.

Related

I'am trying to implement BFS and count all the visited node through the edges. But my code giving me 0 count except the 1st one

In this code I just want to visit the node and count the edges. For the 1st time it seems good but when I pass new nodes and edges it is giving 0 count. I find out that it's condition is not true for the next nodes and edges. It's my first implementation of BFS.
#include<bits/stdc++.h>
using namespace std;
vector<int>v[1000];
int level[1000];
bool vis[1000];
void bfs(int s,int E)
{
int count=0;
queue<int>q;
q.push(s);
level[s]=0;
vis[s]=true;
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=0;i<v[p].size();i++)
{
if(vis[v[p][i]] == false)
{
level[v[p][i]] = level[p]+1;
q.push(v[p][i]);
vis[v[p][i]] = true;
count++;
}
}
}
cout<<count<<endl;
}
int main()
{
int N,E,x,y,size;
while(scanf("%d %d",&N,&E)==2)
{
for(int i=1;i<=E;i++)
{
scanf("%d %d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int s=0;
bfs(s);
}
return 0;
}
You are not resetting whatever variables you have used like your adjacency list v,level and vis.
You have to reset them to some default value before working on a different graph, as values of previous graphs are unwanted.
You can simply run a loop, before each input:
for(int i=0;i<N;i++)
{
v[i].clear();
vis[i]=0;
level[i]=-1;
}

Implementation of QUEUE using Array

Implementation of QUEUE using Array in C++
There seems to be some problem with the Dequeue function.
Instead of deleting from front, it is deleting from rear..
I am not able to figure out what is wrong.
Please help!
#include <iostream>
using namespace std;
#define MAX_SIZE 101
int A[MAX_SIZE];
int front=-1,rear=-1;
void Enq(int x)
{ if (rear==(MAX_SIZE-1))
{return;}
if (front==-1 && rear==-1)
{front=rear=0;}
else { rear=rear+1;}
A[rear]=x;
}
void Deq()
{ if (front == -1 && rear == -1)
{return;}
else if(front == rear)
{
front = rear = -1;
}
else
front++;
}
void Print()
{ cout<<"Queue is: ";
int count=(rear-front);
for(int i=0; i<=count; i++)
{ cout<<A[i]<<" ";
}
cout<<"\n";
}
int main()
{
Enq(2); Print();
Enq(3); Print();
Enq(5); Print();
Deq(); Print();
Deq(); Print();
Enq(24); Print();
return 0;
}
OUTPUT:
Success time: 0 memory: 3460 signal:0
Queue is: 2
Queue is: 2 3
Queue is: 2 3 5
Queue is: 2 3
Queue is: 2
Queue is: 2 3
You are showing count elements, which is calculated as:
int count=(rear-front);
When you make
front++
You will just show one less element. But you always start at the position 0.
for(int i=0; i<=count; i++)
{ cout<<A[i]<<" ";
}
Maybe you should start from "front" and go up to "front+count"?
Keep in mind, trough, this implementation never really deletes anything, and you can just call Enq() MAX_SIZE times, no matter how many times you call Deq().
EDIT: If you want to be able to reuse spaces, you may add the element at the "front-1" position, and then do front--, only if front is >0.
Use your front and rear variables:
for(int i=front; i<=rear; i++) { cout<<A[i]<<" ";}
I would implement it using pointers anyways.

Different output when set different breakpoints

I just wrote a code to build a Huffman Tree using MinHeap. When testing I want to output its traversal result.
The algorithm is simple, but my code can't get the right answer. It's strange that the output was different when I set different breakpoints. For instance, it depends on if I set a break point in the loop, such as line 165 input_list.insert(*parent);.
The test input was
4 //number of nodes.
1 1 3 5 //weight of each node.
and the output when debugging it with a breakpoint in the loop is
5
10
1
2
1
5
3
that is correct. But when I just run it without debug, it even didn't have any output. Does anyone know how to explain it?
#include <iostream>
#include <vector>
using namespace std;
#define max_size 100
int sum=0;
class huffman_node
{
public:
int weight;
huffman_node* left_child;
huffman_node* right_child;
huffman_node(){}
huffman_node(int w, huffman_node* l, huffman_node* r):
weight(w),left_child(l),right_child(r) {}
};
vector <huffman_node> node_list;
class minheap
{
public:
minheap()
{
heap=new huffman_node [max_size];
current_size=0;
}
~minheap()
{
delete []heap;
}
void siftdown(int start, int m)
{
int i=start;
int j=2*i+1;
huffman_node temp=heap[i];
while(j<=m)
{
if(j<m && heap[j+1].weight<heap[j].weight)
{
++j;
}
if(temp.weight<=heap[j].weight)
{
break;
}
else
{
heap[i]=heap[j];
i=j;
j=2*i+1;
}
}
heap[i]=temp;
}
void siftup(int start)
{
int j=start;
int i=(j-1)/2;
huffman_node temp=heap[j];
while(j>0)
{
if(heap[i].weight<=temp.weight)
{
break;
}
else
{
heap[j]=heap[i];
j=i;
i=(j-1)/2;
}
heap[j]=temp;
}
}
bool insert(const huffman_node& input)
{
if(current_size==max_size)
{
cout<<"minheap full"<<endl;
return false;
}
heap[current_size]=input;
siftup(current_size);
++current_size;
return true;
}
bool remove_min(huffman_node& output)
{
if(!current_size)
{
cout<<"minheap empty"<<endl;
return false;
}
output=heap[0];
heap[0]=heap[current_size-1];
--current_size;
siftdown(0,current_size-1);
return true;
}
private:
huffman_node* heap;
int current_size;
};
void route_length(huffman_node* &root,int depth)
{
if(root!=NULL)
{
// if(root->left_child==NULL&&root->right_child==NULL)
// {
// sum+=depth*root->weight;
// }
route_length(root->left_child,depth+1);
cout<<root->weight<<endl;
route_length(root->right_child,depth+1);
}
else
{
return;
}
}
int main()
{
minheap input_list;
int n;
cin>>n;
for(int i=0;i<n;++i)
{
int key;
cin>>key;
huffman_node input(key,NULL,NULL);
input_list.insert(input);
cin.get();
}
huffman_node* root;
for(int i=0;i<n-1;++i)
{
huffman_node* parent;
huffman_node out1;
huffman_node out2;
input_list.remove_min(out1);
input_list.remove_min(out2);
node_list.push_back(out1);
node_list.push_back(out2);
parent=new huffman_node(out1.weight+out2.weight,&node_list[node_list.size()-2],&node_list[node_list.size()-1]);
input_list.insert(*parent);
root=parent;
}
route_length(root,0);
// cout<<sum<<endl;
return 0;
}
The problem is that you are using pointers to elements of a vector<huffman_node> and storing these in your data structure (i.e. left and right members of the huffman_node object).
The thing that is randomly killing your program is that std::vector moves values around in memory when you append to it. The contents of the elements of the vectors are preserved, but the location is not. Once it moves the elements, the memory where the vector used to be can be overwritten by whatever (i.e. gdb needs heap memory too) and now the pointers are pointing to garbage.
As a quick sanity check, you can make your code not crash by reserving space in your node_list by calling
node_list.reserve(max_size*2);
in the beginning of main. This is not the right way of developing this piece of code further, but should illustrate the problem.
It would be better if your node_list was a vector<huffman_node*> instead. Or if you changed the left/right members to be vector indices instead of pointers.

getting extra edge when removing the edges connected to the source vertex in a graph

last week i posted a code to calculate the shortest path in a graph using Dijkastra algorithm but it was very long and nobody was interesting in reading it completely so i deleted it, and now i am trying to simplify the code by going part by part, the code isn't complete yet, and i will cut part of the code here to focus on the first problem that i am facing so far.
briefly i have a class Graph it is going to be constructed by two other classes a vector of elements are instances of a class Edge , and another vector of elements of class Vertex , every vertex has an id , and every edge has two vertices and weight .
class Graph has a method its name is shortest takes two vertices as arguments the first one for the source of the graph and the second is for the destination.
So far i am trying to eliminate the edges that are connected to the source vertex , but i am getting an extra edge still in the vector edges it is connected to the source while all the other edges related to the source are removed.
to demonstrate the result , i initialized a graph has five vertices vers[0], vers[1], vers[2], vers[3], vers[4], and there are 10 edges connecting those vertices starting from eds[0], eds[1], ....eds[9].
the source vertex is vers[2] is connected by 4 edges , so when applying the method shortest as it is shown in the code below i should get rid of all those 4 edges and end with 6 edges , but the result was that i got rid of 3 edges and i have 7 edges remained, the result is as follows:
Hello, This is a graph
0____1 5
0____3 4
0____4 6
1____3 5
1____4 7
2____4 8
3____4 3
size of edges 7
size of vertices 5
as you can notice , there still an edge connected to the source which is 2 , the problem is in this edge (by the way 8 is the weight of the edge)
2____4 8
there is something wrong in the method shortest and specifically in the for loop , i hope you can help in finding my mistake.
Thanks in advance.
Here is the code
#include<iostream>
#include<vector>
#include <stdlib.h> // for rand()
using namespace std;
const unsigned int N = 5;
class Vertex
{
private:
unsigned int id; // the name of the vertex
public:
unsigned int get_id(){return id;};
void set_id(unsigned int value) {id = value;};
Vertex(unsigned int init_val = 0) :id (init_val){} // constructor
~Vertex() {}; // destructor
};
class Edge
{
private:
Vertex first_vertex; // a vertex on one side of the edge
Vertex second_vertex; // a vertex on the other side of the edge
unsigned int weight; // the value of the edge ( or its weight )
public:
unsigned int get_weight() {return weight;};
void set_weight(unsigned int value) {weight = value;};
Vertex get_ver_1(){return first_vertex;};
Vertex get_ver_2(){return second_vertex;};
void set_first_vertex(Vertex v1) {first_vertex = v1;};
void set_second_vertex(Vertex v2) {second_vertex = v2;};
Edge(const Vertex& vertex_1 = 0, const Vertex& vertex_2 = 0, unsigned int init_weight = 0)
: first_vertex(vertex_1), second_vertex(vertex_2), weight(init_weight)
{
}
~Edge() {} ; // destructor
};
class Graph
{
private:
std::vector<Vertex> vertices;
std::vector<Edge> edges;
public:
Graph(vector<Vertex> ver_vector, vector<Edge> edg_vector)
: vertices(ver_vector), edges(edg_vector){}
~Graph() {}
vector<Vertex> get_vertices(){return vertices;}
vector<Edge> get_edges(){return edges;}
void set_vertices(vector<Vertex> vector_value) {vertices = vector_value;}
void set_edges(vector<Edge> vector_ed_value) {edges = vector_ed_value;}
unsigned int shortest(Vertex src, Vertex dis);
};
unsigned int Graph::shortest(Vertex src, Vertex dis) {
vector<Vertex> ver_out;
vector<Edge> track;
for(unsigned int i = 0; i < edges.size(); ++i)
{
if((edges[i].get_ver_1().get_id() == src.get_id()) || (edges[i].get_ver_2().get_id() == src.get_id()))
{
track.push_back (edges[i]);
if(edges[i].get_ver_1().get_id() == src.get_id())
{ver_out.push_back (edges[i].get_ver_1());}
else
{ver_out.push_back (edges[i].get_ver_2());}
edges.erase(edges.begin() + i ); //****
}
};
}
int main()
{
cout<< "Hello, This is a graph"<< endl;
vector<Vertex> vers(5);
vers[0].set_id(0);
vers[1].set_id(1);
vers[2].set_id(2);
vers[3].set_id(3);
vers[4].set_id(4);
vector<Edge> eds(10);
eds[0].set_first_vertex(vers[0]);
eds[0].set_second_vertex(vers[1]);
eds[0].set_weight(5);
eds[1].set_first_vertex(vers[0]);
eds[1].set_second_vertex(vers[2]);
eds[1].set_weight(9);
eds[2].set_first_vertex(vers[0]);
eds[2].set_second_vertex(vers[3]);
eds[2].set_weight(4);
eds[3].set_first_vertex(vers[0]);
eds[3].set_second_vertex(vers[4]);
eds[3].set_weight(6);
eds[4].set_first_vertex(vers[1]);
eds[4].set_second_vertex(vers[2]);
eds[4].set_weight(2);
eds[5].set_first_vertex(vers[1]);
eds[5].set_second_vertex(vers[3]);
eds[5].set_weight(5);
eds[6].set_first_vertex(vers[1]);
eds[6].set_second_vertex(vers[4]);
eds[6].set_weight(7);
eds[7].set_first_vertex(vers[2]);
eds[7].set_second_vertex(vers[3]);
eds[7].set_weight(1);
eds[8].set_first_vertex(vers[2]);
eds[8].set_second_vertex(vers[4]);
eds[8].set_weight(8);
eds[9].set_first_vertex(vers[3]);
eds[9].set_second_vertex(vers[4]);
eds[9].set_weight(3);
unsigned int path;
Graph graf(vers, eds);
path = graf.shortest(vers[2], vers[4]);
cout<<graf.get_edges()[0].get_ver_1().get_id() <<"____"<<graf.get_edges()[0].get_ver_2().get_id() <<" "<<graf.get_edges()[0].get_weight()<< endl; //test
cout<<graf.get_edges()[1].get_ver_1().get_id() <<"____"<<graf.get_edges()[1].get_ver_2().get_id() <<" "<<graf.get_edges()[1].get_weight()<< endl; //test
cout<<graf.get_edges()[2].get_ver_1().get_id() <<"____"<<graf.get_edges()[2].get_ver_2().get_id() <<" "<<graf.get_edges()[2].get_weight()<< endl; //test
cout<<graf.get_edges()[3].get_ver_1().get_id() <<"____"<<graf.get_edges()[3].get_ver_2().get_id() <<" "<<graf.get_edges()[3].get_weight()<< endl; //test
cout<<graf.get_edges()[4].get_ver_1().get_id() <<"____"<<graf.get_edges()[4].get_ver_2().get_id() <<" "<<graf.get_edges()[4].get_weight()<< endl; //test
cout<<graf.get_edges()[5].get_ver_1().get_id() <<"____"<<graf.get_edges()[5].get_ver_2().get_id() <<" "<<graf.get_edges()[5].get_weight()<< endl; //test
cout<<graf.get_edges()[6].get_ver_1().get_id() <<"____"<<graf.get_edges()[6].get_ver_2().get_id() <<" "<<graf.get_edges()[6].get_weight()<< endl; //test
//cout<<graf.get_edges()[7].get_ver_1().get_id() <<"____"<<graf.get_edges()[7].get_ver_2().get_id() <<" "<<graf.get_edges()[7].get_weight()<< endl; //test
//cout<<graf.get_edges()[8].get_ver_1().get_id() <<"____"<<graf.get_edges()[8].get_ver_2().get_id() <<" "<<graf.get_edges()[8].get_weight()<< endl; //test
//cout<<graf.get_edges()[9].get_ver_1().get_id() <<"____"<<graf.get_edges()[9].get_ver_2().get_id() <<" "<<graf.get_edges()[9].get_weight()<< endl; //test
cout<<"size of edges"<<graf.get_edges().size()<< endl;
cout<<"size of vertices"<<graf.get_vertices().size()<< endl;
return 0;
}
This is because you are effectively skipping some vector elements in your Graph::shortest for loop because you are incrementing i even when you erase current element. Change it to something like this to fix the problem:
for (unsigned int i = 0; i < edges.size();) { // no ++i here
if ((edges[i].get_ver_1().get_id() == src.get_id()) || (edges[i].get_ver_2().get_id() == src.get_id())) {
track.push_back(edges[i]);
if (edges[i].get_ver_1().get_id() == src.get_id()) {
ver_out.push_back(edges[i].get_ver_1());
} else {
ver_out.push_back(edges[i].get_ver_2());
}
edges.erase(edges.begin() + i);
} else {
++i; // increment only if not erasing
}
}
Alternatively as per comment, using iterators:
for (auto i = edges.begin(); i != edges.end();) {
if ((i->get_ver_1().get_id() == src.get_id()) || (i->get_ver_2().get_id() == src.get_id())) {
track.push_back(*i);
if (i->get_ver_1().get_id() == src.get_id()) {
ver_out.push_back(i->get_ver_1());
} else {
ver_out.push_back(i->get_ver_2());
}
i = edges.erase(i);
} else {
i++;
}
}
You are also missing a return statement in that function.

Calculate sum of links of similar points

Suppose I have a set of 10000 points and they randomly connected to each other. For example let's take 10 points. And they connected like the picture-
Definition of Similar Points:
The points that has same number of links are called similar points. From the picture we can see-
Node 1 is connected with node [2] and [10]
Node 2 is connected with node [1},[3],[4],[5],[6],[7],[8]
Node 3 is connected with only node [2]
Node 4 is connected with only node [2]
Node 5 is connected with only node [2]
Node 6 is connected with only node [2]
Node 7 is connected with only node [2]
Node 8 is connected with node [2] and [9]
Node 9 is connected with only node [8]
Node 10 is connected with only node [1)
So according to the definition, Node- 3,4,5,6,7,9,10 are similar because each of them has only one link.
Again Node- 1 & 8 are similar because each of them has two links.
My Problem
Now I want to calculate the sum of the links of similar points. For example-
Node 1 has 8 are similar.
For node 1:
It is connected to Node 2 (which has 7 links)
And also connected to Node 10 (which has 1 link )
For node 8:
It is connected to Node 2 (which has 7 links)
And also connected to Node 9 (which has 1 link )
So for the group with two links, the number of total links should be= 7+1+7+1 =16.
Like this way I would like to calculate the total links for other similar points.
My Code
Here is my code. It gives the result for the total links for each of the points.
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
struct Node {
vector< int > links_to;
Node(void){};
Node(int first_link){
links_to.push_back(first_link);
};
};
class Links : public vector<Node> {
public:
void CreateLinks(int n,int m);
void OutputNodes();
};
int RandGenerate(int max) {
return int(drand48()*double(max));
}
void CreateRandom(int *nums,int m,int max) {
bool clear;
for(int i=0;i<m;i++) {
clear=true;
while(clear) {
clear=false;
nums[i]=RandGenerate(max);
for(int j=0;j<i;j++) {
if(nums[i]==nums[j]){
clear=true;break;
}
}
}
}
}
void Links::CreateLinks(int n,int m) {
clear();
for(int i=0;i<m;i++) {
push_back(Node());
}
int edge_targets[m],nums[m];
for(int i=0;i<m;i++) {
edge_targets[i]=i;
}
vector<int> repeated_nodes;
int source=m;
while(source<n) {
push_back(Node());
Node &node=*(end()-1);
for(int i=0;i<m;i++) {
node.links_to.push_back(edge_targets[i]);
at(edge_targets[i]).links_to.push_back(source);
repeated_nodes.push_back(edge_targets[i]);
repeated_nodes.push_back(source);
}
CreateRandom(nums,m,repeated_nodes.size());
for(int i=0;i<m;i++) {
edge_targets[i]=repeated_nodes[nums[i]];
}
source++;
}
}
void Links::OutputNodes() {
for(int i=0;i<size();i++){
cout<<endl;
for(int j=0;j<at(i).links_to.size();j++){
cout<<"Node "<<(i+1)<<" is connected with ["<<(at(i).links_to[j]+1)<<"]"<<endl;
}
cout<<"For Node: "<<(i+1)<<"\t"<<"Total links: "<<at(i).links_to.size()<<endl;
}
}
int main() {
srand48(46574621);
Links network;
network.CreateLinks(10,1); //(nodes,minimum value of link)
network.OutputNodes();
return 0;
}
Which generate the result like this-
Node 1 is connected with [2]
Node 1 is connected with [10]
For Node: 1 Total links: 2
Node 2 is connected with [1]
Node 2 is connected with [3]
Node 2 is connected with [4]
Node 2 is connected with [5]
Node 2 is connected with [6]
Node 2 is connected with [7]
Node 2 is connected with [8]
For Node: 2 Total links: 7
Node 3 is connected with [2]
For Node: 3 Total links: 1
Node 4 is connected with [2]
For Node: 4 Total links: 1 ... etc
I would like to add a function so that it groups the similar points and gives the output of the total links for each groups. How can I do that?
Updated in response to the answer of Pixelchemist
Let's say I store the data in a file name "MyLinks.txt" like this-
1 2
1 10
2 1
2 3
2 4
2 5
2 6
2 7
2 8...etc
And get the input from the file. Here is the code-
int main (void)
{
ifstream inputFile("MyLinks.txt");
double Temp[2];
Links links_object;
while (true) {
for (unsigned i = 0; i < 2; i++){
inputFile>>Temp[i];
}
for (size_t i(0u); i<10; ++i)
{
links_object.add(Node());
}
links_object.link_nodes(Temp[0], Temp[1]);
/*
links_object.link_nodes(0u, 9u);
links_object.link_nodes(1u, 2u);
links_object.link_nodes(1u, 3u);
links_object.link_nodes(1u, 4u);
links_object.link_nodes(1u, 5u);
links_object.link_nodes(1u, 6u);
links_object.link_nodes(1u, 7u);
links_object.link_nodes(7u, 8u);
*/
}
std::vector<size_t> linksum;
for (auto const & node : links_object.nodes())
{
size_t const linksum_index(node.links().size()-1u);
if (linksum.size() < node.links().size())
{
size_t const nls(node.links().size());
for (size_t i(linksum.size()); i<nls; ++i)
{
linksum.push_back(0u);
}
}
for (auto linked : node.links())
{
linksum[linksum_index] += linked->links().size();
}
}
for (size_t i(0u); i<linksum.size(); ++i)
{
std::cout << "Sum of secondary links with " << i+1;
std::cout << "-link nodes is: " << linksum[i] << std::endl;
}
}
Updated my code,store the results of 'connection' in a text file and trying to get the values from that. But now it gives me the segmentation fault. How can I fix it?
I would use a map. The number of links would be the key and its value would be a vector containing the IDs of nodes with that number of links.
typedef std::map<size_t,std::vector<size_t> SimilarNodeMap;
SimilarNodeMap myMap;
... // fill up the map
for (SimilarNodeMap::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
std::cout << "Nodes with " it->first << " links: ";
for ( size_t i = 0; i < second->size(); ++i )
{
std::cout << second->at(i) << std::endl;
}
}
You can go through the nodes that are part of the "pair" and put them into a list. If there is an element you are trying to add that's already in the list don't add it.(e.x if statement check) Then after going through all the elements check the list size and that should be your links.
Correct me if this isn't what you are asking.
I'm sure there is a better way to do this. The complexity of this is O(n^2) time i believe.
I'd use a std::vector<size_t> where the index of the vector is the number of links of the respective node type.
You iterate over all of your nodes and increment the std::vector<size_t>-entry corresponding to the number of links of this node with the number of links of all nodes that are linked to the current one.
This code:
#include <vector>
#include <stdexcept>
class Node
{
std::vector< Node const * > m_links;
public:
Node(void) { }
void link_to (Node const &n)
{
m_links.push_back(&n);
}
std::vector< Node const * > const & links (void) const
{
return m_links;
}
};
class Links
{
std::vector<Node> m_nodes;
public:
void add (Node const &node) { m_nodes.push_back(node); }
void link_nodes (size_t node_a, size_t node_b)
{
size_t ns(m_nodes.size());
if (node_a >= ns || node_b >= ns)
{
throw std::logic_error("Requested invalid link.");
}
m_nodes[node_a].link_to(m_nodes[node_b]);
m_nodes[node_b].link_to(m_nodes[node_a]);
}
std::vector<Node> const & nodes (void) const
{
return m_nodes;
}
};
int main (void)
{
Links links_object;
for (size_t i(0u); i<10; ++i)
{
links_object.add(Node());
}
links_object.link_nodes(0u, 1u);
links_object.link_nodes(0u, 9u);
links_object.link_nodes(1u, 2u);
links_object.link_nodes(1u, 3u);
links_object.link_nodes(1u, 4u);
links_object.link_nodes(1u, 5u);
links_object.link_nodes(1u, 6u);
links_object.link_nodes(1u, 7u);
links_object.link_nodes(7u, 8u);
std::vector<size_t> linksum;
for (auto const & node : links_object.nodes())
{
size_t const linksum_index(node.links().size()-1u);
if (linksum.size() < node.links().size())
{
size_t const nls(node.links().size());
for (size_t i(linksum.size()); i<nls; ++i)
{
linksum.push_back(0u);
}
}
for (auto linked : node.links())
{
linksum[linksum_index] += linked->links().size();
}
}
for (size_t i(0u); i<linksum.size(); ++i)
{
std::cout << "Sum of secondary links with " << i+1;
std::cout << "-link nodes is: " << linksum[i] << std::endl;
}
}
Prints:
Sum of secondary links with 1-link nodes is: 39
Sum of secondary links with 2-link nodes is: 16
Sum of secondary links with 3-link nodes is: 0
Sum of secondary links with 4-link nodes is: 0
Sum of secondary links with 5-link nodes is: 0
Sum of secondary links with 6-link nodes is: 0
Sum of secondary links with 7-link nodes is: 9
You should get the idea.
You might iterate over all nodes and count.
Pseudo code:
std::map<std::size_t, std::size_t> counter;
for each node
++counter[node.links().size]