Insertion at end of linked list using recursion vs Iteration - c++

The function to insert at end of linked list using recursion looks something like this
// Main..
for(int i=0;i<n;i++){
cin>>x;
insert(head,x);
}
void insert(struct node*&h,int x){
if(h==NULL){
h=new node(x);
return;
}
insert(h->next,x);
}
But if I am doing same with iteration it doesn't work the same way,Its making only one node.
void insert(struct node* &h,int x){
if(h==NULL){
h=new node(x);
return;
}
struct node* go=h;
while(go){ //At (go==NULL) it should point to next of last node
go=go->next; // I know it should be go->next!=NULL condition.
}
go=new node(x);//Assigning next of last to new node.
}
I am having serious mental blockage.Can anyone please help why it doesn't work ? What should I do to make it work ?

The problem here is that you loop until go is not null. Okay, once fixed, you loop until go is null,
Then you just overwrite a null pointer by a new. But that doesn't link it to your existing list.
Do that instead:
void insert(struct node* &h,int x)
{
if(h==NULL)
{
h=new node(x);
return;
}
struct node* go=h;
// move until last element
while(go->next)
{
go=go->next;
}
// create a node at the end
go->next=new node(x);//Assigning next of last to new node.
}
At first iteration, go is guaranteed to be non-null (checked by first if condition).
Just check for the first next element to be null, and insert your new node here.

Related

How to delete from the last node in a linked list to a specific node in that list using recursion

So i am trying to delete from a specific node in a linked list but the problem doesn't come from deleting from the node to end ,it comes from trying to delete from the last node to a specific node while trying to use a recursion.
This is what I currently have (deleting from the node to last node)
void rLL<T> :: recursiveDelete(item<T> * node)
{
if (node != nullptr)
{
item<T> * nodeptr = node -> next;
delete node;
size--;
recursiveDelete(nodeptr);
}
}
Now I have to try and switch it around.And I have no idea how to do that.
This is for a school project so please ,if possible, try to keep it simple.
edit:Let's say the list consist of 1,2,3,4,5,6,7 and node 5 was put in to the parameter node then 7 ,6 ,5 should be deleted in that specific order (to clear things up a bit)
The answer to your question is to simply perform the recursive call before calling delete.
However, even if you were able to delete the specified node without failure, the code you presented would still have a major flaw - it does not update the next field of the node prior to the specified node, so you would end up leaving the list in an invalid state, as that prior node would become the new tail node but have a non-null next pointer that does not terminate the list properly.
For a single-linked list, you would have to iterate from the front of the list in order to discover that prior node to update. But once you reach the specified node, and know its previous node, then you can use a recursive algorithm for the rest of the list, eg:
template<typename T>
void rLL<T>::recursiveDelete(item<T> *node, item<T> *previous)
{
if (!node) return;
recursiveDelete(node->next, node);
if (previous) previous->next = nullptr;
--size;
delete node;
}
void rLL<T>::deleteToEnd(item<T> *startNode)
{
if (!startNode) return;
item<T> *node = head;
item<T> *previous = nullptr;
while (node)
{
if (node == startNode)
{
recursiveDelete(node, previous);
return;
}
previous = node;
node = node->next;
}
}
Live Demo
That being said, a double-linked list is better suited for this task, as you don't need to iterate from the front of the list at all, you can start right at the specified node, eg:
void rLL<T>::deleteToEnd(item<T> *startNode)
{
if (!startNode) return;
deleteToEnd(startNode->next);
item<T> *previous = startNode->previous;
if (previous) previous->next = nullptr;
if (head == startNode) head = nullptr;
tail = previous;
--size;
delete startNode;
}
Live Demo
If I understand this correctly, you want to delete a node that points to your specific node. If I were doing this I would have 2 nodes, currentNode and prevNode. When you iterate forward you move both of them and that way when currentNode meets the specifications, you can delete prevNode. If I don't understand the question right let me know.

