List inside struct memory leak? - c++

Some days ago I wrote this question: See here
Where I asked how to insert elements in a list inside a graph struct.
I've been writing more code and reached a point I cannot move forward.
I am posting the code just to make you have an idea:
//data_structures.h
#include <list>
// A structure to represent an adjacency list node
struct AdjListNode
{
int dest;
int weight;
std::list<int> adjacents;
struct AdjListNode* next;
AdjListNode() : dest(0), weight(0), next(NULL) {}
};
// A structure to represent an adjacency list
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
//Initialize each adjacency list as empty by making head as NULL
AdjList(): head(NULL) {}
~AdjList()
{
while (head) {
struct AdjListNode* temp = head;
head = head->next;
delete temp;
}
}
void addAdjacent(int adjacent) {
struct AdjListNode* newNode = new AdjListNode;
newNode->next = head;
head = newNode;
newNode->adjacents.push_back(adjacent);
}
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
// Create an array of adjacency lists. Size of array will be V
Graph(int v) : V(v), array(NULL) {
if(v >= 0) {
array = new struct AdjList[v];
}
else {
throw std::bad_alloc();
}
}
~Graph() {delete [] array;}
};
//main.cpp
int main()
{
// create the graph given in above figure
struct Graph* graph = new Graph(2);
graph->array[0].addAdjacent(1);
graph->array[1].addAdjacent(0);
for(int i = 0; i < graph->V; i++) {
for (list<int>::iterator it = graph->array[i].head->adjacents.begin();
it != graph->array[i].head->adjacents.end(); ++it) {
cout << "Vertex: " << i << " is adjacent to: " << *it << endl;
cout << "Amount: " << graph->array[i].head->adjacents.size() << endl;
cout << endl;
}
}
return 0;
}
As the graph is undirected, the output when zero is connected to 1 and vise-versa (graph->array[0].addAdjacent(1); array1.addAdjacent(0);) is:
Vertex: 0 is adjacent to: 1
Vertex: 1 is adjacent to: 0
However, adding more vertices (let's say, just one more) connected to vertex 0, for instance:
change this:
graph->array[0].addAdjacent(1);
graph->array[1].addAdjacent(0);
by
graph->array[0].addAdjacent(1);
graph->array[1].addAdjacent(0);
graph->array[0].addAdjacent(2);
graph->array[2].addAdjacent(0);
would output this:
Vertex: 0 is adjacent to: 2
Vertex: 1 is adjacent to: 0
Vertex: 2 is adjacent to: 0
What is clearly not correct. It is like vertex 0 is being overwritten, somehow. Any help, please?

Related

Inconsistant outputs on printing values

In this program I am cloning a graph in c++.
This is the question that i am coding.
This is my program and following it the issue and problem area.
#include <vector>
#include <unordered_map>
#include <queue>
#include <iostream>
using namespace std;
#define neighbours neighbors
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
#define neighbours neighbors
class Solution {
public:
Node* cloneGraph(Node* node)
{
// BFS
queue <Node*> q;
// add starting vec
q.push(node);
Node *curr;
int value;
vector <int> visited;
unordered_map <int, Node*> umap;
while(!q.empty())
{
curr = q.front();
q.pop();
visited.push_back(curr->val);
//cout << curr->val << "-";
// create new node
Node *newNode = new Node(curr->val);
// add new node val and addr to umap
umap[value] = newNode;
// clone neighbour list
vector <Node*> nlist;
//vector <Node*> list = curr->neighbours; // make copy of given list
for(Node* node: curr->neighbours)
{
value = node->val;
//cout << value << " ";
// search in map first, if exists take addr else make and insert into
// list
if(umap.find(value) == umap.end())
{
umap[value] = new Node(value);
}
nlist.push_back(umap[value]);
if(find(visited.begin(), visited.end(), value) == visited.end())
{
q.push(node);
}
}
cout << endl;
newNode->neighbours = nlist; // copy nlist to nodes list part
}
// starting of new node = umap[1];
return umap[1];
}
};
int main()
{
Node ob1;
Node ob2;
ob1.val = 1;
ob2.val = 2;
vector <Node*> nlist;
nlist.push_back(&ob1);
ob2.neighbours = nlist;
nlist.pop_back();
nlist.push_back(&ob2);
ob1.neighbours = nlist;
Solution obj;
Node *sv = obj.cloneGraph(&ob1);
cout << sv->val << "-";
for(Node *node : sv->neighbours)
{
cout << node->val << endl;
}
cout << &ob1 << " " << sv << endl;
}
When I comment out the last line my out put is
1-2
When I leave it as it is then the output is
1-0x7ffee561e4e0 0x7fb1ba402840
Also I just tried to comment out the cout << endl; which is towards the end of the while loop and also commented out the last statement of my program which gives an output
1-
What is the reason for such strange behaviour?
umap[value] = newNode; exhibits undefined behavior, by way of accessing an uninitialized variable value.
In practice, value contains some garbage that happens to sit on the stack. Changes to seemingly unrelated parts of the program affect the contents of the stack, and thereby the initial value of value, and ultimately the way the aforementioned undefined behavior manifests itself.

Why is there a memory error in this adjacency list?

In the code, I create an adjacency list with an array and each element of the array makes a list with it's adjacent nodes.
To access the array I needed to use ints; however, my vertex names were strings, so I mapped each vertex name to an int counting up from 0. As you can see in the nextNode() function the when a new node is created the'next'node should always be null.
An example result of the adjacency list will look something like this
inputVertices: a,b,c,d
inputEdges: (a,b), (a,d), (b,c) (d,b)
mapping: a<->0, b<->1, c<->2, d<->3
adjacency list:
arr elements| linked lists connected to elements
0 |->b->d
1 |->c
2 |
3 |->b
struct Node {
string vert;
int weight;
Node *next;
};
struct List {
struct Node *head;
};
class Graph {
int vertices;
int edges;
struct List *vertexArray;
int count = 0;
map<string, int> vertList;
public:
Graph(int vertices) {
this->vertices = vertices;
vertexArray = new List[vertices];
for (int i = 0; i < vertices; i++) {
vertexArray[i].head = NULL;
}
}
~Graph() {
vertList.clear();
}
Node *nextNode(string vert) {
Node *newNode = new Node;
newNode->vert = vert;
newNode->weight = 0;
newNode->next = NULL;
return newNode;
}
void addVertex(string vert) {
vertList[vert] = count; //maps Vertex to an integer in the order the Vertex is added
count++;
}
void addEdge(string head, string vert, int weight) {
Node *newNode = nextNode(vert);
newNode->weight = weight;
newNode->next = vertexArray[vertList.at(head)].head;
vertexArray[vertList.at(head)].head = newNode;
}
I stumbled upon my problem while trying to print my adjacency list
here and the program always crashes in the while loop below. It gets
through the first list of nodes fine, but crashes during the second
list.
I figured out the reason is the first list points to everything fine array[0].head->next = node1 node1->next = node2...noden->next = null(this exits the loop), however for the second list something different happens: array[1].head->next = node1 node1->next = node2...noden->next = 0xabababab. The last node should be null, but it is not. I set all new nodes to null. This causes a seg fault and crashes the program.
void print() {
for (int i = 0; i < vertices; i++) {
Node *n = vertexArray[i].head;
for (auto it = vertList.cbegin(); it != vertList.cend(); ++it) {
if ((*it).second == i) { // true if second type in map (aka int) == current array position
cout << (*it).first; //corresponding first type in map
while (n) {
cout << "-> " << n->vert;
n = n->next;
}
cout << endl;
}
}
}
}

List inside struct in c++

I have a list inside a struct in c++; I just want to insert elements to this list, as normal.
My structs are:
// A structure to represent an adjacency list node
struct AdjListNode
{
int dest;
int weight;
std::list<int> adjacents;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList
{
int pos;
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i) {
graph->array[i].head = NULL;
}
return graph;
}
When I try to aceess:
graph->array[position].head->adjacents->push_back(number);
It just prompts this to me:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Sorry, I have no clue about this error.
The segmentation fault comes from
graph->array[position].head->adjacents.push_back(number);
with
graph->array[position].head = NULL;
I suppose that you have implicit struct invariant in your code since you have two lists that are likely to be connected: the linked list starting at AdjList::head and iterating through AdjNode::next and the list AdjNode::adjacent.
To keep the connection you can add a (C style) function that adds an element in both lists.
void
addAdjacent(AdjList& list, int adjacent) {
// struct AdjListNode* newNode = (struct AdjListNode*) malloc(sizeof(struct AdjListNode));
struct AdjListNode* newNode = new AdjListNode;
newNode->next = list.head;
list.head = newNode;
newNode->dest = 0;
newNode->weight = 0;
newNode->adjacents = std::list<int>(); // undefined behavior with malloc
newNode->adjacents.push_back(adjacent);
}
Note that it is a bad idea to mix C style (malloc/free) with C++ style (especially with the containers of the Standard Template Library). The commented part of my code creates a segmentation fault since a std::list has not its fields filled with 0.
At the end the following main function works even if it has many memory leaks (see the valgrind tool)
int main(int argc, char** argv) {
struct Graph* graph = createGraph(2);
addAdjacent(graph->array[0], 1);
addAdjacent(graph->array[1], 2);
free(graph);
return 0;
}
A C++-98 solution (without any memory leaks) could be:
// A structure to represent an adjacency list node
struct AdjListNode
{
int dest;
int weight;
std::list<int> adjacents;
struct AdjListNode* next;
AdjListNode() : dest(0), weight(0), next(NULL) {}
};
// A structure to represent an adjacency list
struct AdjList
{
int pos;
struct AdjListNode *head; // pointer to head node of list
// Initialize each adjacency list as empty by making head as NULL
AdjList() : pos(0), head(NULL) {}
~AdjList()
{ while (head) {
struct AdjListNode* temp = head;
head = head->next;
delete temp;
}
}
void addAdjacent(int adjacent)
{ struct AdjListNode* newNode = new AdjListNode;
newNode->next = head;
head = newNode;
newNode->adjacents.push_back(adjacent);
}
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
// Create an array of adjacency lists. Size of array will be V
Graph(int v) : V(v), array(NULL)
{ if (v >= 0 && v <= 1000)
array = new struct AdjList[v];
else
throw std::bad_alloc();
}
~Graph()
{ delete [] array; }
};
int main() {
struct Graph* graph = new Graph(2);
graph->array[0].addAdjacent(1);
graph->array[1].addAdjacent(1);
delete graph;
return 0;
}

c++ topological sort giving incorrect output

After extensive testing and debugging, I cannot for the life of my find out why my topological sort algorithm produces the incorrect output. It simply lists the values of the nodes in descending order instead of sorting them topologically. I have listed all relevant classes/input files. Any hints or help is appreciated, thanks in advance.
Header for class graph:
/*
2/19/2016
This is the header for class graph. It includes the definition of a node
and the function signatures
*/
#pragma once
#include <iostream>
using namespace std;
struct node
{
// actual value at each node
int value;
// discovered time
int d;
// finished time
int f;
// keep track of how many edges each vertex has
int numEdges;
// keep track of color of node
char color;
// parent (previous) node
node* p;
// next node
node* next;
};
// Class to represent a graph
class Graph
{
public:
// constructor, give number of vertexes
Graph(int V);
// depth first search
void DFS();
// function to print sorted nodes
void print();
// function for reading file into adjacency list
void readFile(istream& in);
private:
// private function called in depth first search, visits every vertex
// of each edge in the graph
void DFSVisit(node* u);
// number of vertices
int V;
// array of node pointers, first node in each array is
// the vertex and following nodes are edges
node* adj[9];
// linked list to keep track of the sorted list found from depth first search
node* sorted;
// keep track of when each node is discovered/finished
int time;
// keep track of number of backedges
int backEdge;
};
The cpp file for class graph
/*
2/19/2016
This is the cpp file for class graph. It defines function behavior
*/
#include "Graph.h"
using namespace std;
#include <iostream>
#include <string>
Graph::Graph(int V)
{
// set graph's number of vertexes to number input
this->V = V;
this->backEdge = 0;
}
// Depth first search
void Graph::DFS()
{
// initialize all colors to white and parent to null
for (int i = 0; i < V; i++)
{
adj[i]->color = 'w';
adj[i]->p = NULL;
}
// initialize time to 0
time = 0;
// for each vertex, if it is white, visit its adjacent nodes
for (int i = 0; i < V; i++)
{
if (adj[i]->color == 'w') {
DFSVisit(adj[i]);
}
}
}
// Visit node used by depth first search
void Graph::DFSVisit(node* u)
{
// increment time
time++;
// set u's discovered time
u->d = time;
// set color to grey for visited but not finished
u->color = 'g';
// visit each adjacency, number of adjacencies stored by numEdges
for (int i = 0; i < u->numEdges; i++)
{
// create node pointing at u next
node* v = u->next;
// if the node is already grey, then it is a backedge
if (v->color == 'g') {
backEdge++;
}
// if it is white and undiscovered, set its parent to u and visit v's next nodes
else if (v->color == 'w') {
v->p = u;
DFSVisit(v);
}
}
// set last node to black
u->color = 'b';
// increment time
time++;
// set finishing time
u->f = time;
if (backEdge == 0) {
// adds a node to front of linked list that contains sorted values
node* newNode = new node;
newNode->next = sorted;
newNode->value = u->value;
sorted = newNode;
}
}
void Graph::print()
{
if (backEdge == 0) {
node* curr = sorted;
if (sorted == NULL) {
return;
}
else {
cout << "Sorted List:\n";
for (; curr; curr = curr->next)
{
cout << curr->value << " ";
}
cout << endl;
}
}
else cout << "Backedges: " << backEdge << endl;
}
void Graph::readFile(istream& in)
{
// create node pointers to use later
node* head;
node* prev;
node* curr;
// temp string to use while reading file
string temp;
int j;
// loop iterate vertex number of times
for (int i = 0; i < V; i++)
{
// 3rd character in string holds name of first edge
j = 3;
// read line by line
getline(in, temp);
// debug print out adjacency list
// cout << temp << endl;
// create head node, set value to value of vertex, put it at beginning of each linked list
head = new node;
head->value = i + 1;
adj[i] = head;
// set numEdges to 0 when row is started
adj[i]->numEdges = 0;
// set prev to head at end of each outer loop
prev = head;
// read every adjacency for each vertex, once j goes outside of string reading is done
while (j < temp.length()) {
// increment numEdges, meaning vertex has one more adjacency
adj[i]->numEdges++;
// create node and put in value, found by moving j up two spaces and subtracting 48
// because it is a char casted as an int
curr = new node;
curr->value = (int)temp.at(j) - 48;
// connect node, increment j by 2 because adjacencies separated by a whitespace
prev->next = curr;
prev = curr;
j += 2;
}
}
}
The driver for the program
/*
2/19/2016
This is the driver for the topological sort project. It reads a file of
vertexes and edges into an adjacency list and performs a depth first
search on that graph representation, creating a topological sort
if no backedges exist, this indicates a DAG or directed acyclic graph
if backedges do exist, this indicates a graph containing cycles meaning
it cannot be topologically sorted
*/
#include <iostream>
#include <fstream>
#include <string>
#include "Graph.h"
using namespace std;
string FILE_NAME = "graphin-DAG.txt";
int NUM_VERTICES = 9;
int main()
{
// create graph object giving number of vertices
Graph myGraph(NUM_VERTICES);
// open file
ifstream fin(FILE_NAME);
// validate that file was successfully opened, without file print
// error and exit program
if (!fin.is_open()) {
cerr << "Error opening " + FILE_NAME + " for reading." << endl;
exit(1);
}
// read file into adjacency list
myGraph.readFile(fin);
// perform depth first search
myGraph.DFS();
// if graph is a DAG, print topological sort, else print backedges
// this is handled by the print function checking backedges data member
myGraph.print();
}
And the input file
1: 2
2: 3 8
3: 4
4: 5
5: 9
6: 4 7
7: 3 8
8: 9
9:
Also a visual representation of the graph represented by the adjacency list:
http://i.imgur.com/6fEjlDY.png
I think the main problem was that there was some confusion between the 'real' nodes and the nodes in your adjacency list. At least I got confused, so I split the structure into struct Node and struct Adj. The graph now has a Node* nodes[9] for the nodes.
struct Node;
struct Adj
{
Node* node;
Adj* next;
};
struct Node
{
// actual value at each node
int value;
// discovered time
int d;
// finished time
int f;
// keep track of color of node
char color;
// the list od adjacencies for the node
Adj* adj;
};
and things almost instantly seem to work. The answer
Sorted List:
6 7 3 4 5 1 2 8 9
seems correct, [6 7 3 4 5] and [1 2 8 9]. See working example here
Please note that there are still numerous issues with the code, esp. with regard to memory management. Consider using a vector<Node> and a std::vector<Adj>. There are also uninitialized variables in the structs.

Adjacency List representation in C++, using class and pointers, head to lists not working properly

I am trying to implement adjacency lists using classes and pointers in C++. I have created a class of vertices, with an array of pointers pointing at each vertex. further in each vertex class, their is a linked list that should contain adjacency list of that vertex.
The following code runs, but does not give the correct adjacency list correctly. The head of the adjacency list changes, I don't know why. during passing pointers to different functions, this must be happening. The head gets assigned to the edge that is given to the function addToEdgeList() in some cases, but does not stay what is desired.
Here is my code. I can use C++ STL vectors to do this but this pointers issue is bugging me too much.
#include <iostream>
#include <string>
class vertex;
int vertexCount = 0;
struct edge {
int vertexIndex = 0; //takes the index of vertex of which the edge is.
edge *next = NULL; //the adjacency list of that index.
};
class vertex {
std::string name; //name of the vertex. But it can only be called using numbers(0, 1, 2,...)
struct edge *head; //the beginning of the edge it points to.
public:
vertex() {
name = "";
head = new edge;
head = NULL;
}
vertex(std::string abc) {
name = abc;
head = NULL;
// vertexCount += 1;
}
edge * getEdgeBeg() {
return head;
}
void setName(std::string abc) {
name = abc;
vertexCount += 1;
}
void addToEdgeList(edge * e) {
if (head != NULL) {
edge *ptr = new edge;
ptr = this->head;
std::cout << name << "-" << ptr->vertexIndex << "-" << e->vertexIndex << std::endl;
while(ptr->next != NULL) {
ptr = ptr->next;
}
ptr->next = e;
}
else {
head = e;
}
std::cout << head->vertexIndex << " " << name << " " << e->vertexIndex << std::endl;
}
void printEdgeList() {
edge *ptr = new edge;
ptr = head;
while(ptr) {
std::cout << " ->" << ptr->vertexIndex;
ptr = ptr->next;
}
delete ptr;
}
void printName() {
std::cout << name;
}
~vertex() {
delete head;
}
}*graph[15];
void addEdge(int vertex1, int vertex2) {
edge *temp1 = new edge;
edge *temp2 = new edge;
temp1->vertexIndex = vertex2;
temp1->next = NULL;
graph[vertex1]->addToEdgeList(temp1);
temp2->vertexIndex = vertex1;
temp2->next = NULL;
graph[vertex2]->addToEdgeList(temp2);
delete temp1;
delete temp2;
}
void printGraph() {
int i;
for(i = 0; i < vertexCount; i++) {
graph[i]->printName();
std::cout << " (" << i << ")";
graph[i]->printEdgeList();
std::cout << std::endl;
}
}
int main() {
vertex *vptr[15];
vptr[0] = new vertex;
vptr[0]->setName("A");
graph[0] = vptr[0];
vptr[1] = new vertex;
vptr[1]->setName("B");
graph[1] = vptr[1];
vptr[2] = new vertex;
vptr[2]->setName("C");
graph[2] = vptr[2];
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 2);
printGraph();
}
You have several errors on deallocating your pointers.
First, don't do edge *ptr = new edge; but edge *ptr = head; and after, remove your delete on *ptr.
In addEdge function, you add your edges pointers to your graph, so, as they are pointers, you should not delete them at the end of the function, otherwise your graph will point on NULL.
This is my output:
1 A 1
0 B 0
A-1-2
1 A 2
0 C 0
B-0-2
0 B 2
C-0-1
0 C 1
A (0) ->1 ->2
B (1) ->0 ->2
C (2) ->0 ->1