C++ Tree node recursion - c++

How does the recursion work for the function provided?
struct tree
{
int value;
struct tree* left;
struct tree* right;
};
void recursion(tree* head)
{
if (head != NULL)
{
recursion(head->left);
cout << head->value << endl;
recursion(head->right);
}
}
int main()
{
tree* head;
tree* newNode = new(struct tree);
newNode->value = 2;
newNode->left = NULL;
newNode->right = NULL;
head = newNode;
newNode = new(struct tree);
newNode->value = 1;
newNode->left = NULL;
newNode->right = NULL;
head->left = newNode;
newNode = new(struct tree);
newNode->value = 3;
newNode->left = NULL;
newNode->right = NULL;
head->right = newNode;
recursion(head);
return 0;
}
Traversing through the tree node with the recursion() function, during recursion(head->left) inside the function, when it finally hits NULL does the end of that state of recursion become 'head->value' and use the cout << head->value << endl; line of code to print 1? Vice versa for recursion(head->right)? I'm having a hard time understanding how exactly the last left node is being printed granted i'm only using cout for the head->value node.

Using a debugger makes it easier to learn how code is executed as it follows the exact execution order. This when threading is not taken into account.
Sometimes, with difficult patterns, it helps to just draw it on paper. It will make is very visible for what is going on.
The graph below starts with your first created struct with newNode->value = 2;
The green arrows show the order of execution.
out 1, out 2 and out 3 are the head->value in your function.

Related

problem in deleting a node in algorithm to reverse a linked list c++