Linked list concepts

Value of node in *node=*(node->next), if node is the last element in linked list?
Value of node would be NULL or not?
Given a singly linked list consisting of N nodes. The task is to remove duplicates (nodes with duplicate values) from the given list (if exists).
Note: Try not to use extra space. Expected time complexity is O(N). The nodes are arranged in a sorted way.
This solution didn't work for test case 2 2 2 2 2 (five nodes with equal values).
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
*t2=*(t2->next);
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
This worked:
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
if(t2->next==NULL)
{
t1->next=NULL;
t2=NULL;
}
else
{
*t2=*(t2->next);
}
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
Normally I wouldn't post the full code for something that is clearly homework but I wasn't sure how to properly articulate all of the points. I also haven't compiled and ran this because I didn't want to create my own Node class.
First we can talk about the algorithm. If your singly linked list is already sorted and NULL terminated then essentially we have a current node pointing to a node in the list and a travel node (nextNode) that walks down the list. The main thing we need to make sure we do is update the pointers to point to the next node once we've found a non-duplicate.
In the code below I've also added NULL checks which is incredibly important. Get in the habit of knowing exactly which state your variables could be in as it is easy to accidentally call a method on a null pointer which would cause the program to crash.
Node* removeDuplicates(Node* root)
{
// Check that root isn't null before checking that its next pointer is also not NULL
if (root == NULL || root->next == NULL)
return root;
// Set up our current node and the travel node
Node* currentNode = root;
Node* nextNode = root->next;
// Until we've reached the end of the singly linked list
while (nextNode != NULL)
{
// Find the next node that isn't a duplicate
// Also check that we don't reach the end of the list
while (nextNode->data == currentNode->data && nextNode != NULL)
nextNode = nextNode.next;
// Update the current node's next pointer to point to the travel node
currentNode->next = nextNode;
// Update the current node to its next for the next iteration
currentNode = nextNode;
// Update the next node being careful to check for NULL
nextNode = nextNode == NULL ? NULL : nextNode->next;
}
return root;
}
This is not the only way to handle this problem. By reorganizing when you do certain checks and associations you can eliminate some of the NULL checks or make the program more clear. This is just one possible solution.

Segmentation fault (core dumped) - Threaded Binary Search Tree

