Graphs using Adjacency List in c++ - c++

I am trying to implement a graph in C++. I am representing a node in graph using a structure which contains two variables - a) an integer to contain some information about the node. b) a list to contain index of other vertex which are connected to it. Following is the code.
// Graphs using adjacency list
#include <iostream>
#include <list>
#include <cstdlib>
using namespace std;
// structure to represent a vertex(node) in a graph
typedef struct vertex{
int info;
list<int> adj; // adjacency list of edges contains the indexes to vertex
} *vPtr;
int main(){
vPtr node = (vPtr)malloc(sizeof(struct vertex));
node->info = 34; // some arbitrary value
(node->adj).push_back(2); // trying to insert a value in the list
return 0;
}
The code is compiling fine but I am getting a run time error while I am pushing back an element in the list. Is there any problem in my structure. I am using code blocks and GNU GCC, C++ 98 compiler to compile my code.

malloc is a C function - it shouldn't be used with C++ objects, which is very well explained here (short answer: in C++, when you are not dealing with POD types, std::list in your case, you must call the object's constructor to have the actual object ready for use, and malloc() does not do that).
You should used new instead. While malloc only allocates a block of memory of size vertex, new does that and also initializes std::list aswell by calling it's constructor (interesting to point out that when you call delete(), you are calling your object's desctructor aswell).
Here is a piece of code that works for your case, although I suggest you to start using more C++ features within C++ projects:
#include <iostream>
#include <list>
#include <cstdlib>
#include <new>
using namespace std;
// structure to represent a vertex(node) in a graph
typedef struct vertex{
int info;
list<int> adj; // adjacency list of edges contains the indexes to vertex
} *vPtr;
int main(){
cout << "allocating memory for our vertex struct... \n";
vPtr node = new vertex();
node->info = 34; // some arbitrary value
(node->adj).push_back(2); // trying to insert a value in the list
cout << "cleaning allocated memory... \n";
delete(node);
return 0;
}

Couple of things.
Because you are using malloc no constructor is ever called, and as
such the non primitive member adj is never constructed and is
NULL.
You are leaking memory since you never free/delete any of your dynamically allocated memory.
If you are using C++ why are you using malloc instead of new and delete?
You don't have to say struct vertex in the sizeof for C++.
To fix it you could do:
vPtr node = new struct vertex(); // also change to delete instead of free
or
// use current malloc line, change adj to be a pointer to a list and new it
// but this will cause additional problems for you since you really need to use a constructor for STL::list
node->adj = new list<int>;
Bottom line you really shouldn't be using malloc here.

This is UpAndAdam's answer, written completely.
// Graphs using adjacency list
//
#include <iostream>
#include <list>
#include <cstdlib>
using namespace std;
// structure to represent a vertex(node) in a graph
typedef struct vertex{
int info;
list<int> *adj; // adjacency list of edges contains the indexes to vertex
} *vPtr;
int main(){
vPtr node = (vPtr)malloc(sizeof(struct vertex));
node->adj = new list<int>;
node->info = 34; // some arbitrary value
(node->adj)->push_back(2); // trying to insert a value in the list
return 0;
}

Related

Problem with my dynamic array - Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

I have a problem when I'm doing my debugging: Xcode gives:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I think it's a problem with my dynamic array...
My assignment is to calculate the perimeter of a polygon with points.
So, my program receives points (x and y) to fill an array of Points, then I made another array, distance, which I fill with all the distances, and then I can calculate the perimeter.
I don't know if it's very clear but I'm a beginner in C++.
#include <iostream>
#include "Point.h"
#include "Polygone.h"
using namespace std;
int main() {
int numberSide;
int x,y;
Point* array = nullptr;
Polygone myPolygone;
cout<<"enter number of sides:"<<endl;
cin>>numberSide;
float* distance=new float[numberSide];
cout<<"enter points:"<<endl;
for (int i=0; i<numberSide; i++) {
cin>>x>>y;
Point p(x,y);
array[i]=p;
}
for (int i=0; i<numberSide-1; i++) {
distance[i]=array[i].distance(array[i+1]);
}
distance[numberSide]=array[0].distance(array[numberSide]);
myPolygone.perimeter(distance);
delete [] distance;
return 0;
}
You never actually allocate any space for the array variable - you are only declaring it and assigning it a nullptr value. Thus, when you later try executing the array[i]=p; you are trying to dereference a null pointer, which causes your EXC_BAD_ACCESS error.
To fix this, you need to allocate the array, once you know what size it is (i.e. how many sides your polygon has). You should do this in the same way as you allocate the distance array:
cin>>numberSide;
float* distance=new float[numberSide];
Point* array = new Point[numberSide]; // And you should delete the earlier "Point* array = nullptr;` line
Of course, you also need to free the memory when you have finished with it:
delete [] distance;
delete [] array;
return 0;
However, as you are using C++, a far better way than using raw pointers and the new operator is to use the Standard Template Library's std::vector container, which takes care of all allocating and freeing operations internally. Here are the relevant 'replacement' lines:
#include <vector> // This header defines the `std::vector` container
//...
cin>>numberSide;
std::vector<float> distance(numberSide);
std::vector<Point> array(numberSide);
Then you don't need the delete[] lines, as the vectors' memory will be released automatically when the vectors go 'out of scope'. Also, you don't need to really change any of your other code, as the std::vector class has a [] operator, which works as you would want it to.

