Linked List insertion issue - c++

I was trying out Linked List and I have a bit of problem with my insertNode1 function. This function is supposed to insert a new node after the inputted node by the user. The result doesn't show what I wanted to show. I wanted the number 5 to be after 3, but it doesn't show how I wanted it.
#include <iostream>
using namespace std;
class List {
struct node {
float data;
node* next;
};
node* head;
public:
void appendNode(float);
void insertNode(float);
void insertNode1(float,float);
void deleteNode(float);
void displayList();
List(){
head = NULL;
}
~List(){
node *nodePtr, *nextNode;
nodePtr = head;
while (nodePtr != NULL){
nextNode = nodePtr->next;
delete nodePtr;
nodePtr = nextNode;
}
}
};
void List::appendNode(float d)
{
node *newNode, *nodePtr;
newNode = new node;
newNode->data = d;
newNode->next = NULL;
if (!head){
head = newNode;
}
else {
nodePtr = head;
while (nodePtr->next){
nodePtr = nodePtr->next;
}
nodePtr->next = newNode;
}
}
void List::insertNode(float d){
node *newNode, *nodePtr, *prevNode=NULL;
newNode = new node;
newNode->data = d;
if (head== NULL)
{
head = newNode;
newNode->next = NULL;
}
else {
nodePtr = head;
while (nodePtr != NULL && nodePtr->data < d){
prevNode = nodePtr;
nodePtr = nodePtr->next;
}
if (prevNode == NULL){
head = newNode;
newNode->next = nodePtr;
}
else {
prevNode->next = newNode;
newNode->next = nodePtr;
}
}
}
void List::insertNode1(float p, float d){
node *newNode, *nodePtr, *selectedNode=NULL;
newNode = new node;
newNode->data = d;
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
if (head != NULL){
head = newNode;
newNode->next = NULL;
}
else {
while (nodePtr->next != NULL && nodePtr->data != p){
nodePtr = nodePtr->next;
}
if (selectedNode == NULL){
head = newNode;
selectedNode->next = NULL;
}
else {
selectedNode->next = newNode;
}
}
}
void List::deleteNode(float da){
node *nodePtr, *previousNode=NULL;
if (head == NULL){
return;
}
if (head ->data == da){
nodePtr = head->next;
delete head;
head = nodePtr;
}
else{
nodePtr = head;
while (nodePtr != NULL && nodePtr->data != da){
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
void List::displayList(){
node *nodePtr;
nodePtr = head;
while (nodePtr!= NULL){
cout << nodePtr->data << endl;
nodePtr = nodePtr->next;
}
}
int main(){
List lobj;
lobj.appendNode(3);
lobj.appendNode(6.4);
lobj.appendNode(4.5);
lobj.appendNode(7.8);
lobj.insertNode(1.5);
lobj.displayList();
cout << "after deleting and adding a new node" << endl;
lobj.deleteNode(6.4);
lobj.displayList();
lobj.insertNode1(3, 5);
lobj.displayList();
system("pause");
}

At the beginning of your void List::insertNode1(float p, float d) function:
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
Here, selectedNode points at the head of the list and you seem to overwrite the data of that node with the value of p, which I cannot help but feel is not what you meant to do.

There are a few issues inside List::insertNode1.
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
Here selectedNode points at head but then you set the first data value to p.
if (head != NULL){
head = newNode;
newNode->next = NULL;
}
This part only executes when head is not null. This means you get rid of the entire list every time this is run. This is why the last call to list::displayList only prints 5.
if (selectedNode == NULL){
head = newNode;
selectedNode->next = NULL;
}
Here selectedNode is NULL. first you set head to be a new node but this doesn't change selectedNode. If you ran this method on an empty list your program would segfault here. You should be setting the next of head or newNode to NULL here, not selectedNode.
else {
selectedNode->next = newNode;
}
Here selectedNode still points to head. You change nodePtr but this doesn't also change selectedNode.

Related

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.

C++ linked lists Remove and RemoveBack function

I was wondering how to create a linked list with a remove(int num) and removeback(int num)? using the same format as provided in prepend?
#include "ll.h"
LL::LL()
{
head = NULL;
}
void LL::prepend(int num)
{
node* newNode = new node;
newNode->val = val;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
}
else
{
newNode->next = head;
head = newNode;
newNode = NULL;
}
}
void LL::remove(int num)
{
}
void LL:removeBack (int num)
{
}
I think remove and removeBack would be the same function? Correct? Also how do I pass that value back
I assume that remove(int num) removes the first node that has the same value as num. I'll leave removeBack as an exercise for you :).
void LL:remove(int num) {
if (!head) {
return;
}
else if (head->val == num) {
node* temp = head;
head = head->next;
delete temp;
return;
}
node* second = head;
node* first = head->next;
// Iterate until we find the target, or reach the end
while (first && first->val != num) {
second = first;
first = first->next;
}
// At this point, first points to either nullptr or the target
if (first) {
second->next = first->next;
delete first;
}
}
What about searching for the node and then deleting the node with that value?
void LL:remove (int num){
ListNode *nodePtr, *previousNode;
if (!head) {
return;
}
else if (head->value == num)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
nodePtr=head;
while (nodePtr != NULL && nodePtr->value !=num){
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
previousNode->next = nodePtr->next;
delete nodePtr;
}
}

C++ Linked list print error

I don't understand why the display() func show me only the first member of the list. I think I did a mess with pointers, but I can't understand where. I have compared this to other linked list source and it seem that the function is written in the-good-way.
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
struct Node
{
int Data;
Node * next;
};
void initNode(struct Node *head,int n);
void AddNode(int n,Node* head);
void display(Node* head);
int main()
{
Node * head = new Node;
initNode(head,5);
display(head);
AddNode(10,head);
display(head);
AddNode(15,head);
display(head);
cin.get();
return 0;
}
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
}
void display(Node * head)
{
while(head)
{
cout << head->Data << " "<<endl;
head = head->next;
}
}
void initNode(struct Node *head,int n)
{
head->Data = n;
head->next = NULL;
}
Your AddNode method is over-complicated. Do something like this to add to the front:
Node *AddNode(int n, Node *head)
{
Node *newNode = new Node;
newNode->Data = n;
newNode->next = head;
return newNode;
}
Or to add to the end:
Node *AddNode(int n, Node *head)
{
Node *newNode = new Node;
newNode->Data = n;
newNode->next = NULL;
if(head == NULL) return newNode;
Node *current = head;
while(current->Next != NULL)
{
current = current->Next;
}
current->Next = newNode;
return head;
}
Doing AddNode this way you will not need initNode. Now you can just day:
Node *head = NULL;
head = AddNode(5, head);
head = AddNode(10, head);
head = AddNode(15, head);
display(head);
Also, you don't need to say struct Node in C++, it is only required in C.
Function AddNode has an infinite loop.
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
}
Let assume that you have only one element that is the head (after a call of initNode). And as the result head->next = NULL. So inside the body of the loop you make assignment
nextNode->next = node;
Now head->next is not equal to NULL. So after statement
nextNode = nextNode->next;
nextNode caontains the new element. As it is not equal to NULL then iteration of the loop will be repeated. Again for the new node its data member next is equal to NULL. And you add it to it itself.
Now you have no any element in the list that would have data member next equal to NULL. So you are unable to add new elements. The last element contains reference to itself.
You could write the function the following way
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while( nextNode -> next ) nextNode = nextNode->next;
nextNode->next = node;
}
But take into account that it is assumed that head is not equal to NULL. otherwise the function will be incorrect. I think that you should redesign you list.
In your AddNode function add a break in the if block.
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
break;
}
nextNode = nextNode->next;
}
}
Now it should add properly.
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
The problem is this block of code. When you find the end of the list (if nextNode->next == NULL) you need to break out of the loop. Try it with an example to convince yourself.
Each time you add a node you traverse from head to the end of the list
You can change it as follows
void AddNode(int n){
Node *node=new Node;
node->data=n;
node->next=NULL; //head is global
if(head==NULL){
t=head=n;
}
else{
t->next=n; //t is global
t=t->next;
}
}

