I'm trying to create a directed graph represented by an array of pointers to nodes, but I'm struggling to add nodes into each index of the graph. Here is what I have:
struct Node {
int index;
list<Node*> outgoingNodes;
};
struct Graph {
Node* nodePointers; // Array of pointers to nodes in graph
int N; // Number of nodes in graph
};
Here is how I am creating the graph:
Graph* graph = new Graph();
graph->N = 7;
graph->nodePointers = new Node[graph->N];
I then try to add a node into index 0 in the graph in the following way, but I get an error that "operand types are 'Node' and 'Node*'":
Node* a = new Node();
a->index = 0;
graph->nodePointers[0] = a;
Without changing either of my structs, how could I correctly add a node into an index in my graph's array of node pointers?
Thanks for any help!
Node* nodePointers is a pointer to an array of Nodes. If you want an array of Node pointers, you need to declare it as Node** nodePointers, and allocate the array with new Node*[graph->N]:
struct Graph {
Node** nodePointers; // Array of pointers to nodes in graph
int N; // Number of nodes in graph
};
int main() {
Graph* graph = new Graph();
graph->N = 7;
graph->nodePointers = new Node*[graph->N];
...
}
First:
struct Node {
int index;
list<Node*> outgoingNodes;
};
Although correct, it is inefficient for no apparent reason. Almost always prefer a vector over a list. It is as easy to work with, but takes less memory and works faster on almost any conceivable use case:
struct Node {
int index;
std::vector<Node*> outgoingNodes;
};
Next, the code:
struct Graph {
Node* nodePointers; // Array of pointers to nodes in graph
int N; // Number of nodes in graph
};
Holds a block of Node objects, not pointers to nodes. The best thing is to use a vector of pointers:
struct Graph {
std::vector<std::unique_ptr<Node>> nodePointers; // pointers to nodes in graph
};
This way deallocation and memory management will be automatic.
Then your usage example becomes:
// are you sure graph has to be on the heap?
auto graph = std:: make_unique<Graph>();
graph->nodePointers.resize(7);
I then you can add a node into index 0 in the graph in the following way:
graph->nodePointers[0] = std::make_unique<Node>();
graph->nodePointers[0]->index = 0;
This was the better way to do it, but if you insist on:
Without changing either of my structs, how could I correctly add a
node into an index in my graph's array of node pointers?
Then you should note that "graph's array" is not made of pointers, but of nodes. So adding nodes is done differently:
// you can still allocate the graph on the heap, but the following way is safer
Graph graph;
graph.N = 7;
graph.nodePointers = new Node[graph.N];
But now nodePointers is a misnomer, because it should be named nodes (not pointers).
Then add a node into index 0 in the graph in the following way (by this point it is already constructed):
graph->nodePointers[0].index = 0;
And adding an edge looks lije:
graph->nodePointers[0].outgoingNodes.push_back(&graph->nodePointets[2]);
At line graph->nodePointers[0] = a; change this to graph->nodePointers[0] = *a; It will work.
Now let me explain you, Suppose you want an array of int then you can declare it as int x[10] or int *x=new int(10). What it shows in second case that x is an pointer which points to int object not to int pointer. I hope you got your solution.
Related
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.
I'm working on a Graph Theory Algorithm. I know what is a graph and what is an edge etc. I have this first part of this script in c++ where it declares some variables and some struct, and after it defines a function that adds an edge.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int M = 500;
struct struct_edge
{
int v;
struct_edge * n;
};
typedef struct_edge * edge;
struct_edge pool[M * M * 2];
edge top = pool, adj[M];
int V, E, match[M], qh, qt, q[M], father[M], base[M];
bool inq[M], inb[M], ed[M][M];
void add_edge(int u, int v)
{
top->v = v, top->n = adj[u], adj[u] = top++;
top->v = u, top->n = adj[v], adj[v] = top++;
}
If this isn't enough I'll put an other part of the script.
I have some problem to understand why the struct_edge has a pointer to an other struct_edge (it's an edge not a node!). And I have some serious problem to understand this declaration:
edge top = pool, adj[M];
top is a pointer to a struct_edge and it has an array of struct and an array of int at the interior?!?
For a full code you can see this link
http://codeforces.com/blog/entry/49402
To answer your first problem, the graph is stored as an adjacency list format. Each node has an associated linked list of edges (struct_edge), each of which has an index (int v;) to the node at the end of the edge, and a pointer to the next edge (struct_edge* n;). The index is to the adj[M] array, which stores the M nodes that make up the graph.
Second problem, pool is a statically declared array of struct_edge, and the OP uses this to make a stack allocator, i.e. the new nodes are allocated by incrementing top, which is a pointer to the top of the stack. top is initialized to pool which is the base of the stack (start of the array).
EDIT: A diagram of the pointer arrangement for the wikimedia graph you linked:
(Note the indices start from 0 instead of 1, so Node 1 in the graph diagram corresponds to v = 0 in the code)
So I currently have a simple struct (linkedlist) that I will be using in a HashMap:
struct Node {
std::string key, value;
Node* head;
}
I'm currently trying to dynamically allocate an array with pointers to each struct. This is what I have right now ...
Node* nodes = new Node[100]
I understand this allocates an array of 100 nodes into memory (which I will have to delete later on); however, upon iteration to try to transverse these nodes (which I an implementing as a linked list)...
for (int x = 0; x < 100; x++) {
Node current = nodes[x]; // Problem is I wanted an array to node pointers. This is not a pointer.
while (current != nullptr) { // this isn't even legal since current is not a pointer.
// DO STUFF HERE
current = current.next; // This is not a pointer access to a method. I'm looking to access next with current->next;
}
}
Hopefully I was clear enough. Can someone how to allocate a dynamic array of pointers to structs? So far I'm able to dynamically allocate an array of structs, just not an array of pointers to structs.
There are two approaches. Either you allocate an array of structures and introduce one more pointer that will point to the element in the array that will play the role of the head.
For example
Node *head = nodes;
(in this case head points to nodes[0])
After the list will not be needed you have to delete it using operator
delete [] nodes;
Or you can indeed to allocate an array of pointers to the structure like this
Node **nodes = new Node *[100];
But in this case each element of the array in turn should be a pointer to a dynamically allocated object;
And to delete the list you at first have to delete each object pointed to by elements of the array for example in a loop
for ( int i = 0; i < 100; i++ ) delete nodes[i];
and then to delete the array itself
delete [] nodes;
It is a good idea to initialize each element of the array with zeroes when the array is allocated for example
Node **nodes = new Node *[100]();
I suggested you this structure:
class myList {
struct Node {
string value;
Node* next;
}
/*Public methods .. Add/Set/Get/Next/isEmpty.. etc ... */
Node* head, *tail;
};
in main:
myList* lis = new myList[number];
then you have number of lists! and do all work in class by method's and operators, like if you want the next node just call lis[0].getNext();
if you want to skip current node dolis[0].Next(); ... etc ..
this how to work, what you try to do is looks like C program!
I want to implement a tree trie and insert an example value into the key variable I am using a pointer to pointer and creating a dynamic array of 100 elements but my application crashes after starting.
#include<iostream>
using namespace std;
struct node {
int key;
node **children;
};
int main() {
node *child;
child = new node;
child->children = new node *[100];
child->children[20]->key = 90;
cout<<child->children[20]->key;
return 0;
}
You need to allocate memory for child->children[20]. You allocated memory for child->children but not for the elements in the array. You can do this as follows:
for (int i=0;i<100;++i) {
child->children[i] = new node;
}
By storing a node * you are storing the address of a node which contains the address of an array of addresses of nodes. This means that you need to allocated memory for all three levels of the hierarchy. You only allocated memory for two of the layers.
I've implemented a n-ary tree ( to be more specific, a trie ) and I was wondering if there's a method to represent and traverse it as a vector. With a binary tree that would be trivial ( see this question ) but I don't seem to find a way to perform this with a n-ary tree.
My final goal would be storing the vector represented tree to a file, mmap it and perform fast lookups without having it effectively loaded into memory.
An efficient approach to store a trie on disk ad using it with a mmap-ped pointer instead of allocating its inner structures would be great too.
Thanks.
If you have a tree where every node n has exactly k children, then you can proceed by placing the children of node n at positions k*n+m in the array, where m is between 0 and k-1. This will also work if every node has k or less children, but it will use a lot more memory than required if a lot of nodes have fewer than k children. The only other way I know of to store a tree as an array where nodes have different number of children is to store an auxillary array,, where for each node you store the offset into the original array to find that node's children and then you can either also store the number of children for each node or simply look up the offset for the next node's children to figure out how many children there are for the node.
Any graph structure can be represented as a flat array of nodes (in fact, that's how computer memory works). You just need to use indices instead of pointers, because pointers are invalidated when the vector grows or when the structure is mmap'd.
Here's a three-way tree as a flat vector:
struct Node {
Node(int data) : payload(data)
{
for (int i = 0; i < 3; i++) {
child[i] = (size_t)(-1); // invalid
}
}
int payload;
size_t child[3];
};
typedef std::vector<Node> Tree;
void add_node(Tree &t, size_t parent, int child_index, int payload)
{
t.push_back(Node(payload));
t[parent].child[child_index] = t.size() - 1;
}
You'll need separate logic to insert the root node since it doesn't have a parent. Also if you want a version where the mmap'd files can be used cross-platform, you'd better use fixed-size index types rather than the platform-specific int and size_t.
Traversal code is the same as with a pointer structure, except that
next = node->child[1]
becomes
t[t[node_idx].child[1]]
etc. i.e. each lookup of a node passes through the Tree object.
Assuming you know the No of node of the tree
you could change the size of adj vector to your suitable value
code->
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[100000000];
void dfs(int);
int main()
{
int i,n,root,par;
cin>>n;
//Input line contains n space separated integers.
// The ith integer represents the immediate ancestor of the ith node
// Node having 0 as parent node is the Root Node
i=1;
while(i<=n)
{
cin>>par;
if(par==0)
{
root=i;
}
else
{
adj[par].push_back(i);
}
i++;
}
//traversal of the Tree(Inorder traversal)
dfs(root);
}
void dfs(int at)
{
vector<int>::iterator it;
it=adj[at].begin();
cout<<*it<<" ";
while(it!=adj[at].end())
{
dfs((*it));
it++;
}
return;
}
Hoping this might helps