I'm solving problems in algorithms and I have to reverse a forward linked list.
Here is my code:
For a node:
struct Node{
int value;
Node* next;
};
For reversing, here is the algorithm I made:
Node* reverse(Node* head){
Node* node = head->next;
Node* sentry = new Node;
sentry->next = head;
while(node != nullptr){
head->next = node->next;
node->next = sentry->next;
sentry->next = node;
node = head->next;
}
return sentry;
}
Here is a print function to test:
void print(Node* head){
Node* node = head->next;
while(node != nullptr){
std::cout << node->value << '-';
node = node->next;
}
}
The problem is that the reversed list has as last node the head, so when I try to do: delete head; before return sentry; to delete that node I get Core Dump error. I know that I can just search in internet a method to reverse the list, but I want to understand why this happens, why can't I just delete the head node.
Edit: here's is the code deleting the head:
Node* reverse(Node* head){
Node* node = head->next;
Node* sentry = new Node;
sentry->next = head;
while(node != nullptr){
head->next = node->next;
node->next = sentry->next;
sentry->next = node;
node = head->next;
}
delete head; // head = nullptr; also doesn't work.
return sentry;
}
Here is a main function to test:
int main(){
Node* node5 = new Node{5,nullptr};
Node* node4 = new Node{4,node5};
Node* node3 = new Node{3,node4};
Node* node2 = new Node{2,node3};
Node* node1 = new Node{1,node2};
Node* head = new Node;
head->next = node1;
head->value;
print(reverse(head));
return 0;
}
Let's look at your code:
void print(Node* head){
Node* node = head->next;
while(node != nullptr){
std::cout << node->value << '-';
node = node->next;
}
}
This code will never print the head. Slightly better code would be:
void print(Node* head) {
for (Node * node = head; node != nullptr; node = node->next) {
std::cout << node->value << '-';
}
}
Now, from your code in main it looks like you don't expect to print the head -- you're using it as a pointer. That would be odd. You basically have an extra, empty node just hanging out. So your main could do this:
int main(){
Node* node5 = new Node{5,nullptr};
Node* node4 = new Node{4,node5};
Node* node3 = new Node{3,node4};
Node* node2 = new Node{2,node3};
Node* head = new Node{1,node2};
std::cout << "Original version: ";
print(head);
std::cout << "\n\n";
std::cout << "Reversed version: ";
print(reverse(head));
std::cout << "\n";
return 0;
}
Finally, your reverse method is flat out broken. You shouldn't have to allocate anything.
Linked lists and other forms of linked structures (like trees) can be very confusing. At this stage in your learning, drawing pictures REALLY helps. I did so for years and years, and I still do when it gets complicated.
Note * reverse(Node *head) {
Node * prev = nullptr;
while (head != nullptr) {
Node * nextNode = head->next;
head->next = prev;
prev = head;
head = nextNode;
}
return prev;
}
There's probably a more elegant way to do this, but I don't want to think that hard :-)
Think about what this does. It keeps track of the previous node. The first time through the loop, there is no previous node. After that, the previous node is the old head, then old head->next, et cetera.
At each node, it sets the next pointer to this previous node. So head->next becomes nullptr (it's the new end of the list). Old Head->next->next comes old head, et cetera.
I haven't tested this code.
This is my final copy with a compile and output:
^ make Foo && Foo
g++ Foo.cpp -o Foo
Original: 1 : 2 : 3 : 4 : 5 :
Reversed: 5 : 4 : 3 : 2 : 1 :
^ cat Foo.cpp
#include <iostream>
struct Node{
Node (int v): value(v) {}
int value = 0;
Node* next = nullptr;
};
void print(Node* head);
Node * reverse(Node* head);
int main() {
// This part is gross, but I was in a hurry
Node * head = new Node(1);
head->next = new Node(2);
head->next->next = new Node(3);
head->next->next->next = new Node(4);
head->next->next->next->next = new Node(5);
std::cout << "Original: ";
print(head);
std::cout << "\n\nReversed: ";
print(reverse(head));
std::cout << "\n";
}
void print(Node* head) {
for (Node * node = head; node != nullptr; node = node->next) {
std::cout << node->value << " : ";
}
}
Node * reverse(Node *head) {
Node * prev = nullptr;
while (head != nullptr) {
Node * nextNode = head->next;
head->next = prev;
prev = head;
head = nextNode;
}
return prev;
}

Why a simple linked list reverse function always return the last node instead of the first

I have written a simple reverse function for the linked list, shown below:
typedef struct _NODE
{
int data;
_NODE *next;
}NODE;
void print(NODE *head)
{
NODE *start;
start = head;
while (start)
{
printf("%d ", start->data);
start = start->next;
}
}
NODE* reverse(NODE *head)
{
NODE *prev = NULL;
NODE *curr = head;
while (curr)
{
NODE *temp = curr->next;
curr->next = prev;
prev = curr;
curr = temp;
}
head = prev;
return head;
}
int main()
{
NODE *head = new NODE;
NODE *node1 = new NODE;
NODE *node2 = new NODE;
head->data = 1;
node1->data = 2;
node2->data = 3;
head->next = node1;
node1->next = node2;
node2->next = NULL;
reverse(head);
print(head);
getchar();
delete head;
delete node1;
delete node2;
head = NULL;
node1 = NULL;
node2 = NULL;
return 1;
}
I found the output will always be 1. My question is why does the head pointer after the reverse function always point to the node with value 1. I have already assigned the previous pointer to the head pointer in the reverse function.
But if I change below, the output became correct.
reverse(head);
To
head = reverse(head);
Because the head variable in the reverse function is not the same variable as the head variable in the main function.
Assigning to the head variable in reverse does not change the value of the head variable in main.

The first element in the created list is always 0

I don't yet understand fully how linked lists and nodes in C/C++ work, but this is the function I use to add nodes to a list.
void AddNode(Node* head, int new_data)
{
Node* new_node = new Node();
Node *last = head;
new_node->data = new_data;
new_node->next = NULL;
if (head == NULL)
{
head = new_node;
return;
}
while (last->next != NULL)
{
last = last->next;
}
last->next = new_node;
}
The first element in the list will always be 0, what am I doing wrong?
In c++ , you must update
Node *last = head;
to
Node *& last = head;
In C, you must update
Node *last = head;
to
Node ** last = head;
I used the function AddNode as bellow:
Node* head = new Node();
AddNode(head, 1);
And i get the same problem like you.Because the first element will never change.There are two modify
(1) return the head
Node* AddNode(int new_data)
{
Node* head = NULL;
Node* new_node = new Node();
Node *last = head;
new_node->data = new_data;
cout << "-->" << new_node->data << endl;
new_node->next = NULL;
if (head == NULL)
{
head = new_node;
return head;
}
while (last->next != NULL)
{
last = last->next;
}
last->next = new_node;
return head;
}
use like this:
Node* head = AddNode(1);
(2)pass the head address,because you want to change it
void AddNode(Node** head, int new_data)
{
Node* new_node = new Node();
Node *last = *head;
new_node->data = new_data;
cout << "-->" << new_node->data << endl;
new_node->next = NULL;
if (*head == NULL)
{
*head = new_node;
return;
}
while (last->next != NULL)
{
last = last->next;
}
last->next = new_node;
}
use lie this:
Node* head = NULL;
AddNode(&head, 1);
Hope it's useful for you.

Getting " expected a ; " error message in C++

I am implementing Binary search tree in C++. I have written the following code but for some reason I get an error message that says:
expected a ;
I get above message when compiling the code.
Also I am new to C++ and I would appreciate a lot if I get some help on this one.
Some context to Binary Search Tree:
Binary search trees keep their keys in sorted order, so that lookup
and other operations can use the principle of binary search: when
looking for a key in a tree (or a place to insert a new key), they
traverse the tree from root to leaf, making comparisons to keys stored
in the nodes of the tree and deciding, on the basis of the comparison,
to continue searching in the left or right subtrees. On average, this
means that each comparison allows the operations to skip about half of
the tree, so that each lookup, insertion or deletion takes time
proportional to the logarithm of the number of items stored in the
tree. This is much better than the linear time required to find items
by key in an (unsorted) array, but slower than the corresponding
operations on hash tables.
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *left, *right, *parent;
};
Node* DeleteNode(Node *root, int data);
void find_min(Node *root);
void inorder(Node *x);
void Insert(Node *root, int data);
//delete a node
//search_tree
//insert a node
//temp->parent = NULL;
int main()
{
Node *root, *temp;
//node with 20
temp = new Node;
temp->data = 20;
temp->left = NULL;
temp->right = NULL;
root = temp;
//node with 10
temp = new Node;
temp->data = 10;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left = temp;
temp->parent = root;
//node with 30
temp = new Node;
temp->data = 30;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right = temp;
temp->parent = root;
//node with 25
temp = new Node;
temp->data = 25;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right->left = temp;
temp->parent = root->right;
//node with 40
temp = new Node;
temp->data = 40;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right->right = temp;
temp->parent = root->right;
//node with 2
temp = new Node;
temp->data = 2;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left->left = temp;
temp->parent = root->left;
//node with 15
temp = new Node;
temp->data = 15;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left->right = temp;
temp->parent = root->left;
find_min(root);
cout << "Printing numbers in order" << endl;
inorder(root);
cout << "printing in-order of the given root" << endl;
delete(root);
}
void find_min(Node *root)
{
Node *temp;
temp = root;
while (temp->left != NULL)
temp = temp->left;
cout << "min number is " << temp->data << endl;
}
void inorder(Node *x)
{
if (x != NULL)
{
inorder(x->left);
cout << x->data << endl;
inorder(x->right);
}
}
Node* DeleteNode(Node *root, int data)
{
if (root->data == NULL) {
return root;
}
// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
else if (data < root->data)
root->left = DeleteNode(root->left, data);
// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if (data > root->data)
root->right = DeleteNode(root->right, data);
// case 1: No child
else if (root->left == NULL & root->right == NULL)
delete root;
return root;
//data < root->data struct Node *temp = root;
// case 2: one child
if (root->left == NULL){
Node *temp = root;
root = root->right;
delete temp;
return root;
}
//
else if (root->right == NULL) {
Node *temp = root;
root = root->left;
delete temp;
return root;
}
// case 3: two child
else (root == root->right){
root->data = temp->data;
root->right = DeleteNode(root->right, temp->data);
return root;
}
}
This is your issue: else (root == root->right){. If you want to make that a condition, you'll need to use else if(root == root->right)
Note that per Godbolt, you have more errors even with that fix (they look simple to fix).

C++ Pointers, Linked List Confusion

I am trying to build a linked list in C++. My understanding is that the code I have created should create a node and then progressively link 4 more onto the end. Unfortunately, while I would expect to see the cout results as "12 123 1234 12345" I'm seeing "12 12 12 12" and in my main I am unable to traverse the list - it just crashes.
I have the following code:
struct listNode {
int val;
listNode* next;
};
int nodeCount = 0;
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
int main()
{
listNode* first = addToEnd(NULL);
addToEnd(first);
addToEnd(first);
addToEnd(first);
addToEnd(first);
cout<<"Third: "<<first->next->next->val;
}
Any help is appreciated, as I am at wit's end!
It is obvious that function addToEnd is wrong
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
Let's assume that the list already contains two nodes and consider the do-while loop inside the function. At first current_next != null so the following statement is executed
current = current->next;
Now current points to the second node. Its data member next is equal to NULL. So the condition of the loop
} while (current->next != NULL);
will be false and no iteration will be repeated. So we added nothing.
Also the function returns nothing if node is not equal to NULL.
Rewrite the function the following way
listNode* addToEnd( listNode* node )
{
listNode* newNode = new listNode { ++nodeCount, NULL };
if ( node == NULL) return newNode;
listNode* current = node;
while ( current->next != NULL ) current = current->next;
current->next = newNode;
return newNode;
// or
//return node;
}
Take into account that this statement
cout<<"Third: "<<first->next->next->val;
outputs only the value of the third node.
If you want to output all the list you should write
for ( listNode *current = first; current; current = current->next )
{
std::cout << current->val << ' ';
}
std::cout << std::endl;
By the way using my function you could write in main for example the following way:)
listNode* first;
addToEnd( addToEnd( addToEnd( addToEnd( first = addToEnd( NULL ) ) ) ) );
Use a for loop to get you to the last node instead of a while, and then assign the new node OUTSIDE of the loop. Trying to do it inside will result in an infinite loop (and make the code harder to read):
listNode* current;
for(current = node; current->next != NULL; current = current->next) ;
current->next = newNode;
You're also forgetting to return newNode at the end of the function.
You're falling off the end of a function with non-void return type. The fact that you don't use the return value does not make that ok.
6.6.3 in the Standard says that:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
There is no return statement just in case the if condition that checks if(node==null) fails..
Is it against the rules to use recursive functions in your question?
Why not do...
void addToEnd(listNode* node){
if(node == NULL){
*node = new listNode;
node->next = NULL;
node->val = ++nodeCount;
}else{
addToEnd(node->next);
}
return;
}
int main(){
listNode* first = NULL;
addToEnd(first); // 1
addToEnd(first); // 2
addToEnd(first); // 3
addToEnd(first); // 4
addToEnd(first); // Linked list is now 5 long
}
This is how I would have coded adding five nodes to a linked list that holds a node count. If anyone has advice it is welcome.
#include <iostream>
#include <cstdlib>
using namespace std;
struct listNode{
int val;
listNode* next;
};
listNode* addToEnd(listNode*, int);
int main()
{
listNode* first = NULL;
listNode* temp;
int nodeCount = 1;
for(int i = 0; i < 5; i++){
first = addToEnd(first, nodeCount);
nodeCount++;
}
temp = first;
while(temp){
cout << temp->val << ' ';
temp = temp->next;
}
temp = first;
//Deallocate memory
while(temp){ //could do memory deallocation while displaying
nodeToDelete = temp; //the value of nodeCount but wanted to illustrate
//both methods individually
temp = temp->next;
delete nodeToDelete;
}
first = NULL; //eliminate hanging pointer
return 0;
}
listNode* addToEnd(listNode* node, int nodeCount)
{
listNode* newNode = new (nothrow) listNode;
listNode* current = node;
if(newNode){
newNode->val = nodeCount;
newNode->next = NULL;
if (node == NULL)
node = newNode;
else{
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
}
else
cout << "error allocationg memory" << endl;
return node;
}