How to make an intersection function with linked lists?

Here is the linked lists code, so how to make two different lists and display the intersection between them?
For example there is two linked lists called L1 and L2, so how to implement a function that displays the intersection of these two lists, like L1 has 1,2,3,4,5 and L2 has 11,3,4
so the result would be 3,4.
#include <iostream>
using namespace std;
#include "Node.h"
class DoublyLinkedList{
private:
Node* head;
Node* tail;
Node* list;
int elementCount;
public:
DoublyLinkedList(){
head = tail = list = NULL;
elementCount = 0;
}
void insertAtFront(int item){
elementCount++;
Node* newNode;
newNode = new Node;
newNode->data = item;
list = head;
if(list == NULL) {
head = newNode;
tail = head;
return;
}
newNode->next = head;
head->prev = newNode;
head = newNode;
head->prev = tail;
tail->next = head;
}
void insertAtEnd(int item){
elementCount++;
Node* newNode;
newNode = new Node;
newNode->data = item;
list = head;
if(list == NULL){
head = newNode;
tail = head;
return;
}
tail->next = newNode;
newNode->prev = tail;
tail = newNode;
head->prev = tail;
tail->next = head;
}
bool insertAtIndex(int item, int index){
if(index > elementCount){
cout << "Invalid index" << endl;
return false;
}
else if(index == 0){
insertAtFront(item);
}
else if(index == elementCount){
insertAtEnd(item);
}
else {
Node* newNode = new Node;
newNode->data = item;
list = getNodeAt(index - 1);
newNode->next = list->next;
list->next->prev = newNode;
list->next = newNode;
newNode->prev = list;
elementCount++;
}
return true;
}
};
Since this is a learning assignment, here is a general description of the approach:
Define a function bool contains(int value) const that takes an int value and returns true when the list contains the specified value; this function will have a loop in it.
Define a function DoublyLinkedList intersectWith(DoublyLinkedList& other) const that produces the intersection by following the algorithm below:
Create a new DoublyLinkedList result
For each item of this list, call other.contains(node.data)
If the function returned true, check that result.contains(node.data) returns false to eliminate duplicates
If other.contains(node.data) && !result.contains(node.data), add node.data to result
Continue to the next node until this list is exhausted
Return the result list.

