Construct Binary Tree from Parent Array test case failing - c++

Link of the question-[Link][1]
Basically we are given an array of integers and it's size. Question is to construct a binary tree from it. Each index corresponds to data stored in a node, and the value of that index is the data of the parent. Value of the root node index would always be -1 as there is no parent for root. The Output will be the sorted level order traversal of the tree.
Now my approach is that I parse the array from 1 to n(not the 0th element/root node), and for each element, I get it's parent using the first function, and insert the child accordingly. But one particular test case is failing. Maybe the website's own output is not correct. I will post everything below:-
Example test case-
Size of array-7
Elements- -1 0 0 1 1 3 5
Output- 0 1 2 3 4 5 6
Particular test case(which is my doubt)-
Size of array- 42
Elements-
3 19 1 41 35 29 27 11 17 23 9 15 33 13 39 23 19 25 21 1 33 15 31 21 5 7 37 29 7 11 31 39 -1 27 3 9 25 17 13 41 37 35
Website's output- 32
My output - 0
Functions
void getParent(Node* root, int val, Node* &main)
{
if(root==NULL) return;
if(root->data==val){
main=root;
return;
}
getParent(root->left,val,main);
getParent(root->right,val,main);
}
Node *createTree(int parent[], int n)
{
if(n==0) return NULL;
Node * root=new Node(0);
for(int i=1;i<n;i++)
{
Node* main=NULL;
getParent(root,parent[i],main);
//main has the parent
Node* child=new Node(i);
if(main==NULL) break;
if(main->left==NULL)
{
main->left=child;
}
else if(main->right==NULL)
{
main->right=child;
}
}
return root;
}
[1]: https://www.geeksforgeeks.org/construct-a-binary-tree-from-parent-array-representation/
[2]: https://i.stack.imgur.com/0fRmn.png

Not sure what you are doing with your getParent method. Also you are initiating a root node with value 0 and not doing anywith it in the loop and then finally you return the root. I suspect your root will always have a value 0.
The solution is very simple actually. You initialize an array of nodes with each node's value as the index of the array. For example for an array of size 5, you create an array of 5 nodes with each node having a value of the index at which it is located.
Then next step is go through the parent array and see if the node located at parent[i] has either left or right "available", if yes assign the node accordingly.
the code is :
Node* createTree(int parent[], int n) {
Node** nodes = new Node*[n];
for ( int i = 0; i < n; i++ )
nodes[i] = new Node(i);
int rootIndex = 0;
for ( int i = 0; i < n; i++ ) {
if ( parent[i] == -1 ) {
rootIndex = i;
} else {
if ( nodes[parent[i]] -> left == NULL ) {
nodes[parent[i]] -> left = nodes[i];
} else if ( nodes[parent[i]] -> right == NULL ) {
nodes[parent[i]] -> right = nodes[i];
}
}
}
return nodes[rootIndex];
}

Related

Double linked list in C++ (Pointer memory access violation)

