Heap memory vector initilization in C++ - c++

I am confused between
vector<node>* children = new vector<node>;
vector<node> *children = new vector<node>;
vector<node*> children = new vector<node>;
I just want to implement a general tree data structure as
struct node{
int index;
vector<int> sol;
vector<node *> children;
};
node *createNode(int indexVal)
{
node* n = new Node();
n->index = indexVal;
vector<int>* soll = new vector<int>;
n->sol = soll;
vector<node>* childrenn = new vector<node *>;
n->children = childrenn;
return n;
}
void addChildren(node* curr, node* child)
{
//something like
curr->push_back(child);
};
I want to be able to modify sol and children vector in which ever scope I want, given that I have a node pointer
I am confused which one of the three given will be the best results, how will they differ?
Also how would this extend to 2-d vectors?

You have this:
vector<node *> children;
That is fine, it's a vector of pointers to nodes. You do not use new to create it, it is created automatically whenever you have a node. So:
node *createNode(int indexVal)
{
node* n = new node();
n->index = indexVal;
return n;
}
The node has sol and children vectors directly inside it.

Regarding
vector<int>* children = new vector<int>;
and
vector<int> *children = new vector<int>;
They are the same. Both are declaring a pointer to a vector< int>. The only difference is the position of the *. Some people think it is more readable when the * is closer to the type name. Others prefer the * closer to the variable name.
Although I prefer the first one, which puts the * closer to type, the second one is more correct because in C++ the parser associates the * with the variable and not with the type. Thus one could declare the following:
vector<int> *ptr1, var2, *ptr2, *ptr3, var3
This would declare variables ptr1, ptr2 and ptr3 as being pointers to vector< int> while var2 and var3 would be normal variables. If you use the first writing style and write:
vector<int>* ptr1, var2, ptr2, ptr3, var3
Believing that all variables would be pointers, you would be wrong. Only ptr1 would be a pointer and all the others would be normal variables.
Now this
vector<node*> children = new vector<node>;
Is a completely different thing. While on the first two you're declaring a pointer to an array of ints, on the third one you are declaring an array of pointers to int. Also, note the typo you made on the new where you forget the *. To work, it would need to be (note the * at the end)
vector<node*> children = new vector<node*>;
Regarding your code, it seems that sol is the data stored in the node and children contains the pointers to the other nodes. So I believe in this case the following is correct
struct node{
int index;
vector<int> sol;
vector<node *> children;
};
And here
node *createNode(int indexVal)
{
node* n = new Node();
n->index = indexVal;
/* This is wrong and unecessary. As sol is not a pointer, when
you do a new above, the new already allocates the sol so that
you don't need to allocate again here */
vector<int>* soll = new vector<int>; // remove this
n->sol = soll; // not needed
/* Now here you have some typos. It should be vector<node *> and not
vector<node>* */
vector<node>* childrenn = new vector<node *>;
n->children = childrenn;
return n;
}
I didn't make any comments on the tree itself as you posted just a skeleton code instead of the real one. I assume you know trees and just wanted to know the C++ stuff regarding pointers and vector. If you don't know trees yet, look closer to your code because there are some parts that are not quite right.

The first two declarations are equivalent:
vector<node>* children = new vector<node>;
vector<node> *children = new vector<node>;
They declare a pointer to a dynamic vector.
The third declaration:
vector<node*> children = new vector<node>;
declares a dynamic vector<node*> and assigns a new vector to it, which will result in a compile-time error as the types are incompatible.
Try this out
node *createNode(int indexVal)
{
node* n = new node();
n->index = indexVal;
n->sol = new vector<int>;
n->children = new vector<node *>;
return n;
}
void addChildren(node* curr, node* child)
{
curr->children->push_back(child);
}

Related

Initialize array of structs in C++