Insert Node in a Sorted Doubly linked list

I am not able to figure out, why is my code to insert into a sorted doubly linked list failing on some test cases.Please let me know. I dont know of the test cases, they are system generated.
Node* SortedInsert(Node *head,int data)
{
// Complete this function
// Do not write the main method.
Node * temp = (Node*)malloc(sizeof(Node));
temp->data = data;
temp->next = NULL;
temp->prev = NULL;
if (head == NULL)
{
head = temp;
return head;
}
if (temp->data <= head->data)
{
temp->next = head;
head->prev = temp;
head = temp;
return head;
}
Node *curr = head;
while (curr->next!=NULL)
{
if (temp->data <= curr->data)
{
curr->prev->next = temp;
temp->prev = curr->prev;
temp->next = curr;
curr->prev = temp;
return head;
}
curr = curr->next;
}
curr->next = temp;
temp->prev = curr;
return head;
}
Thanks
Once you reach the last node, you should again compare its data with the new node and insert accordingly.
curr->next = temp;
temp->prev = curr;
return head;
}
If execution reaches this part, then at present curr is pointing to the last node. Now you should again compare its data like the following:
if (temp->data <= curr->data)
{ // insert before last node
curr->prev->next = temp;
temp->prev = curr->prev;
temp->next = curr;
curr->prev = temp;
return head;
}
// else insert at the end.
curr->next = temp;
temp->prev = curr;
return head;
}
Alternatively, you can write an if condition for node at the end of the list
Node* SortedInsert(Node *head,int data)
{
struct Node* p = head;
struct Node* q = NULL;
struct Node* r = new Node;
r->data=data;
r->prev=NULL;
r->next=NULL;
if(p==NULL){
p=r;
head=p;
}
else if(p!=NULL&&p->data>r->data){
p->prev=r;
r->next=p;
p->next=NULL;
head = r;
}
else{
p=head;
while(p!=NULL) {
if(p!=NULL&&p->data>r->data){ //If node is not at the end of list and smaller than some node
(p->prev)->next = r;
r->next = p;
r->prev = p->prev;
p->prev=r;
return head;
}
else if(p->next==NULL) //If node is at the end of list
{
p->next = r;
r->prev = p;
r->next = NULL;
return head;
}
else{}
p=p->next;
}
}
return head;
}
/*
* For reference:
*
* link to the problem :-
* https://www.hackerrank.com/challenges/insert-a-node-into-a-sorted-doubly-linked-list
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode* next;
* DoublyLinkedListNode* prev;
* };
*
* Function to insert a node in sorted DLL with given data & return head
*/
DoublyLinkedListNode* sortedInsert(DoublyLinkedListNode* head, int data) {
DoublyLinkedListNode** prev = &head;
DoublyLinkedListNode* newNode = new DoublyLinkedListNode(data);
while ( *prev && ((*prev)->data <= data) ) {
prev = &(*prev)->next;
}
newNode->prev = *prev;
newNode->next = *prev;
*prev = newNode;
return head;
}
This solution works in all cases (insert in between, insert at the head, insert at the end etc). I was just trying to write a code without any conditions. While searching for some error, I ended up on this SO thread. Do correct me if this solution doesn't work for some test cases.
This is my code that passed all the test cases.
DoublyLinkedListNode* sortedInsert(DoublyLinkedListNode* head, int data) {
DoublyLinkedListNode *temp = head;
if (!temp) {
temp = new DoublyLinkedListNode(data);
head = temp;
return head;
}
while (temp->data < data && temp->next != nullptr) {
temp = temp->next;
}
if (temp->data > data) {
DoublyLinkedListNode *t = new DoublyLinkedListNode(data);
t->next = temp;
if (temp == head) {
head = t;
temp->prev = t;
return head;
}
temp->prev->next = t;
t->next = temp;
temp->prev = t;
} else {
DoublyLinkedListNode *t = new DoublyLinkedListNode(data);
t->next = temp->next;
temp->next = t;
temp->next->prev = temp;
if (t->next != nullptr) t->next->prev = t;
}
return head;
}
Here is some code in order to Insert a Node in Sorted Doubly Linked List
Node* SortedInsert(Node *head,int data)
{
struct Node *temp;
struct Node *newNode = new Node();
newNode->data=data;
newNode->next=NULL;
newNode->prev=NULL;
temp=head;
if(head==NULL)
{
head = newNode;
}
else
{
while(temp!=NULL)
{
if(temp->data<data&&temp->next!=NULL)
{
temp=temp->next;
}
else
{
if(temp->next==NULL&&temp->data<data)
{
temp->next = newNode;
newNode->prev = temp;
break;
}
else if(temp->prev==NULL&&temp->data>data)
{
newNode->next=temp;
temp->prev = newNode;
head=newNode;
break;
}
else
{
newNode->next = temp;
newNode->prev = temp->prev;
temp->prev->next =newNode;
temp->prev=newNode;
break;
}
}
}
}
return head;
}
Here is the complete C++ program for inserting a node at appropriate position in a sorted doubly linked list:
void InsertInSortedDoublyLinkedList()
{
Node *head;
head = CreateDoublyLinkList(3);
PrintDoublyLinkedList(head);
head = SortedInsert(head, 6);
printf("\n Linked list after insertion in sorted order\n");
PrintDoublyLinkedList(head);
}
void PrintDoublyLinkedList(Node *head)
{
Node *temp = head;
printf("NULL -> ");
while (temp)
{
printf("%d ->", temp->data);
temp = temp->next;
}
printf("NULL");
}
Node* CreateDoublyLinkList(int numberOfNodes)
{
Node *head = NULL, *temp, *temp1;
int startingValue = 3;
if (numberOfNodes == 0)
{
return head;
}
temp = (Node*)malloc(sizeof(Node));
temp->data = startingValue;
temp->next = NULL;
temp->prev = NULL;
head = temp;
startingValue += 2;
numberOfNodes--;
for (; numberOfNodes > 0; numberOfNodes--, startingValue += 2, temp = temp->next)
{
temp1 = (Node*)malloc(sizeof(Node));
temp1->data = startingValue;
temp1->next = NULL;
temp1->prev = temp;
temp->next = temp1;
}
return head;
}
Node* SortedInsert(Node *head,int data)
{
Node *temp = NULL, *temp1,*newNode;
int nodeInserted = 0;
if (head == NULL)
{
head = (Node*) malloc(sizeof(Node));
head->data = data;
head->next = NULL;
head->prev = NULL;
}
else
{
if (head->data > data)
{
//insertion need to take place before head itself.
newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = head;
newNode->prev = NULL;
head->prev = newNode;
head = newNode;
}
else
{
temp1 = head;
temp = head ->next;
while (temp)
{
if (temp->data > data)
{
//we need to insert the node before temp
newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->prev = temp1;
newNode->next = temp;
temp1->next = newNode;
temp->prev = newNode;
nodeInserted = 1;
break;
}
temp1 = temp;
temp = temp->next;
}
if (!nodeInserted)
{
//node insertion need to take place at tail.
newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->prev = temp1;
newNode->next = NULL;
temp1->next = newNode;
}
}
}
return head;
}
struct Node
{
int data;
Node *next;
Node *prev;
}
Node* SortedInsert(Node *head,int data)
{
Node* p1,*p2;
int n=10;
p2=(Node*)malloc(sizeof(struct Node));
p2->next=NULL;
p2->prev=NULL;
p2->data=data;
p1=head;
if(p1==NULL)
return p2;
while(p1->next!=NULL)
{
if(p1->data<data)
p1=p1->next;
else
break;
}
/*Three cases arise when p1->next == NUll i.e. we are end of list
case 1: insert after the end
case 2: insert in between last and second last node
case 3: insert node at the beginning of the list
*/
if(p1->next==NULL)
{
if(p1->data<data)
{
p2->prev=p1;
p1->next=p2;
}
else if(p1->data > data && p1->prev!=NULL)
{
p2->next=p1;
p2->prev=p1->prev;
if(p1->prev!=NULL)
p1->prev->next=p2;
p1->prev=p2;
}
else
{
p2->next=p1;
p2->prev=p1->prev;
if(p1->prev!=NULL)
p1->prev->next=p2;
p1->prev=p2;
head=p2;
}
}
// Here we have only one case where new node is inserted between two nodes of the list
else
{
p2->next=p1;
p2->prev=p1->prev;
if(p1->prev!=NULL)
p1->prev->next=p2;
p1->prev=p2;
}
return head;
}