Windows Visual Studio C++ lists of lists

Windows lists
Found the following post somewhat helpful but I'm still struggling.
Creating list of lists in c++
What I require is a list of string lists.
So:
#include <list>
typedef list<std::string, allocator<std::string>>> LISTSTR;
typedef list<LISTSTR, allocator<LISTSTR>> LISTLISTSTR; // uncertain what this is doing?!!?
main()
{
LISTLISTSTR records;
// Add a blank string list to the list
LISTSTR *rowoffields = new LISTSTR();
rowoffields->insert(string("Field1"); // also tried new string("Field1")
records.insert(rowoffields); // also tried *rowoffields
}
But this returns the compile error :
no instance of overloaded function "std::list<_Ty,_Alloc>::insert[with _Ty=std::string, _Alloc=std::allocator<std:string>]" matches the argument list
argument types are (std::string) // or types are (std::string*) if using new string("Test")
object type is: LISTSTR
no instance of overloaded function "std::list<_Ty,_Alloc>::insert[with _Ty=LISTSTR, _Alloc=std::allocator<LISTSTR>]" matches the argument list
argument types are (LISTSTR*) // or types are (LISTSTR) if using *rowoffields
object type is: LISTLISTSTR
Here is one way to go about doing it that is perhaps a bit closer to Python's normal usage. We first declare an array of pointers to a list of strings (type-specified-up-front, not Python-duck-typed (though we could do that with templates). Then we use those pointers in a memory-safe fashion (no leaks) to make new lists. Notice in this specific setup that the total number of lists is fixed at compile-time (and is equal to const int SIZE), and the array of pointers lives on the stack, but the lists the pointers point to are all dynamically allocated on the heap. (You can do this with new and delete, but the newer smart pointers are really the way to go).
#include <list>
#include <memory> //for the smart pointers
#include <iostream>
const int SIZE = 3;
int main() {
//make an array of smart pointers to list of strings:
std::unique_ptr<std::list<std::string>> myLists[SIZE];
//use each smart pointer in the list to make a new list:
for (int i = 0; i < SIZE; i++) {
myLists[i] = std::make_unique<std::list<std::string>>();
}
//load each new list with a single string:
myLists[0]->push_front("Hello");
myLists[1]->push_front("World,");
myLists[2]->push_front("I'm C++!");
//print the results
for (int i = 0; i < SIZE; i++) {
std::cout << myLists[i]->front() << " ";
}
std::cout << std::endl;
return 0;
}
Now if you wanted to be able to add more lists to your list of lists at runtime, you'd have to dynamically allocate the array of pointers to list, rather than do it with static (automatic) allocation as in this example. (Edit: Or, you could set some upper limit, say 100, and then make that the max amount of lists in the application. Probably want to use a std::array to hold that list of pointers, rather than the plain array above, as std::array does bounds checking as with Python).
For the simpler version:
#include <list>
//remove typedefs
int main() { //notice the int!
const int SIZE = 10;
//make array of pointers to list of strings (on stack, fixed size)
std::list<std::string>* myLists[SIZE];
//use pointer to make new list on heap:
myLists[0] = new std::list<std::string>;
//use pointer syntax (instead of . use ->) to call list functions
myLists[0]->push_front("Old style C++");
//more code...
//when finished must remember to free that memory:
delete myLists[0];
//and not leave a dangling pointer:
myLists[0] = nullptr;
return 0;
}

How to create an array of pointers to structure using new?

I am trying to create a graph using linked list styled nodes where each node is a structure containing a key and an address to the next node, but I want to join multiple nodes to one node so I tried creating an array of pointers to structure and initialize them using new dynamically but it throws an error saying that it "cannot convert node*** to node** in assignment".
I have tried using struct node* next[] but it didn't work well. What am I missing here? Should I just use a vector of pointers instead of an array?
struct node
{
int key;
struct node** next;
};
int main()
{
struct node A;
A.key = 12;
A.next = new node**[2];
return 0;
}
Should I just use a vector of pointers instead of an array?
This is often an ideal solution. This would fix the memory leak that your program has (or would have if it compiled in the first place). An example:
struct node
{
int key;
std::vector<node*> next;
};
// usage
A.next.resize(2);
Vector does have space overhead, which can be a problem with big graphs because the total overhead increases linearly in relation to number of nodes. If vector is not appropriate for you, an alternative is std::unique_ptr, which does not have any overhead compared to a bare pointer:
struct node
{
int key;
std::unique_ptr<node[]> next;
};
// usage
A.next.reset(new node*[2]);
new node**[2];
What am I missing here?
You're attempting to create an array of node** when you need an array of node*.
Should I just use a vector of pointers instead of an array?
YES!
After including the vector library, then in your structure, you would have a member like this:
std::vector<node*> next;
This is the C++ approach, using raw pointers is the C approach.
As an encyclopedian information though, with raw pointers, you would do:
A.next = new node*[2];
which means an array of two pointers.

Allocating space for List inside structure

I have a structure as follows:
struct Vertex{
list<int> q;
};
I created an array of size 10 as follows:
Vertex *ver = (Vertex*) malloc(10 * sizeof(Vertex));
Now I wish to insert in the list. I am having a hard time figuring out why is it giving a segmentation fault:
ver[1].q.push_back(10);
Can someone please explain what's wrong here?
mallocjust allocates memory, it doesn't construct any objects in that memory.
You could instead try
Vertex* ver = new Vertex[10];
which does initialize the Vertex structs and its list members.
An even easier way to create 10 Vertex objects is
std::vector<Vertex> ver(10);
This also saves you from the trouble of having to delete[] the objects later.
The constructor for your list q was never called. Either you use the new operator (Vertex* ver = new Vertex[10];) or you use std::vector<Vertex> instead of Vertex*
#include <list>
#include <vector>
std::vector< std::list<int> > q(10);
if you need an array of vertices with 3 scalars of type int you should use this:
#include <array>
#include <vector>
std::vector< std::array<int,3> > q(10);

How to use a vector of pointers to a structure in c++?

I have an assignment that is due about a week from now. It is about making a letter counter (cases don't matter) of text file in the directory the source file is. Then the output of the letters should be, first, according to the letter with highest number of occurrences of it, and, second, if there are letters with the same number of occurrences, then sorting will be according to the alphabetical order. The assignment page is here: http://www.cs.sfu.ca/CourseCentral/135/tjd/a1.html. I already did a program that has the same output (here it is: https://drive.google.com/file/d/0BxuBN4fpoq5LNHIwR2U2elVkdVE/view?usp=sharing). The thing is, as what you can see from the assignment page, is that my proffisor is insisting that we use a vector, Freq_table, that has pointers to a structure, char_count. I tried to do simple code to add elements to the vector, like this:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <vector>
using namespace std;
struct char_count {
char c;
int count;
};
typedef vector<char_count*> Freq_table;
int main () {
char_count A_count = {'A', 0};
Freq_table.push_back (A_count);
}
But the compiler always gives this message:
error: expected unqualified-id before '.' token
Freq_table.push_back (A_count);
I can't seem to solve this error. All I need for now is to know what is the syntax of adding elements to a vector that has pointers to a structure.
Regards.
What you are doing is wrong, you are doing something like
int.push_back(A_count);
Furthermore, you tell your vector that you want to store a pointer to a char_count-variable, but you store the variable itself, therefore resulting in another error.
Before you can push values into a vector, you have to declare it. A possible (untested) solution would be
Freq_table newTable;
newTable.push_back(&A_count);
You've declared Freq_table as a type, not an instance, so change:
typedef vector<char_count*> Freq_table;
to:
vector<char_count*> Freq_table;
To add to the table, you have to pass the address of a char_count instance. One way is:
char_count* A_count = new char_count; // allocate a new instance...returns the address.
A_count->c = 'A';
A_count->count = 0;
Freq_table.push_back(A_count);
Don't forget you will have to delete the instances in the vector if allocated with new or you will have memory leaks.
The only redeeming part of that assignment is that you aren't actually required to use dynamic memory. You can use the vector of pointers for only the one purpose it is reasonably well-suited, namely for getting the letters sorted by descending frequency.
The pointers in the vector will be non-owning pointers. It is appropriate to use a raw pointer for non-owning pointers, since that can't cause a memory leak.
Something like this:
int main(void)
{
char_count dictionary_order[26];
for( int i = 0; i < 26; ++i ) dictionary_order[i] = {'A'+i, 0};
/* read the input, count letters.
Notice that the matching letter is always at index ch-'A' */
Freq_table frequency_order;
for (auto& item : dictionary_order) frequency_order.push_back(&item);
sort(frequency_count.begin(),
frequency_count.end(),
[](char_count* a, char_count* b) -> bool
{
return (a->count == b->count)? (a->c < b->c) : (a->count > b->count);
}
);
/* print them out */
}
No dynamic allocation, therefore no leaks. And because C++ destroys local variables in the opposite order of declaration, the pointed-to objects will exist longer than the pointers themselves do.
If you needed to accommodate a variable number of items, you could have a vector<char_count> that manages the memory, and store pointers to those in your mandated vector of pointers. Of course, pointers become invalid if the vector is resized, so you'd build the entire "real" vector before starting to fill the pointer vector.