Represent and traverse a n-ary tree as a vector - c++

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

Related

C++ Creating Array of Pointers to Nodes in Directed Graph

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.

Fill an existing BST from sorted array of same size using inorder traversal

If I have BST tree of int of size n and a sorted array of int of size n (of different values) and I want to fill the tree with the array elements - I should do it by inorder traversal on the tree so that arr[0] would be in the left-most node and arr[n-1] would be in the right-most node. (So it takes O(n) time)
I tried to write a naive recursive function that do it but it doesn't work. It seems there should be done something to save the current index in the array.
void insert(Node* v, int* arr) {
if (!v) {
return;
}
insert(v->left, arr);
v->key = a[0];
insert(v->right, arr + 1);
}
How should I change it?
Your decision is almost true. Just change function declaration to:
void insert(Node* v, int* &arr)
and when you visit the right subtree you should pass the next element of array the next way:
insert(v->right, ++arr);
arr is necessary to pass as reference &. It is related to the passing of the copy of pointer to array in your case. When return from child node to parent node, the pointer is reset to the first element of initial array arr.
You can get the similar behaviour using pointer to pointer to array with minor changes in the code also.

Which data structure is like a combination of a doubly-linked list and an array?

Is there any already created structure which would be simply basic array of doubly linked list nodes?
I mean then you use get(int index) it would return element directly from array (array[i].element). With this structure I could easily do foreach too because every element would be linked to each other, so I would not need to think about blank array places.
Q: Why I need this ?
A: I have unlimited memory, I know how big array I need and I want that structure would be fastest.
Here is a small C++11 container guide, just set your constraints and follow the arrows:
IMO std::deque is the most probable candidate.
In case you want to create something yourself, here is an example of how could it look like:
struct Node{
// constructor
Node (int v, Node* n = 0, Node* p = 0)
: value(v), next(n), prev(p) { }
// data member
int value;
// pointer to next node
Node* next;
// pointer to previous node
Node* prev;
};
size_t number_of_nodes = 10;
Node* ptr = new Node[number_of_nodes];
Based on your description, I think the most fitting data structure would be a double-ended queue; or, in C++, a std::deque.
How it's like a doubly-linked list:
Stores back and front pointers
{push,pop}_{front,back} are O(1)
Doesn't need reallocs when expansion is necessary
How it's like an array:
Allows subscript indexing
O(1) random access
The get operation you're looking for is operator[] or std::deque::at.
Some considerations are that insertion/removal of elements not on polar ends of the structure (i.e., somewhere in the middle) are average case O(n) on the number of elements for the same reason it's O(n) to remove an element from a basic array.
Obligatory basic-use-case
I think what you are looking for is the container deque already present in the STL. See -> http://en.cppreference.com/w/cpp/container/deque
If it is not the one you are looking for, you probably find the container you need here --> http://www.cplusplus.com/reference/stl/
Hope this help

Constructing a binary tree using queue in C++