I have struct Node in my code defined like this:
struct Node {
Node() : prev(0), left(0), right(0) {}
Node* prev;
Node* left;
Node* right;
char val;
};
I initialize array of Node structer objects like that:
Node** pool = new Node*[10000000];
I thought it will create Node structure objects using defoult constructor, but in fact the arrays seems to be empty. Is there any EFFICIENT way to create immidiately array of 'empty' objects?
You should be using std::vector<>; there is very little reason to use new in C++.
auto pool = std::vector<Node>(10000000);
(Your original code is creating Node*s, not Nodes.)
If for some reason you don't want to use vector, you could use std::unique_ptr<>. That code would be
std::unique_ptr<Node[]> pool(new Node[10000000]);
but you really should use vector.
Also, you can simplify and improve Node:
struct Node final {
Node* prev = nullptr;
Node* left = nullptr;
Node* right = nullptr;
char val = '\0';
Node(const Node&) = delete;
Node& operator(const Node&) = delete;
};
If you are constructing an ast/asg and you do not need linear data structures, you may consider still bulk allocating stuff with an ::std::vector<>, which will potentially give you cache locality.
You can still link individual Node objects via the pointers in your struct. If you then use indices instead of pointers, you can even resize your vector whenever you run out of available objects in your pool.
Node** pool = new Node*[10000000];
constructs an array of Node* rather than Node. What you are looking for is,
Node* pool = new Node[10000000];
which constructs an array of Node. If you actually want an array of Node* then the appropriate initialisation is,
int nObjects = 10000000;
Node** pool = new Node[nObjects];
for(auto i = 0; i < nObjects; ++i) {
pool[i] = new Node();
}
As others have said you likely do not want to use new or C-style arrays if you can avoid it.

Recursive struct without pointers? (Huffman)

