c++ use of *& as parameter (Pointer fun, tertiary tree method) - c++

I'm trying to write a method which adds a key-value pair to a tertiary tree, but I'm obviously doing something wrong as I get a segfault whenever I reach the marked code
void Tree::add(int k, Node *&r)
{
cout<<"add"<<endl;
if(r==NULL){
r = new Node(k);
//check(heap area);
}
begin problem code
else if(r->keyCount == 1){
cout<<"adding second key";
if(r->getKey() < k){
Node * temp = new Node(r->getKey(),k,r->data[0],0);
delete r;
r = temp;
r->keyCount++;
cout<<"test"<<endl;
}
else
{
Node * temp = new Node(k,r->getKey(),0,r->data[0]);
delete r;
r = temp;
r->keyCount++;
cout<<"test"<<endl;
}
end code
}
else if(k < r->getKey())
{
cout<<"left"<<endl;
add(k,r->child[Node::L]);
}
else if(r->keyCount > 1 && k < r->getKey(1))
{
cout<<"middle"<<endl;
add(k,r->child[Node::M]);
}
else if(r->keyCount > 1 && k > r->getKey(1))
{
cout<<"right"<<endl;
add(k,r->child[Node::R]);
}
else
r = new Node(k);
}
What I'm trying to do is, in the case that there is only 1 out of the 2 keys used in this particular node, replace the current node with a new node which has the keys in the appropriate places (lesser val in key[0], greater val in key[1])
How do I do this properly?
My code apparently deletes both the address AND pointer for the old node, but doesn't properly reassign the pointer to the new node.
EDIT
updated code. the output is as follows:
% p4
Enter pairs consisting of an int and a double. I create a
ternary tree, keeping the data in order, by int. Finish entering
data by pressing ^d
2 2
add
Entering the pair: 2, 2
1 1
add
adding second key to current node
test
Entering the pair: 1, 1
-1 -1
add
left
add
Entering the pair: -1, -1
3 3
add
right
Segmentation Fault
EDIT 2
Here's a link to a zip containing the entire project if you want to look at all the code: http://sdrv.ms/WSrLfv
EDIT 3
More error data - output from gdb on crash
Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=#0x8047554) at testTree.cc:26
26 x[k]=d;
Current language: auto; currently c++
EDIT 4
stepping through gdb to the segfault:
Breakpoint 1, Tree::add (this=0x8047554, k=3, r=#0x8047554) at tree.cc:58
58 cout<<"add"<<endl;
(gdb) n
add
61 if(r==NULL){
(gdb) n
65 else if(r->keyCount == 1){
(gdb) n
87 else if(k < r->getKey())
(gdb) n
92 else if(r->keyCount > 1 && k < r->getKey(1))
(gdb) n
97 else if(r->keyCount > 1 && k > r->getKey(1))
(gdb) n
99 cout<<"right"<<endl;
(gdb) n
right
100 add(k,r->child[Node::R]);
(gdb) n
Breakpoint 1, Tree::add (this=0x8047554, k=3, r=#0x806416c) at tree.cc:58
58 cout<<"add"<<endl;
(gdb) n
add
61 if(r==NULL){
(gdb) n
62 r = new Node(k);
(gdb) n
107 }
(gdb) n
107 }
(gdb) n
Tree::operator[] (this=0x8047554, index=3) at tree.cc:47
47 return *(locate(index,root)->data);
(gdb) n
48 }
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=#0x8047554) at testTree.cc:26
26 x[k]=d;
(gdb)

This should be working.
In response to your edit: I noticed something interesting in your ouput:
-1 -1
add
left
add
Entering the pair: -1, -1
Notice how it says "left" and then it says "add" afterward because of the recursive call. However, in the input that crashes the program you don't see "add" after:
3 3
add
right
Segmentation Fault
If you look at your Tree::locate function:
Node * Tree::locate(int k, Node *rt) const
{
if(rt==NULL)
return rt;
if(k==rt->getKey())
return rt;
if(rt->keyCount>1 && k==rt->getKey(1))
return rt;
if(k < rt->getKey())
{
return locate(k,rt->child[Node::L]);
}
else if(rt->keyCount>1 && k < rt->getKey(1))
{
return locate(k,rt->child[Node::M]);
}
else if(rt->keyCount>1 && k<rt->getKey(1))
{
return locate(k,rt->child[Node::R]);
}
else
return NULL;
}
This line:
else if(rt->keyCount>1 && k<rt->getKey(1))
is the same condition as the previous one, so it is being skipped completely.

Related

C++ Variable mysteriously changed after calling unrelated function

I have the following code for a board game program that I am making. The function "copyMap" simply copies the contents of the first array map to the second array map_copy. In the function "solver", I have a loop that iterates over the game grid, and for each cell, call copyMap.
The issue is, when solver is called, it runs for 1 iteration then promptly crashes the program. Moreover, the iterators, x_pos and y_pos, which are supposed to start at 0 and 0, gets changed to 2 and 5 after calling copyMap and before the program crashes.
void copyMap(int map[][WIDTH], int map_copy[][WIDTH], int rows_to_copy) {
// copy the contents of the first rows_to_copy rows of map to map_copy
for( int i = 0 ; i < rows_to_copy ; i++ ) {
for( int j = 0 ; j < WIDTH ; j++ ) {
map_copy[i][j] = map[i][j];
cout<<i<<" "<<j<<endl;
}
}
}
int solver(int map[][WIDTH]) {
int map_copy[HEIGHT][WIDTH];
for(int x_pos = 0 ; x_pos < HEIGHT ; x_pos++ ) {
for(int y_pos = 0 ; y_pos < WIDTH ; y_pos++ ) {
copyMap(map, map_copy, MAX_ROWS);
cout<<x_pos<<" "<<y_pos<<endl;
}
}
}
This is the console output: (For the first iteration of the loop)
0 0
0 1
0 2
...
81 8
2 5
The game grid has 81 rows and 9 columns, so copyMap prints 0 0, 0 1, ..., 81 8.
Then, solver prints 2 5. However, the iterators are still supposed to be 0 0.
The iterators are not passed to the function copyMap at all. Why are their values being changed, and why is my program crashing?
I would appreciate any help on this issue, thank you.
Copymap iterates through each element. I don't think you need to call it inside a nested loop inside solver. You should take it outside of the loop and set a breakpoint inside the loop to watch x_pos and y_pos.
Solved, turns out map has 81 rows and 9 columns but map_copy only has 9 rows and 9 columns, so copyMap tried to access out-of-bounds memory locations.

Segmentation Fault when popping from a stack

Anyone can help me with finding out the error with this code? This is for a hackerrank question MAXIMUM ELEMENT. For the case 2, the line "maxes.pop()" keeps giving me segmentation fault. Commenting that line out actually allows the code to compile.
QUESTION:
You have an empty sequence, and you will be given queries. Each query is one of these three types:
1 x -Push the element x into the stack.
2 -Delete the element present at the top of the stack.
3 -Print the maximum element in the stack.
Function Description
Complete the getMax function in the editor below.
getMax has the following parameters:
string operations[n]: operations as strings
Returns
int[]: the answers to each type 3 query
Input Format
The first line of input contains an integer, . The next lines each contain an above mentioned query.
Constraints
Constraints
All queries are valid.
Sample Input
STDIN Function
----- --------
10 operations[] size n = 10
1 97 operations = ['1 97', '2', '1 20', ....]
2
1 20
2
1 26
1 20
2
3
1 91
3
Sample Output
26
91
vector<int> getMax(vector<string> operations) {
stack<int> nums;
stack<int> maxes;
vector<int> maxnums;
int max = INT_MIN;
//int top = -1;
for(long unsigned int i=0; i<operations.size(); i++){
switch(operations[i][0]){
case('1'):
cout<<"Operation 1"<<endl;
nums.push(stoi(operations[i].substr(2)));
if(nums.top() > max){
max = nums.top();
maxes.push(max);
}
break;
case('2'):
cout<<"Operation 2"<<endl;
if(max==nums.top()){
//cout<<"top element in maxes"<<maxes.top()<<endl;
maxes.pop();
max = maxes.top();
}
nums.pop();
break;
case('3'):
cout<<"Operation 3"<<endl;
maxnums.push_back(maxes.top());
break;
}
}
return maxnums;
}
Consider the following input sequence:
1 1 // push 1. Pushes 1 into nums and maxes
1 1 // push 1. Pushes 1 into nums, but not into maxes, since max = 1.
3 // delete top stack element
3 // delete top stack element
Before processing the first 3 line, your state will be this:
nums = {1, 1}
maxes = {1}
max = 1
Now, on the first pop, everything will be fine, so after the first pop, you will end up with this state:
nums = {1}
maxes = {}
max = 1
However, on on the second pop, max == nums.top() is still true, so you pop from your maxes stack, which is already empty. That is why it gives you the segmentation fault.

Construct Binary Tree from Parent Array test case failing

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];
}

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