I am trying to write some data structure HW in C++. When I was trying to construct a binary tree using a queue, I was somehow confused by the pointer issues.
class Tree{
private:
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(NULL), right(NULL) {}
};
public:
TreeNode* root = NULL;
Tree();
Tree(queue<int>& val);
~Tree();
string toString_bf();
};
Tree(queue<int> &vals){
if (vals.empty())
return;
root = new TreeNode(vals.front());
vals.pop();
queue<TreeNode**> pts; // what is the meaning of this? Why should use pointers to pointer?
pts.push(&(root->left)); // also have doubts here, about the reference used in the parameter
pts.push(&(root->right));
while (!vals.empty()){
TreeNode* t = new TreeNode(vals.front());
*(pts.front()) = t; // and here
pts.pop();
vals.pop();
pts.push(&(t->left));
pts.push(&(t->right));
}
}
According to my understanding, left and right are both pointers, why could not just pass values to them?
The variable pts is a queue of pointers to where subtrees need to be placed later. Those locations are themselves pointers to TreeNode (each being either a left or right data member, of type TreeNode *) so it makes sense that you need a TreeNode ** to point at them.
In other words, each time *(pts.front()) = t; is executed, a left or right member of a previously contructed TreeNode is being set to point to the most recently constructed node.
You could make a typedef TreeNode *TreePtr; and perhaps it would look cleaner using that.
To further clarify what's happening:
Each time the 'while' loop starts:
root is the root of a tree under construction, containing n+1 nodes, each holding one value taken from the input queue vals (where n is the number of times the while loop has already run)
vals contains all the remaining values yet to be put into the tree (if any)
pts contains a set of pointers to pointers within the nodes in the tree; it contains pointers to all of the pointers which have not yet had subtrees assigned to them; there are n+2 of these.
So each loop makes one new node, makes one of these unassigned pointers point at the new node, and then adds the new node's unassigned pointers to the queue.
Note that when the operation ends, there are always n+2 pointers in pts, which are discarded. By knowing how many nodes are needed ( = vals.size()) it's possible to stop doing the pts.push operations once enough have been done, which reduces the amount of temporary space needed by about 50%:
vals.pop();
if( pts.size() < vals.size()) {
pts.push(&(t->left));
pts.push(&(t->right))
} // otherwise we have enough for all remaining vals.

C++ fixed-size linked list

Non-duplicates:
Which STL C++ container to use for a fixed size list? (Specific use case)
std::list fixed size (See below)
Motives:
Allocation happens once (in the constructor) and deallocation happens once (in the destructor).
O(1) insertion and removal of an element anywhere in the list without needing to deal with the overhead of memory management. This isn't possible with an array-based implementation.
Is there a straightforward approach for implementing this using the standard library? Is there an implementation of something like this in Boost?
What I was first thinking when I read that was the approach to use a different allocator, i.e. one that pre-allocates a given number of elements to avoid the price of allocating. I'm not familiar with defining allocators though, but if you find out I'd be interested in the results.
Without that, here's a different approach. I saved myself the template ... stuff, but I guess you'll be able to do that yourself if you need.
typedef std::list<...> list_t;
struct fslist: private list_t
{
// reuse some parts from the baseclass
using list_t::iterator;
using list_t::const_iterator;
using list_t::begin;
using list_t::end;
using list_t::empty;
using list_t::size;
void reserve(size_t n)
{
size_t s = size();
// TODO: Do what std::vector does when reserving less than the size.
if(n < s)
return;
m_free_list.resize(n - s);
}
void push_back(element_type const& e)
{
reserve_one();
m_free_list.front() = e;
splice(end(), m_free_list, m_free_list.begin());
}
void erase(iterator it)
{
m_free_list.splice(m_free_list.begin(), *this, it);
}
private:
// make sure we have space for another element
void reserve_one()
{
if(m_free_list.empty())
throw std::bad_alloc();
}
list_t m_free_list;
};
This is incomplete, but it should get you started. Also note that splice() is not made public, because moving elements from or to a different list would change both size and capacity.
I think the simplest way to do it would be to have 2 data structures. An array/vector which is fixed sized and is used for "allocation". You simply grab an element from the array to create a node and insert it into your list. Something like this seems to meet you requirements:
struct node {
node *prev;
node *next;
int value;
};
node storage[N];
node *storage_ptr = storage;
then to create a new node:
if(node == &[storage + N]) {
/* out of space */
}
node *new_node = *storage_ptr++;
// insert new_node into linked list
This is fixed size, allocated all at once, and when storage goes out of scope, the nodes will be destroyed with it.
As for efficiently removing items from the list, it is doable, but slightly more complex. I would have a secondary linked list for "removed" nodes. When you remove a node from the main list, insert it at the end/beginning of the "deleted" list.
When allocating, check the deleted list first before going to the storage array. If it's NULL use storage, otherwise, pluck it off the list.
I ended up writing a template for this called rigid_list.
It's far from complete but it's a start:
https://github.com/eltomito/rigid_list
(motivated by Ulrich Eckhardt's answer)