I defined a binary tree this way:
struct btree {
int x;
btree* left_child = nullptr;
btree* right_child = nullptr;
};
Then I have a vector of floats (prob_distr) and I turn each float into a leaf and I put all the leafs into a priority queue (with a custom sort function but it doesn't matter here).
auto comp = [] (btree &a, btree &b) -> bool { return a.x > b.x; };
priority_queue<btree, vector<btree>, decltype(comp)> q(comp);
for(auto t: prob_distr)
{
btree leaf;
leaf.x = t;
q.push(leaf);
}
For the Huffman algorithm, I then loop on the priority queue until it only has 1 element left: I take the 2 nodes at the top out of the queue, I create a new node with these two nodes as children and I put these new node into the queue.
while(q.size() >= 2)
{
btree left = q.top(); q.pop();
btree right = q.top(); q.pop();
btree root;
root.x = left.x + right.x;
root.left_child = &left;
root.right_child = &right;
q.push(root);
}
The problem is that I have pointers to the left and right binary trees, and these trees are deleted when going out of the while loop. Then I have pointers pointing Nothing. Is there any way to solve this, for example by having a struct which stores the children trees and not just pointers, or by storing the nodes somewhere else without it gets too complicated?
You need to use pointers here, because the size of the structure has to be known at the compile time. If you would have struct itself as a member variable the memory requirement would recursively go to infinity.
You need to dynamically allocate the memory with new. The memory allocated with new is allocated until you explicitly release it by using delete. Just write
root.left_child = new btree(left);
root.right_child = new btree(right);
As already said, you also need to use delete to free the memory of the children. Be careful not to make copies of children which do not get deleted, and not to delete children which are still in use somewhere else. Consider using smart pointers.

Can't initialize an array of pointers in C++

I have an array of pointers to a structure called "table" (the structure is called Node).
I declare the array as so in the class:
Node * table;
Then, in another method, I initalize the table:
this->table = new Node [this->length];
And everything works fine. this->length is a valid entry, this->table is pointing to the right array, and etc. However, then I try to change the value of the elements:
for(int i = 0; i < this->length; i++) {
this->table[i] = new Node;
}
Or even
for(int i = 0; i < this->length; i++) {
this->table[i] = 0;
}
And everything starts bugging out. Why can't I set these pointers to anything?
This is the error I get:
(Where line 15 is the line of "this->table[i] = new Node;").
I hate to post long segments of code, so here's a shortened version of the code itself:
template <class T, class S>
class HashMap {
public:
HashMap();
private:
struct Node;
Node * table;
static const unsigned length = 100;
};
template <class T, class S>
HashMap<T, S>::HashMap() {
this->table = new Node [HashMap::length];
for(int i = 0; i < HashMap::length; i++) {
this->table[i] = new Node;
}
}
template <class T, class S>
struct HashMap<T, S>::Node {
T value;
S key;
Node * next;
};
No research I'm doing is telling me what the error is; any help is appreciated!
You don't have an array of pointers. You have an array of Nodes. Apparently, what you want is something like this:
Node ** table;
...
this->table = new Node*[this->length];
Or maybe you don't actually need an array of pointers, but simply an array of nodes. In that case, no extra initialization is needed beyond:
this->table = new Node[this->length];
Beyond that, unless this is a learning exercise, take a look at the standard library, which has dynamic arrays and hash maps all ready for you.
table is not an array of pointers. It's an array of Nodes (or rather, it points to an array of Nodes). The type of table is Node*; the type of table[i] is Node, not Node*.
If you actually do want an array of pointers, then you need
Node** table;
table = new Node*[length];
Or better still, something like
vector<unique_ptr<Node>> table;
table.resize(length);
You do not have declared an array of pointers.
Node *table(point to a node)
Node **table(point to an array Nodes)
Node** table;
table =new Node*[this->length];
for(int i=0;i<this->length;i++)
{
table[i]=new Node;
}
this->table = new Node [HashMap::length];
this->table is of type Node* and new Node [HashMap::length] also returns a Node* , i.e. an array of Node of lenght HashMap::length is created and the array address is stored in this->table pointer.
this->table[i] = new Node;
As an example, we can define:
int* arr = new int[10];
Here arr is of type int* but arr[0] will be of type int.
similarly, this->table[i] is of type Node and new Node returns Node*. Hence incompatible types. Correct line would be
this->table[i] = *new Node;
But, this line is unnecessary as the array of Nodes is already created and the memory is allocated. Using this line in the code will lead to a memory leak.

Unable to compile C++ code: invalid conversion from 'Node*' to 'int'

I have this C++ class with an array of Node objects called adj (I guess you don't need to see the implementation of my Node class)
class Graph {
public:
Node *adj;
bool *marked;
int nVertex, p;
int *distance;
void graph(int quantity);
bool is_marked();
void cleaner();
void newVertex(int value);
};
And I have this method which creates a node nod and tries to store it in the p-th position in adj:
void Graph::newVertex(int value)
{
Node *nod = new Node(value);
adj[p++] = nod;
}
When I try to compile this code I get the following error message:
invalid conversion from 'Node*' to 'int'
I can't see what I have done wrong in my code. The array initialization looks right to me and the object assignment too. Please help me answer this question.
UPDATE: the code for the Node class:
class Node {
public:
int value, cost;
Node *next;
Node() {}
Node(int val) {
value = val;
next = NULL;
cost = 0;
}
};
UPDATE: I can't use C++ vector here. I'd love to but it's for a homework thing. Before anyone thinks I am cheating or something, please note that I'm not asking for a solution to my specific assigned problem, but instead to a problem that I am having for compiling the code.
The type of adj[p++] is clearly Node& and you try to assign a Node* to it. I guess, your Node type has a constructor taking an int and the compiler tries but fails to convert the Node* to an int.
You probably meant to declare adj as
std::vector<Node*> adj;
... and then add new nodes using, e.g.:
adj.push_back(nod);
(note, that you still need to make sure the allocated objects get released at the appropriate point in time).
adj is of type Node*. adj[someIndex] is then of type Node. You are trying to assign Node* to Node. My educated guess is, you have Node::operator=(int), so the compiler tries to interpret your code that way - but that doesn't work out either, producing the error message you observe.
After you have created your new Node:
Node *nod = new Node(value);
you need to hook it up to your linked list. A linked list looks like:
[HEAD] => [value|next] => [value|next] => NULL
where HEAD in your case would be adj.
Therefore, you need to update the next of your new node to point to the current head node, then update the head node to point to the new node.
That is, you should end up with something like:
adj => [value|next] => [value|next] => ... => NULL
^ ^
nod adj'
where adj' is the old value of adj.
It helps to create diagrams of what the data structure looks like and how the values are being updated.
You then need to work out how to traverse the nodes in the list.
Also, don't forget to clean up the nodes in the Graph destructor (and be careful how you do that).
OK, with the definition of the Node class in hand I think I can see what you're trying to do. If I'm correct, you want to have Graph::adj point to a linked list of Node elements, with each Node then pointing to the next Node in the list. If that's correct the implementation of new_vertex needs to look something like:
void Graph::newVertex(int value)
{
Node *nod = new Node(value);
nod->next = adj;
adj = nod;
}
No need to have an index (p) - you'd just walk the linked list of Node elements with code similar to
Node *n = adj;
while(n != NULL)
{
// do something useful with n
n = n->next;
}
If you really insist upon using array syntax to access elements of the linked list (bad idea in my mind, as it just adds to the potential confusion, but YMMV) you could add something like
Node *operator[](int n); // 0-based index into Node list
to Graph with an implementation similar to
Node *operator[](int ndx)
{
Node *n = adj;
for( ; n != NULL, ndx > 0 ; ndx--)
n = n->next;
return n;
}
Share and enjoy,.

How to create multiple objects in the same function but without overwriting each other?

I'm trying to create an object in a function, but I am running into the problem that variable names have to be defined at runtime. Is there something I can do like with arrays that allows ne to dynamically create a variable in a function and preferably give it a different name from the one created when the function was called last?
***I'm working in C++
EDIT:
I can't give any code because I don't have any right now. All I have right now is pseudo code.
Basically, I'm trying to create a linked list, but the addNewItem() method that I want to use would require using the same method to create different objects.
EDIT:
Technically, we're not making a linklist, just more of a proof of concept to understand how they work.
EDIT: Here's the code:
#include "linklist.h"
#include <iostream>
using namespace std;
struct linklist
{
Student * obj;
linklist * next;
};
linklist * head;
int main()
{
}
void addStudent(char * newsdnt)
{
if(!head){
linklist * a = new linklist;
a->obj = new Student(newsdnt);
a->next = 0;
head = a;
return;
}else{
linklist * a = new linklist;
a->obj = new Student(newsdnt);
a->next = 0;
if(!head->next){
head->next = a; // Can only have one or two items in list
}
}
}
If you want a linked list - call new to create each new node and then add it to the list.
Smth like this:
void addStudent(char * newsdnt)
{
linklist* a = new linklist;
a.obj = new Student(newsdnt);
a.next = 0;
if( head == 0 ) {
head = a;
} else {
linklist* whereToAdd = head;
while( whereToAdd.next != 0 ) {
whereToAdd = whereToAdd.next;
}
whereToAdd.next = a;
}
}
The easiest way to build a (singly) linked list is to add the new item at the front:
linklist *head = 0;
...
a->next = head;
head = a;
...
If it is acceptable to add items at the tail in O(N) time, then you scan the list each time to find the end.
linklist head;
...
a->next = 0;
item = &head;
while (item->next != 0)
item = item->next;
item->next = a;
...
If you must add new items at the tail of the list in O(1) time, then keep a circular list, and a pointer to the tail of the list (so that tail->next is a pointer to the head of the list). (The previous list structures could be called 'open ended'.)
linklist root = { 0, &root };
linklist *tail = &root;
...
a->next = tail;
tail->next = a;
...
Beware: the termination conditions for iterating over the entire list (e.g. to find an item in the list) vary depending on the structure used (circular versus open-ended).
Caveat: untested code!
If you aren't sure what O(1) and O(N) means, then read up on 'Big O' notation.
I would suggest a vector:
#include <vector>
using namespace std;
void foo()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
cout << v[0] + v[1] << endl;
}
Assuming that you need N objects of some type T:Arrays are very much present in C++. So is the STL which provides you with a host of oppertunities. You need to define how you will want to access and use these objects -- that influences the choice of your container. But can you post some code so that our answers are a little less vague (and more helpful to you)?
I'm not exactly sure what you want but is sounds like you could use Multiset.
Please provide more details, and I might be able to provide more help.
For starters I would suggest you rename your linkedlist struct to node and add a new linked list struct that holds the head, and (maybe) current / tail pointers. You should then implement methods in this class / struct that will allow you to manipulate it.
What you're missing at the moment is a method that will traverse the list (recursively getting the next pointer until you're at the end) and return a pointer to the last element. Once you have that, you can set the next pointer of that element to your newly created object.