Error in Implementation of Dijkstra's Algorithm

I am trying to attempt Dijkstra's with an Adjacency list, I can't figure out why I'm failing the test cases.
Node * n = list[source].head;
while(n)
{
q.push(n);
v[n->b] = n->w;
n = n->next;
}
while(!q.empty())
{
n = q.front();
i = n->b;
o = list[i].head;
q.pop();
while(o)
{
if(!v[o->b])
{
q.push(o);
v[o->b] = v[i] + o->w;
}
else if(v[o->b] > v[i] + o->w)
{
v[o->b] = v[i] + o->w;
}
o = o->next;
}
}
i = 0;
while(i < vertices)
{
if(i != node)
printf("%d ", v[i] ? v[i] : -1);
i++;
}
cout<<"\n";
I am passing trivial test cases.
Example Input: (x y w),
1 2 3,
1 3 4,
1 4 5,
3 5 101,
Source is 1.
Output:
3 4 5 5
Example 2:
1 2 24
1 4 20
3 1 3
4 3 12
Source is 1.
Output: 24 3 15
However, I am failing the more sophisticated test cases.
It seems you are confusing the two arrays - one for which vertex is already visited, and one for the optimal special distances(i.e. optimal distance to the vertices found so far). Let's denote the visited array with v and the optimal distance array with dist.
In this statement:
if(v[o->b] > v[i] + o->w)
You need to be using dist instead of v.
After you pop a node you need to check if it is visited. If it is visited, continue on to the next node. Otherwise mark it as visited and execute the remaining logic.