I keep getting the following error : Segmentation fault (core dumped) . I found out the line of code that is causing the problem ( marked with a comment inside of the program) . Please tell me why this error is happening and how to fix it.
I've tried to dry run my code (on paper ) and see no logical errors (from my understanding).
I have only recently got into coding and stackoverflow please guide me through how I can further improve my question , as well as my code . Thanks !
class tree
{
struct node // Creates a node for a tree
{
int data;
bool rbit,lbit; // rbit/lbit= defines if right/left child of root is present or not
node *left,*right;
};
public:
node *head,*root;
tree() // constructor initializes root and head
{
root=NULL;
head=createnode(10000);
}
node *createnode(int value)
{// Allocates memory for a node then initializes node with given value and returns that node
node *temp=new node ;
temp->data=value;
temp->lbit=0;
temp->rbit=0;
temp->left=NULL;
temp->right=NULL;
return temp;
}
void insert(node *temp,int value) // Creates binary search tree node by node
{
if(root==NULL) // Checking if tree is empty
{
root=createnode(value); //Root now points to new memory location
head->left=root;
head->lbit=1;
root->left=head;//this line gives the segmentation fault (what i thought before correction)
}
}
void inorder(node *root) // Inorder traversal of tree (this function is logically incorrect)
{
if(root==NULL)
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
void getdata()//Accepts data , creates a node through insert() , displays result through inorder()
{
int data;
cout<<"Enter data"<<endl;
cin>>data;
insert(root,data);
inorder(root);
}
/*void inorder(node *root) // Working inorder code
{
if(root->lbit==1)
inorder(root->left);
cout<<root->data<<"\t";
if(root->rbit==1)
inorder(root->right);
}*/
};
int main()
{
tree t; // Tree Object
t.getdata(); // Calling getdata
return 0;
}
I think the comments section largely reflects a miscommunication. It's easy to believe that you are experiencing a crash ON that particular line.
This is not actually the case. Instead what you have done is created a loop in your tree which leads to infinite recursion by the inorder function. That causes a stack overflow which segfaults -- this would have been extremely easy to spot if you had just run your program with a debugger (such as gdb) attached.
temp = createnode(value);
if(root == NULL)
{
root = temp;
head->left = root;
head->lbit = 1;
temp->left = head;
}
Look at the loop you have just created:
head->left points to root
root->left == temp->left, which points to head
An inorder traversal will now visit:
root
head
root
head
root
head
...
Since it never gets to the end of the left-branch, the function never outputs anything before overflowing the stack and crashing.
So no, your code is not logically correct. There's a fundamental design flaw in it. You need to rethink what you are storing in your tree and why.
From the code,
root=temp; //Root now points to temp
head->left=root;
head->lbit=1;
temp->left=head;// this line gives the segmentation fault
root is not pointing to temp. temp(pointer) is assigned to root(pointer).
head's left pointer is root, and temp's left is head (which means root's left is head). so in the function "inorder",
void inorder(node *root) // Inorder traversal of tree
{
if(root==NULL) <<<<<<
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
the argument node *root (left) is never NULL and the function never return.
There's not enough information on exactly how this should work (what is node.lbit for example).
The question's insert() function will not work. It's passing in a value which is immediately overwritten (among other issues). There's no explanation of what tree.head is for, so it's ignored. The fields node.lbit and node.rbit look to be superfluous flags of node.left != NULL (similarly for right). These are omitted too. The insert() is also not creating the tree properly.
void insert(int value) // Insert a value into the tree (at branch)
{
// Create a new node to insert
struct node *temp = createnode(value);
if (root == NULL) // Checking if tree is empty
{
root = temp; //Root now points to temp
}
else
{
insertAtBranch(root, temp);
}
}
// recursively find the leaf-node at which to insert the new node
void insertAtBranch(node *branch, node *new_node)
{
// to create a BST, less-than go left
if (new_node->value <= branch->value)
{
if (branch->left == NULL)
branch->left = new_node; // There's no left-branch, so it's the node
else
insertAtBranch(branch->left, new_node); // go deeper to find insertion point
}
else // greater-than go right
{
if (branch->right == NULL)
branch->right = new_node;
else
insertAtBranch(branch->right, new_node);
}
}
Imagine how a binary tree works. New nodes are only ever inserted at the edges. So you look at a given node, and decide if this new-node is less or grater than the one you're looking at (unless the tree is empty, of course).
Say the new-node.value is less than the branch-node.value, you want to branch left. Still with the same node, if it doesn't have a left-branch (node.left == NULL), the new node is the left branch. Otherwise you need to travel down the left-branch and check again.
I would have made node a class, and used a constructor to at least set the default properties and value. But that's not a big deal.

How pop is working in stack using linked list?

Here in the pop function, after top is assigned to temp, its written top=top->link, but how is top=top->link making it point to its back node?
top=top->link is meant to move forward and point to the node to its front and here it should be NULL.
EDIT: cout added in pop. Now to make question more specific, how cout<<top->data will print 32 ? it should be pointing to NULL.
#include<iostream>
using namespace std;
class stack_ll{
private:
struct node{
int data;
node *link;
}*top;
public:
stack_ll()
{
top=NULL;
}
void push(int);
void pop();
void display();
~stack_ll()
{
if(top==NULL)
return;
node *temp;
while(top!=NULL)
{
temp=top;
top=top->link;
delete temp;
}
}
};
void stack_ll::push(int num)
{
node *temp;
temp=new node;
if(temp==NULL) {
cout<<"stack is full"<<endl;
return;
}
temp->data=num;
temp->link=top;
top=temp;
}
void stack_ll::pop(){
if(top==NULL)
{
cout<<"stack is empty"<<endl;
return;
}
node * temp;
int item;
temp=top;
item=temp->data;
top=top->link;
cout<<top->data<<endl;
delete temp;
}
int main()
{
stack_ll l1;
l1.push(5);
l1.push(56);
l1.push(32);
l1.push(34);
l1.pop();
l1.push(23);
l1.pop();
}
You are right. Pop here will remove the first object and will now have top as NULL even though there are some objects in the stack. What you should do to fix that, is change the link direction - meaning each object will point to the lower object. In that case, when removing the top, you will be able to retrieve the next object, that is lower in the stack
change:
temp->data=num;
temp->link=top;
top=temp;
to:
temp->data=num;
top->link=temp;
top=temp;
and add a special case for an empty stack where top->link=temp; will not be legal like:
if(top==NULL){
temp->data=num;
top=temp;
top->link=NULL;
}
EDIT:
your logic should be like this:
empty stack has only a null_ptr (top)
push: if stack is empty - top is now new element and it's link is null_ptr, else - top's link is now new element, top becomes new element and new element's link is null_ptr
pop: if stack is empty do nothing, else - print top's data, save top as temp, top becomes top's link (the lower element in stack), print temp's data and delete temp
This implementation is correct. You don't need to change anything.
Working of push
When we try to add an element is this stack, we create a new node and make it head of the link list. Hence the last element added will always be head of the link list.
Working of of Pop
When we try to pop an element we just do top- = top->link. This means we just changed the head node to the previous element which was added in the stack.

Segfault-Iterative insert in BST

I'm trying to write a code to insert a new element in the BST iteratively. When I try to execute the code, I get a segfault. Can someone look over the code and help me correct it?
bool insert2(int item)
{
BstNode *parent;
BstNode *root=new BstNode;
cout<<root->data;
cout<<"\n";
BstNode *ptr;
int ctr=0;
//cout<<root->data;
if (root==NULL)
{
BstNode *temp=new BstNode;
temp->data=item;
temp->left=NULL;
temp->right=NULL;
root=temp;
//cout<<root->data;
return true;
}
else
{
ptr=root;
while (ptr!=NULL)
{
ctr=ctr+1;
cout<<ctr;
if (ptr->data==item)
{
cout<<ptr->data;
return false;
}
if (item < ptr->data)
{
parent=ptr;
ptr=ptr->left;
}
else
{
parent=ptr;
ptr=ptr->right;
}
}
BstNode *add=new BstNode;
add->data = item;
add->left= NULL;
add->right= NULL;
return true;
}
}
on editing out the root-> data part, the code would go into the first if block and return true, which makes me guess that my problem lies somewhere in the deceleration.
There are a number of things that you are doing wrong. First of all, as PaulMcKenzie has pointed out, you should not be creating the root at the beginning of the function. If the BST does not start out empty, the root already exists and you do not want to create a new one. Instead, the root should be a public variable (which would only allow you to have one BST), or the function should take a pointer to the root as one of the parameters. It certainly does not make sense that you create the root and then test it to see if it is NULL. Unless you ran out of memory, it would not be NULL right after you created it.
Another problem with your code is that after you find the appropriate location in the BST, you create the new node, but do not attach it to the tree. Instead, you might want to insert the following lines after you initialize add:
if(item < parent->data)
parent->left = add;
else
parent->right = add;
As far as the fact that you get a seg-fault every time you call the function, it is probably because, when you declare root, you do not initialize its right and left pointers to NULL. Therefore, the while loop does not stop when it reaches root->left or root->right. When you try to deference ptr later in the loop, you are deferencing an uninitialized pointer, resulting in a seg-fault.