I am trying to implement a double linked list in C++. I get an error which I do not understand. It is a runtime error in else branch at line:
list->tail->next = new_node;
It says that list->tail was at a different memory address. Unfortunately, I have the German version of Visual Studio, so I can not translate it that good. The error is marked as a "write access violation".
Could someone explain me what is going on here?
#include <iostream>
typedef struct dlist_node dlist_node;
struct dlist_node { // represents one node with its data and with pointers to the next and
dlist_node* next; // previous node
dlist_node* prev;
int data;
};
typedef struct { // represents nodes of the list that one can access
dlist_node* head;
dlist_node* tail;
} dlist;
void dlist_append(dlist* list, int data) { // to append the list with new data/node
dlist_node* new_node = new dlist_node;
new_node->data = data;
new_node->next = new_node->prev = NULL;
if (list->tail == NULL) { // if list is empty
list->head = list->tail = new_node;
}
else {
list->tail->next = new_node; // error appears here
new_node->prev = list->tail;
list->tail = new_node;
}
}
int main() {
dlist* double_linked_list = new dlist;
std::cout << double_linked_list->head;
dlist_append(double_linked_list, 42);
std::cout << double_linked_list->head;
}
If you are still stuck, then let's see if we can get you unstuck. While C++ already provides doubly linked-list in std::list which should be the preferred list implementation over writing your own. That said, we understand that many of the linked-list self-implementation are exercises for educational purposes, either for self-study or as part of a class. That is fine, you need to fully understand them, there is a lot of legacy-code out there that makes use of all types of self-invented lists.
As noted in the comments, among other issues, your biggest issue is you do not allocate and initialize your dlist_node nodes when adding nodes to your list. Your list has two separate struct, dlist that holds the head and tail pointers (which with a more encapsulated approach can be made members of the same struct or class where your prev and next and payload (data) pointers are declared, and the functions that operate on the list would be member functions)
Using the separate struct is fine, and using both head and tail pointers within the struct ensures your list additions can be done in-order in O(1) time. While your code has been edited, there is no reason to allocate for dlist double_linked_list. You have a struct, you can simply create an instance. The pointers head and tail will point to a dlist_node that you allocate and initialize with each node you add to your list.
The key is that head will always point to the first node in your list and tail will always point to the last. This provides the starting points for iterating over each node in your list in the forward, and reverse directions. When you add (or append) a node to your list, after setting the prev and next pointers correctly for each node involved, you simply update the head (if inserting a new first node), or tail (if adding to the end of the list) pointers accordingly.
When using a simple int as the list payload, you can easily allocate for and initialize your new node in your add (append) node function. However, as your payloads become more complicated, it is often convenient to write a createnode() function that takes the values needed to fully initialize the node as parameters and then allocates for and fully initializes the node, returning a pointer to the new node on success, or nullptr in the case of allocation failure. This allows you to reuse your add() function and only customize your createnode() for each new list.
Before looking at your add and create node functions, let's look at your structs themselves. While in C, it is convenient to use typedef to create an alias for struct dlist or struct dlist_node, in C++ that is completely unnecessary and often causes more problems than it solves. When you declare a struct in C++, you simply create an instance of the struct and can refer directly to the struct name as a type, e.g.
struct dlist_node { /* list node */
int data;
struct dlist_node *prev, *next;
};
struct dlist { /* list wrapper with head & tail pointers */
dlist_node *head, *tail;
};
Now for an add() (your append) and a createnode() function, you could do the following:
/** create new node initialize all members */
dlist_node *createnode (int v)
{
dlist_node *node = new dlist_node; /* allocate node */
if (!node) /* validate allocation (and use try/catch) */
return nullptr;
node->data = v; /* initialize members values */
node->prev = node->next = nullptr;
return node; /* return new node */
}
/** add node at end of list, update tail to end */
dlist_node *add (dlist *l, int v)
{
dlist_node *node = createnode (v); /* allocate node, initialize data */
if (!node) /* validate allocation */
return nullptr;
if (!l->head) /* if 1st node, node is head/tail */
l->head = l->tail = node;
else { /* otherwise */
node->prev = l->tail; /* set prev to tail */
l->tail->next = node; /* add at end, update tail pointer */
l->tail = node;
}
return node; /* return new node */
}
Always validate that your allocation has succeeded and handle the error if it fails.
Now to create a list in main() (or any other scope where the list is needed) you simply declare an instance of the struct and initialize both head and tail to nullptr (which can be moved to the constructor so it happens automatically), you can do:
dlist list = { nullptr, nullptr }; /* initialize list pointers nullptr */
To create a list named list. To test the list, add a few nodes to the list, check the list both forward and backwards, and then remove all the nodes in a random order checking all pointers after the removal of each node, e.g.
#define NNODES 16
...
dlist list = { nullptr, nullptr }; /* initialize list pointers nullptr */
int a[NNODES]; /* array to shuffle */
for (int i = 0; i < NNODES; i++) { /* fill array with NNODES int */
add (&list, i+1);
a[i] = i+1;
}
(the array is used to hold the node values, so you can shuffle the array and then iterate over the shuffled array removing the nodes in a random order)
You generally will want a function to allow you to delete a specific node, and then all nodes when the list is no longer needed, freeing the memory for a given, or all nodes. You need a function to print the list in forward and reverse directions. If you modify the example I linked to to use new and delete instead of malloc and free and use iostream instead of stdio.h, you would have:
#include <iostream>
#include <random>
#ifndef NNODES
#define NNODES 16
#endif
/*
* non-list misc functions
*/
/** shuffle integer array of size 'n'
* (using fisher-yates method)
*/
void shuffle (int *a, int n)
{
std::random_device rd; /* random seed */
std::mt19937 gen(rd()); /* standard mersenne_twister_engine */
std::uniform_int_distribution<> dist(0, NNODES - 1); /* distribution 0, 15 */
int i, tmp;
while (n-- > 1) {
i = dist(gen);
tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
}
/*
* list structs and functions
*/
struct dlist_node { /* list node */
int data;
struct dlist_node *prev, *next;
};
struct dlist { /* list wrapper with head & tail pointers */
dlist_node *head, *tail;
};
/** create new node initialize all members */
dlist_node *createnode (int v)
{
dlist_node *node = new dlist_node; /* allocate node */
if (!node) /* validate allocation (and use try/catch) */
return nullptr;
node->data = v; /* initialize members values */
node->prev = node->next = nullptr;
return node; /* return new node */
}
/** add node at end of list, update tail to end */
dlist_node *add (dlist *l, int v)
{
dlist_node *node = createnode (v); /* allocate node, initialize data */
if (!node) /* validate allocation */
return nullptr;
if (!l->head) /* if 1st node, node is head/tail */
l->head = l->tail = node;
else { /* otherwise */
node->prev = l->tail; /* set prev to tail */
l->tail->next = node; /* add at end, update tail pointer */
l->tail = node;
}
return node; /* return new node */
}
/** print all nodes in list */
bool prn (dlist *l)
{
if (!l->head) {
std::cout << "list-empty\n";
return false;
}
for (dlist_node *n = l->head; n; n = n->next)
std::cout << ' ' << n->data;
std::cout.put('\n');
return true;
}
/** print all nodes in list in reverse */
bool prnrev (dlist *l)
{
if (!l->tail) {
std::cout << "list-empty\n";
return true;
}
for (dlist_node *n = l->tail; n; n = n->prev)
std::cout << ' ' << n->data;
std::cout.put('\n');
return false;
}
/** delete node with value v from list (for loop) */
bool del_node (dlist *l, int v)
{
if (!l->head) {
std::cout << "list-empty\n";
return false;
}
dlist_node **ppn = &l->head; /* pointer to pointer */
dlist_node *pn = l->head; /* pointer to node */
for (; pn; ppn = &pn->next, pn = pn->next) {
if (pn->data == v) {
*ppn = pn->next; /* set node at address to next */
if (pn != l->tail) /* prev is next prev */
(*ppn)->prev = pn->prev;
else /* deleting tail, set tail to prev */
l->tail = pn->prev;
delete pn; /* free current */
pn = nullptr;
break;
}
}
return true;
}
/** delete all nodes in list */
void del_nodes (dlist *l)
{
dlist_node *n = l->head;
while (n) {
dlist_node *victim = n;
n = n->next;
delete victim;
}
l->head = l->tail = nullptr;
}
int main (void) {
dlist list = { nullptr, nullptr }; /* initialize list pointers nullptr */
int a[NNODES]; /* array to shuffle */
for (int i = 0; i < NNODES; i++) { /* fill array with NNODES int */
add (&list, i+1);
a[i] = i+1;
}
shuffle (a, NNODES); /* shuffle array for random removal */
prn (&list); /* print list forward */
prnrev (&list); /* print list reverse */
std::cout.put('\n');
for (int i = 0; i < NNODES; i++) { /* remove all nodes in random order */
std::cout << "deleting : " << a[i] << '\n';
del_node (&list, a[i]); /* delete node with random value a[i] */
if (prn (&list)) { /* print list forward if nodes remain */
prnrev (&list); /* print list reverse if nodes remain */
std::cout.put('\n'); /* tidy up with a '\n' */
}
}
}
Example Use/Output
$ ./bin/dlist_dlist_node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
deleting : 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
16 15 14 13 12 11 10 9 8 7 6 5 4 3 2
deleting : 9
2 3 4 5 6 7 8 10 11 12 13 14 15 16
16 15 14 13 12 11 10 8 7 6 5 4 3 2
deleting : 12
2 3 4 5 6 7 8 10 11 13 14 15 16
16 15 14 13 11 10 8 7 6 5 4 3 2
deleting : 7
2 3 4 5 6 8 10 11 13 14 15 16
16 15 14 13 11 10 8 6 5 4 3 2
deleting : 16
2 3 4 5 6 8 10 11 13 14 15
15 14 13 11 10 8 6 5 4 3 2
deleting : 5
2 3 4 6 8 10 11 13 14 15
15 14 13 11 10 8 6 4 3 2
deleting : 8
2 3 4 6 10 11 13 14 15
15 14 13 11 10 6 4 3 2
deleting : 14
2 3 4 6 10 11 13 15
15 13 11 10 6 4 3 2
deleting : 4
2 3 6 10 11 13 15
15 13 11 10 6 3 2
deleting : 3
2 6 10 11 13 15
15 13 11 10 6 2
deleting : 13
2 6 10 11 15
15 11 10 6 2
deleting : 2
6 10 11 15
15 11 10 6
deleting : 6
10 11 15
15 11 10
deleting : 10
11 15
15 11
deleting : 11
15
15
deleting : 15
list-empty
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/dlist_dlist_node
==17580== Memcheck, a memory error detector
==17580== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17580== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==17580== Command: ./bin/dlist_dlist_node
==17580==
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
deleting : 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 16
16 14 13 12 11 10 9 8 7 6 5 4 3 2 1
...
deleting : 16
12
12
deleting : 12
list-empty
==17580==
==17580== HEAP SUMMARY:
==17580== in use at exit: 0 bytes in 0 blocks
==17580== total heap usage: 19 allocs, 19 frees, 74,664 bytes allocated
==17580==
==17580== All heap blocks were freed -- no leaks are possible
==17580==
==17580== For counts of detected and suppressed errors, rerun with: -v
==17580== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

Breadth First Search fails to find destination that does exist

So I have been working on a Breadth First Search to get a path given a starting and ending node. However in some cases it seems to fail and not get the path, which I know is possible since a Depth First Search and visual inspection shows that it should exist.
I have an Adjacency Matrix:
1 2 3 4 5 6 7 8
1 0 20 25 20 0 0 0 0
2 20 0 5 0 30 0 0 0
3 25 5 0 13 8 21 0 0
4 20 0 13 0 0 17 0 0
5 0 30 8 0 0 33 0 0
6 0 0 21 17 33 0 0 0
7 0 0 0 0 0 0 0 10
8 0 0 0 0 0 0 10 0
Which has a graph as follows:
This is my function:
void Network::BFS(int src, int dest, vector<bool>& visited, vector<int>& path) {
// The Queue is the core for the BFS.
queue<int> Queue;
// Mark current node as visited.
visited[src] = true;
Queue.push(src);
// While queue is not empty.
while (!Queue.empty()) {
// Add node to path.
// Check if we have found the destination yet or not, if we have we do one last push to path and we're done!
if (Queue.front() == dest) {
return;
}
int top = Queue.front();
path.push_back(Queue.front());
// Pop off front.
Queue.pop();
// Iterate and process all none visited nodes.
for (int node = 0; node < amountOfNodes; node++) {
// Check if it is not visited already.
if (visited[node] == false && (adjMatrix[node * amountOfNodes + src] != 0)) {
Queue.push(node); // Add to end.
visited[node] = true;
}
}
}
}
Sample input and output:
(6, 3) -> Path is: 6
(1, 5) -> Path is: 1 2 3 4
As you can see, it does not compute the path properly at all. Where is my algorithm going wrong here, and how do I fix it?
BFS involves visiting adjacent nodes in a FIFO fashion. Once you reach a node, you put into the queue all its neighbours, unless they were already visited.
First off, there's a typo where you iterate over adjacent nodes. You want to traverse the top column, not the src one:
adjMatrix[node * amountOfNodes + top] != 0
// ~~^
Secondly, your current path implementation stores the visit order of nodes, not a path from the source to its destination. For the latter, you need to store the parent of each node, so that the final path can be restored by going from a child (destination) to its parent, grandparent, great-grandparent, ..., etc.
std::vector<int> parent(amountOfNodes, -1);
//...
if (visited[node] == false && (adjMatrix[node * amountOfNodes + top] != 0))
{
Queue.push(node); // Add to end.
visited[node] = true;
parent[node] = top;
}
Restoring the path is straightforward:
int u = dest;
do
{
std::cout << u << " ";
u = parent[u];
}
while (u != -1);
DEMO

Building a segment tree in c++

I am trying to build a segment tree in c++. Following the recursive function for the same:
int buildTree(int node,int start,int end,int tree[])
{
// printf("Node is: %d\n",node);
printf("start: %d\tend:%d\tnode:%d\t\n",start,end,node);
if ( start == end )
{
// printf("start: %d,node: %d,array[start] : %d\n",start,node,array[start] );
tree[node] = array[start];
return array[start];
}
else
{
int mid = ( start + end ) / 2;
buildTree(2 * node ,mid + 1,end,tree);
buildTree(2 * node + 1,start,mid,tree);
tree[node] = tree[ 2 * node ] + tree[ 2 * node + 1 ];
return tree[node];
}
}
The array is globally defined:
int array[] = {1,2,3,4,5};
The tree after following call:
int main(int argc, char const *argv[])
{
int tree[100];
buildTree(0,0,4,tree);
for (int i = 0; i < 9; ++i)
{
printf("%d : %d\n",i, tree[i]);
}
return 0;
}
gives the output:
start: 0 end:4 node:0
start: 3 end:4 node:0
start: 4 end:4 node:0
start: 3 end:3 node:1
start: 0 end:2 node:1
start: 2 end:2 node:2
start: 0 end:1 node:3
start: 1 end:1 node:6
start: 0 end:0 node:7
0 : 15
1 : 6
2 : 3
3 : 3
4 : 474810352
5 : 32766
6 : 2
7 : 1
8 : 0
So, the nodes 4 and 5 are never processed. Where am I doing wrong? I think I am having hard time with recursion.
I build a segment tree using somehow the same implementation.
You should call the function buildTree with initial node = 1.
buildTree(1,0,4,tree);
This should fix the error.
Also most of the segment tree implementation codes use the node (2*node) for the range (start -> mid) and the node (2*node+1) for the range(mid+1 -> end).
I think it's a matter of convention. However sticking to the convention makes it easier for you to debug your code, and easier for other programmers to understand it.
So you can rewrite the recursive calls as:
buildTree(2 * node ,start,mid,tree);
buildTree(2 * node + 1,mid+1,end,tree);
Instead of:
buildTree(2 * node ,mid + 1,end,tree);
buildTree(2 * node + 1,start,mid,tree);

next greater element in array

#include<iostream>
#include <stack>
using namespace std;
void printNextGreaterElement(int input[], int inputSize) {
stack<int> s;
s.push(input[0]);
for (int i = 1; i < inputSize; i++) {
while (!s.empty() && s.top() < input[i]) {
cout<<"Next greater element for "<<s.top()<<"\t = "<<input[i]<<"\n";
s.pop();
}
s.push(input[i]);
}
while (!s.empty()) {
int top = (int) s.top();
s.pop();
cout<<"Next greater element for "<<top<<"\t = null\n";
}
}
int main() {
int input[] = { 98, 23, 54, 12, 20, 7, 27 };
printNextGreaterElement(input, 7);
return 0;
}
I was learning about NGE in the array and came across this piece of code which I found on geeksforgeeks and other websites, but isn't this gives wrong output for the test case:
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6
Given an array, print the Next Greater Element (NGE) for every element. The Next greater Element for an element x is the first greater element on the right side of x in array.
Your code seems to be fine and gives the correct output of the input which you told gives wrong output is as following.
The input is as you mentioned
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6
The output is
Next greater element for 3 = 12
Next greater element for 10 = 12
Next greater element for 2 = 9
Next greater element for 4 = 9
Next greater element for 9 = 13
Next greater element for 12 = 13
Next greater element for 0 = 8
Next greater element for 8 = 11
Next greater element for 1 = 7
Next greater element for 5 = 6
Next greater element for 6 = null
Next greater element for 7 = null
Next greater element for 11 = null
Next greater element for 13 = null
For example, the second element in the array is 3, the next greater element in the array is 12 (Which is the output).
The explanation of the algorithm is not given here as it is well written in the post you mentioned.

how does Insert node function of Marching Cube works?

I am trying to understand MarchingCube algorithm:
My previous question was this. Now I am stuck in one function where the node ( which holds each grid of whole cube in linked list kind of structure) is inserted. I can understand the first few line of the code but, when I look at the code I find some part of the code redundant.
NODE *Insert(NODE *listset, NODE *tmpNode) {
1 NODE *temp;
2
3 if(listset == NULL) return tmpNode;
4 else {
5 tmpNode->next = listset->next;
6 listset->next = tmpNode;
7 return listset;
8 }
9 temp = listset;
10 if(temp->next == NULL) {
11 if(temp->depth > tmpNode->depth) temp->next = tmpNode;
12 else {
13 tmpNode->next = temp;
14 listset = tmpNode;
15 }
16 return listset;
17 }
18 while(temp->next != NULL) {
19 if(temp->next->depth > tmpNode->depth) temp = temp->next;
20 else {
21 tmpNode->next = temp->next;
22 temp->next = tmpNode;
23 return listset;
24 }
25 }
26 temp->next = tmpNode;
27 return listset;
}
In this function from 1 to 8 perfectly makes sense ( its just inserting new node to its end).
How could code ever reach after that point (I mean code from 9-27) ?? Is it even necessary??
Can anyone please explain what is going in the part 9-27.