Adjacency list implementation in C++ - c++

I am looking for a concise and precise adjacency list representation of a graph in C++. My nodes are just node ids. Here is how I did it. Just want to know what experts think about it. Is there a better way?
This is the class implementation (nothing fancy, right now don't care about public/private methods)
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
class adjList {
public:
int head;
vector<int> listOfNodes;
void print();
};
void adjList :: print() {
for (int i=0; i<listOfNodes.size(); ++i) {
cout << head << "-->" << listOfNodes.at(i) << endl;
}
}
class graph {
public:
vector<adjList> list;
void print();
};
void graph :: print() {
for (int i=0; i<list.size(); ++i) {
list.at(i).print();
cout << endl;
}
}
My main function parses an input file line by line. Where each line is interpreted as following:
<source_node> <node1_connected_to_source_node> <node2_connected_to_source_node <node3_connected_to_source_node> <...>
Here is the main:
int main()
{
fstream file("graph.txt", ios::in);
string line;
graph g;
while (getline(file, line)) {
int source;
stringstream str(line);
str >> source;
int node2;
adjList l;
l.head = source;
while (str >> node2) {
l.listOfNodes.push_back(node2);
}
g.list.push_back(l);
}
file.close();
g.print();
getchar();
return 0;
}
I know I should add addEdge() function inside adjList class instead of directly modifying its variable from main() however, right now I just wonder about the best structure.
EDIT:
There is one shortcoming in my approach. For a complicated graph with large number of nodes, node will indeed be a struct/class and in that case I will be duplicating values by storing the whole object. In that case I think I should use pointers. For example for an undirected graph, I will be storing copies of node objects in the adjList (connection between node 1 and 2 means 1's adjacency list will have 2 and vice versa). I can avoid that by storing pointers of node objects in the adjList instead of the whole object. Check the dfs implementation which get benefited by this approach. There I need to insure that each node gets visited only once. Having multiple copies of the same node will make my life harder. no?
In this case my class definitions will change like this:
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <map>
using namespace std;
class node {
public:
node() {}
node(int id, bool _dirty): node_id(id), dirty(_dirty) {}
int node_id;
bool dirty;
};
class adjList {
public:
node *head;
vector<node*> listOfNodes;
void print();
~adjList() { delete head;}
};
void adjList :: print() {
for (int i=0; i<listOfNodes.size(); ++i) {
cout << head->node_id << "-->" << listOfNodes.at(i)->node_id << endl;
}
}
class graph {
public:
vector<adjList> list;
void print();
void dfs(node *startNode);
};
void graph::dfs(node *startNode) {
startNode->dirty = true;
for(int i=0; i<list.size(); ++i) {
node *stNode = list.at(i).head;
if (stNode->node_id != startNode->node_id) { continue;}
for (int j=0; j<list.at(i).listOfNodes.size(); ++j) {
if (!list.at(i).listOfNodes.at(j)->dirty) {
dfs(list.at(i).listOfNodes.at(j));
}
}
}
cout << "Node: "<<startNode->node_id << endl;
}
void graph :: print() {
for (int i=0; i<list.size(); ++i) {
list.at(i).print();
cout << endl;
}
}
And this is how I implemented main() function. I am using a map<> to avoid duplication of objects. Creating a new object only when its not defined earlier. Checking existence of an object by its id.
int main()
{
fstream file("graph.txt", ios::in);
string line;
graph g;
node *startNode;
map<int, node*> nodeMap;
while (getline(file, line)) {
int source;
stringstream str(line);
str >> source;
int node2;
node *sourceNode;
// Create new node only if a node does not already exist
if (nodeMap.find(source) == nodeMap.end()) {
sourceNode = new node(source, false);
nodeMap[source] = sourceNode;
} else {
sourceNode = nodeMap[source];
}
adjList l;
l.head = sourceNode;
nodeMap[source] = sourceNode;
while (str >> node2) {
// Create new node only if a node does not already exist
node *secNode;
if (nodeMap.find(node2) == nodeMap.end()) {
secNode = new node(node2, false);
nodeMap[node2] = secNode;
} else {
secNode = nodeMap[node2];
}
l.listOfNodes.push_back(secNode);
}
g.list.push_back(l);
startNode = sourceNode;
}
file.close();
g.print();
g.dfs(startNode);
getchar();
return 0;
}
SECOND EDIT
After Ulrich Eckhardt suggestion to put adjacency list in node class, here is what I think is a better data structure to store a graph and perform dfs(), dijkstra() kind of operations. Please note that adjacency list is merged in node class.
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <map>
using namespace std;
class node {
public:
node() {
}
node(int id, bool _dirty): node_id(id), dirty(_dirty) {
//cout << "In overloaded const\n";
}
int node_id;
bool dirty;
vector<node*> listOfNodes;
};
class graph {
public:
vector<node*> myGraph;
void dfs(node* startNode);
};
void graph::dfs(node* startNode) {
startNode->dirty = true;
for (int j=0; j<startNode->listOfNodes.size(); ++j) {
if (!startNode->listOfNodes.at(j)->dirty) {
dfs(startNode->listOfNodes.at(j));
}
}
cout << "Node: "<<startNode->node_id << endl;
}
Can we do better than this?

There are a few things that could be improved, but in general your approach is reasonable. Notes:
You are using int as index into a container, which will give you warning from some compilers, because the size of a container could exceed the size representable as int. Instead, use size_t.
Rewrite your for (int i=0; i<list.size(); ++i) to for(size_t i=0, size=list.size(); i!=size; ++i). Using != instead of < will work with iterators. Reading and storing the size once makes it easier to debug and possibly even more efficient.
Inside the loop to print, you have list.at(i).print();. The list.at(i) will verify the index is valid and raise an exception when not. In this very simple case, I am sure that the index is valid, so using list[i] instead is faster. Also, it implicitly documents that the index is valid and not that you expect it to be invalid.
The print() functions should be constant.
I don't understand what the int head is. Is this some kind of ID for the node? And isn't the ID simply the index inside graph::list? If it is the index, you could compute that on demand using the address of the element minus the address of the first element, so there's no need to store it redundantly. Also, consider validating that index when reading, so you don't have any edges going to a vertex that doesn't exist.
If you don't care about encapsulation on a node-level (which is reasonable!), you could also make this a struct, which saves some typing.
Storing pointers instead of indices is tricky but could improve speed. The problem is that for reading, you might need a pointer to a vertex that doesn't exist yet. There is a hack that allows doing that without using additional storage, it requires first storing the indices in the pointer values (using reinterpret_cast) and after reading, making a second pass on the data where you adjust these values to the actual addresses. Of course, you can also use the second pass to validate that you don't have any edges going to vertices that don't exist at all (which is a place where the at(i) function becomes useful) so this second pass to verify some guarantees is a good thing anyway.
On explicit request, here's an example for how to store an index in a pointer:
// read file
for(...) {
size_t id = read_id_from_file();
node* node_ptr = reinterpret_cast<node*>(id);
adjacency_list.push_back(node_ptr);
}
/* Note that at this point, you do have node* that don't contain
valid addresses but just the IDs of the nodes they should finally
point to, so you must not use these pointers! */
// make another pass over all nodes after reading the file
for(size_t i=0, size=adjacency_list.size(); i!=size; ++i) {
// read ID from adjacency list
node* node_ptr = adjacency_list[i];
size_t id = reinterpret_cast<size_t>(node_ptr);
// convert ID to actual address
node_ptr = lookup_node_by_id(id);
if(!node_ptr)
throw std::runtime_error("unknown node ID in adjacency list");
// store actual node address in adjacency list
adjacency_list[i] = node_ptr;
}
I'm pretty sure that this works in general, though I'm not 100% sure if this is guaranteed to work, which was why I'm reluctant to post this here. However, I hope this also makes clear why I'm asking what exactly "head" is. If it is really just the index in a container, there is little need for it, neither inside the file nor in memory. If it is some kind of name or identifier for a node that you retrieved from a file, then you absolutely need it, but then you can't use it as index, the values there could as well start their IDs with 1 or 1000, which you should catch and handle without crashing!

Related

Hash table implementation in C++

I am trying the following code for Hash table implementation in C++. The program compiles and accepts input and then a popup appears saying " the project has stopped working and windows is checking for a solution to the problem. I feel the program is going in the infinite loop somewhere. Can anyone spot the mistake?? Please help!
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
/* Definitions as shown */
typedef struct CellType* Position;
typedef int ElementType;
struct CellType{
ElementType value;
Position next;
};
/* *** Implements a List ADT with necessary functions.
You may make use of these functions (need not use all) to implement your HashTable ADT */
class List{
private:
Position listHead;
int count;
public:
//Initializes the number of nodes in the list
void setCount(int num){
count = num;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
//Inserts an element after Position p
int insertList(ElementType data, Position p){
Position temp;
temp = p->next;
p->next = new CellType;
p->next->next = temp;
p->next->value = data;
return ++count;
}
//Returns pointer to the last node
Position end(){
Position p;
p = listHead;
while (p->next != NULL){
p = p->next;
}
return p;
}
//Returns number of elements in the list
int getCount(){
return count;
}
};
class HashTable{
private:
List bucket[10];
int bucketIndex;
int numElemBucket;
Position posInsert;
string collision;
bool reportCol; //Helps to print a NO for no collisions
public:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
}
collision = "";
reportCol = false;
}
int insert(int data){
bucketIndex=data%10;
int col;
if(posInsert->next==NULL)
bucket[bucketIndex].insertList(data,posInsert);
else { while(posInsert->next != NULL){
posInsert=posInsert->next;
}
bucket[bucketIndex].insertList(data,posInsert);
reportCol=true;}
if (reportCol==true) col=1;
else col=0;
numElemBucket++;
return col ;
/*code to insert data into
hash table and report collision*/
}
void listCollision(int pos){
cout<< "("<< pos<< "," << bucketIndex << "," << numElemBucket << ")"; /*codeto generate a properly formatted
string to report multiple collisions*/
}
void printCollision();
};
int main(){
HashTable ht;
int i, data;
for (i=0;i<10;i++){
cin>>data;
int abc= ht.insert(data);
if(abc==1){
ht.listCollision(i);/* code to call insert function of HashTable ADT and if there is a collision, use listCollision to generate the list of collisions*/
}
//Prints the concatenated collision list
ht.printCollision();
}}
void HashTable::printCollision(){
if (reportCol == false)
cout <<"NO";
else
cout<<collision;
}
The output of the program is the point where there is a collision in the hash table, thecorresponding bucket number and the number of elements in that bucket.
After trying dubbuging, I come to know that, while calling a constructor you are not emptying the bucket[bucketIndex].
So your Hash Table constructor should be as follow:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
bucket[i].makeEmptyList(); //here we clear for first use
}
collision = "";
reportCol = false;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
what you can do is you can get posInsert using
bucket[bucketIndex].end()
so that posInsert-> is defined
and there is no need to
while(posInsert->next != NULL){
posInsert=posInsert->next;
because end() function is doing just that so use end() function

Accessibility for Vectors of Singly Linked Lists (or possibly a Linked List of Linked Lists)

Been wracking my mind all day trying to hammer out the underlying data structures for a challenge assignment in one of my programming classes.
The problem is as follows:
Given an assortment of objects (each of which includes an identifier and a weight) and a supply of containers (which have a fixed weight capacity), pack all the items using as few containers as possible without overloading any of them.
I have the logic aspects hammered out using a hodgepodge of arrays, but the dynamic nature of this assignment has me wanting to optimize things by using vectors and/or linked lists.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <vector>
#include <algorithm>
using namespace std;
struct Item
{
int number;
double weight;
bool operator < (const Item& str) const
{
return (weight < str.weight);
}
};
class Node
{
int number;
double weight;
Node* next;
public:
Node()
{};
void SetID(int iNum)
{
number = iNum;
};
void SetWeight(double iWeight)
{
weight = iWeight;
};
void SetNext(Node* iNext)
{
next = iNext;
}
int GetID()
{
return number;
};
double GetWeight()
{
return weight;
};
Node* Next()
{
return next;
};
};
class List
{
Node* head;
double weight;
public:
List()
{
head = NULL;
weight = 0;
};
int Size()
{
Node* tmp;
int count = 0;
for (tmp = head; tmp != NULL; tmp = tmp->Next())
{
count++;
}
return count;
};
double Weight()
{
return weight;
};
void Print()
{
Node *tmp = head;
if ( tmp == NULL )
{
cout << " E M P T Y" << endl;
return;
}
do
{
cout << setw(8) << tmp->GetID() << " | " << setw(8) << tmp->GetWeight() << endl;
tmp = tmp->Next();
} while ( tmp != NULL );
};
void Append(int iNum, double iWeight)
{
Node* newNode = new Node();
newNode->SetID(iNum);
newNode->SetWeight(iWeight);
newNode->SetNext(NULL);
Node *tmp = head;
if ( tmp != NULL )
{
while ( tmp->Next() != NULL )
{
tmp = tmp->Next();
}
tmp->SetNext(newNode);
}
else
{
head = newNode;
}
weight += iWeight;
};
};
double ItemWeights(vector<Item> iVect)
{
double total = 0;
for(int i = 0; i < iVect.size(); i++)
{
total += iVect[i].weight;
}
return total;
}
int main()
{
const double MAX_WEIGHT = 20;
vector< Item > source;
//
// Segment of code which propagates the vector data
// works fine, but is excluded for the sake of brevity
//
double totalWeight = ItemWeights(source);
// Duplicate vector of items
vector< Item > items(source);
for(int i = 0; i < items.size(); i++)
{
cout << setw(8) << items[i].number << setw(8) << items[i].weight << endl;
}
cout << "\n Total weight = " << totalWeight << endl;
cout << "\n\n Press any key to continue... ";
getch();
// Solution A-Original
// vector< vector< Item > > boxesAO( vector< Item >);
// boxesAO[0].push_back({items[items.size()].number, items[items.size()].weight});
vector< List > boxesAO;
// boxesAO[0].Append(items[items.size()].number, items[items.size()].weight);
return 0;
}
I've left some of the methods I've tried in the code (commented out) - none of which worked. As I mentioned above, I've got it working with arrays of linked lists and with 2D arrays, but the vast range of potential input makes these problematic at best. Either a bunch of empty lists taking up space or, worse, not having enough.
I'm thinking that vector< List > is my best option, but I can't figure out how I'm supposed to access any of the List functionality.
If someone would be so helpful as to offer a suggestion for how to create a "dynamic 2D array" as well as a code example of how to access it, I would be most greatly appreciative. My deepest thanks in advance.
EDIT:
#jaredad7 ~ That's what I've been trying, but it keeps causing the program to crash.
List box;
box.Append(items[items.size()].number, items[items.size()].weight);
This works just fine - no problems whatsoever.
The earlier code propagates a 1D vector of Item structs, which also works properly.
vector< List > boxes;
boxes[0].Append(items[items.size()].number, items[items.size()].weight);
This compiles fine but crashes during execution, no matter what index is used. (I'm also using couts for debugging, and the issue most definitely lies with trying to access the List functions.)
I'm suspecting that .push_back or somesuch may be needed, but I haven't been able to find much information concerning vectors of List objects.
If you can, my first suggestion would be to go with the vector (if that is allowed). As for accessing functions/attributes of a member of a vector, it's done the same way as an array, that is:
vectorname[i].functionname(a,b,c);
The best way to do this without vectors would be to use your nodes as the item container (a struct), and handle node-creation, deletion, etc. in your list class. Then, you would only really need one container for as many objects of one type as you need. You can make the type dynamic (although it appears you only need doubles for this project) by adding a class template (use google if you are unfamiliar with templates in C++). This will allow your user to make a container for each type of data (much like a vector).

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.

Confusion in creating a directed graph in C++

I am trying to create a directed graph by reading a text file where each line has two columns, first column is a tail vertex and second column is the head vertex. Presently just to test if my code works I am trying to populate the graph and print it out.
I am printing my graph after every node insertion. Graph print works as fine until I insert the third node "4" after which first node changes to 0 from 1. I do not have any clue why. I wonder if storing node pointers in edge is a good idea. I am doing it because I already have node information in the "nodes" vector hence do not want to duplicate it.
Input test file:
1 2
4 5
My data structures are:
node: which holds node id and and boolean variable node dirty
edge: which holds pointers to tail node and head node
graph: Holds vectors of all nodes and edges
Output:
Pushing :1
print called
Nodes are:
1
Pushing :2
print called
Nodes are:
1
2
Pushing :4
print called
0(0) --> 2(0) // Problem this should have been 1(0) --> 2(0)
Nodes are:
1
2
4
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
class node {
public:
node() {}
node(int _nodeId, bool dirty);
int nodeId;
bool dirty;
void operator=(node rhs);
bool operator==(node rhs);
};
class edge {
public:
edge(node *_startNode, node *_endNode): startNode(_startNode), endNode(_endNode) {}
node *startNode, *endNode;
};
node :: node(int _nodeId, bool _dirty) {
nodeId = _nodeId;
dirty = _dirty;
}
void node :: operator=(node rhs) {
this->dirty = rhs.dirty;
this->nodeId = rhs.nodeId;
}
bool node :: operator==(node rhs) {
if (this->nodeId == rhs.nodeId) {
return true;
}
return false;
}
class graph {
public:
void print();
void addEdge(node startNode, node endNode);
void addNode(node n);
void dfs(node s);
private:
vector<edge> edges;
vector<node> nodes;
};
void graph :: addNode(node n) {
// only add this node if it does not exist in the graph
if (find(nodes.begin(), nodes.end(), n) == nodes.end()) {
//print();
cout << "Pushing :"<<n.nodeId<<endl;
nodes.push_back(n);
}
print();
cout << endl;
}
void graph :: dfs(node s) {
// Search node s and mark it as dirty
}
void graph :: print() {
cout << "print called\n";
vector<edge>::iterator itr = edges.begin();
while (itr != edges.end()) {
cout << itr->startNode->nodeId << "("<< itr->startNode->dirty<<") --> ";
cout << itr->endNode->nodeId << "("<< itr->endNode->dirty<<")"<<endl;
++itr;
}
cout << "Nodes are:\n";
for (int i=0; i< nodes.size(); ++i) {
cout << nodes.at(i).nodeId << endl;
}
}
void graph :: addEdge(node startNode, node endNode) {
vector<node>::iterator itrStartNode;
itrStartNode = find(nodes.begin(), nodes.end(), startNode);
vector<node>::iterator itrEndNode;
itrEndNode = find(nodes.begin(), nodes.end(), endNode);
edge e(&(*itrStartNode), &(*itrEndNode));
edges.push_back(e);
}
int main(int argc, char *argv[]) {
graph g;
// Read the file here
ifstream file;
file.open("test.txt", ios::in);
string line;
while (getline(file, line)) {
int startNodeId, endNodeId;
istringstream is(line);
is >> startNodeId >> endNodeId;
node startNode(startNodeId, false);
node endNode(endNodeId, false);
g.addNode(startNode);
g.addNode(endNode);
g.addEdge(startNode, endNode);
}
file.close();
g.print();
return 0;
}
You're creating temporary variables, e.g.
node startNode(startNodeId, false);
node endNode(endNodeId, false);
and
edge e(&(*itrStartNode), &(*itrEndNode));
and storing pointers to temporary instances into your containers, e.g.
edge e(&(*itrStartNode), &(*itrEndNode));
edges.push_back(e);
Once you exit the local scope in which those instances were created (the while loop or the addEdge method), the stack memory storing those instances are taken back by the program for use elsewhere. However, your pointers still point to valid memory addresses (taken back by the program or not), and so, may still point to valid-seeming data. That's probably what's going on, i.e. why you're seeing valid-seeming but incorrect vertices.
Use the new operator to create instances that persist beyond the local scopes of loops and functions, and clean them up (via delete) appropriately.

singly linked chain printing c++

I am trying to pick my chain in the format {1,2,3,4,etc}. You can find the header file below which will have the layout of the nodes. I am just confused on how I should go about cycling through my list to print out Item.
Any guidance would be greatly appreciated!
set.h
using namespace std;
#include <iostream>
class Set
{
private:
struct Node
{
int Item; // User data item
Node * Succ; // Link to the node's successor
};
unsigned Num; // Current count of items in the set
Node * Head; // Link to the head of the chain
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
// Initialize the set to empty
//
Set();
// Insert a specified item into the set, if possible
//
bool insert( int );
// Display the set
//
void display( ostream& ) const;
};
Here are two recommendations: 1) Sort the list first, then print all nodes; 2) Create another list (indices) to the data and sort those links (don't need data in those nodes).
Sorting List First
An often used technique is to order the nodes in the order you want them printed. This should involve changing the link fields.
Next, start at the head node and print each node in the list (or the data of each node in the list).
Using an Index list
Create another linked list without the data fields. The links in this list point to the data fields in the original list. Order the new list in the order you want the nodes printed.
This technique preserves the order of creation of the first list and allows different ordering schemes.
Changing Links
Since you're writing your own Linked List, the changing of the links is left as an exercise as I'm not getting paid to write your code. There are many examples on SO as well as the web for sorting and traversing linked lists.
You just want to do something like this:
void Set::display(ostream &out) const {
for(int i=0; i<Num; i++) {
out << Pool[i] << " ";
}
out << endl;
}
An ostream behaves as cout would.
It's hard to get your question. If you want to print the array to screen you should consider writing a display() like:
#include <iostream>
#include <iterator>
void Set::display() const {
ostream_iterator<int> out_it (cout," ");
copy(Pool,Pool+Num,out_it);
cout << endl;
}
or if you want to write to a ostream& (as it is pointed out in the answer by #alestanis)
#include <iostream>
#include <iterator>
void Set::display(ostream &out) const {
ostream_iterator<int> out_it (out," ");
copy(Pool,Pool+Num,out_it);
out << endl;
}
Without testing, I'd do something like this. (Assumes the last node has Succ set to NULL, as I would recommend it does.)
void LoopList(struct Node *head)
{
for (struct Node *p = head; p != null; p = p->Succ)
{
// Do whatever with this node
Print(p);
}
}
I think I was over thinking it. Anyway here is what I ended up doing. Now I just need to add some formatting for the commas and im all set.
Node * Temp;
Temp = new (nothrow) Node;
Temp = Head;
out << "{";
while(Temp->Succ)
{
out << Temp->Item;
Temp = Temp->Succ;
}
out << '}' << endl;
Suppose your list is cyclical, you can use this:
struct Node *n = begin;
if (n != NULL) {
//do something on it
...
for (n = begin->Succ; n != begin; n = n->Succ) {
}
}
or
struct Node *n = begin;
if (n != NULL) {
do {
//do something
...
n = n->Succ;
} while (n != begin)
}