We are iterating through the linked list with the help of head, that is, we are updating our head as we move forward towards i th position. Please have a look at the fuction insertIthnode. I am inserting my Node at i th position are returning head - and it's still able to print the linked list. I don't know how? head is no longer pointing towards the first node then how is it still able to return a full linked list?
here's the code:
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
next = NULL;
}
};
int length(Node *head) {
int x = 0;
Node *temp = head;
while (temp != NULL) {
x += 1;
temp = temp->next;
}
return x;
}
void printIthnode(Node *head, int i) {
int n = length(head);
if (i < 0 || i > n - 1) {
cout << -1 << endl;
return;
}
int count = 1;
while (count <= i) {
head = head->next;
count++;
}
if (head) {
cout << head->data << endl;
} else {
cout << "-1" << endl;
}
}
Node *takeinput() {
int data;
cin >> data;
Node *head = NULL;
Node *tail = NULL;
while (data != -1) {
Node *n = new Node(data);
if (head == NULL) {
head = n;
tail = n;
} else {
tail->next = n;
tail = n;
}
cin >> data;
}
return head;
}
void PrintLL(Node *head) {
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
Node *insertIthnode(Node *head, int i, int data) {
if (i < 0) {
return head;
} else if (i == 0) {
Node *n = new Node(data);
n->next = head;
head = n;
return head;
}
int count = 1;
while (count <= i - 1 && head != NULL) {
head = head->next;
count++;
if (count == i - 1) {
Node *n = new Node(data);
n->next = head->next;
head->next = n;
return head;
}
return head;
}
}
int main() {
/*Node n1(1);
Node *head=&n1;
Node n2(2);
Node n3(3);
Node n4(4);
Node n5(5);
Node n6(6);
n1.next=&n2;
n2.next=&n3;
n3.next=&n4;
n4.next=&n5;
n5.next=&n6;
*/
Node *head = takeinput();
insertIthnode(head, 3, 7);
PrintLL(head);
}
In the main() function you are creating a head when you are taking input from the user with the help of the "takeInput()" function.
After that, you are calling the function "insertIthnode(head,3,7)" which is returning the head (since the return type is Node) but you are not receiving it in any variable so the head returned from the "insetIthnode" is lost.
Your original head remains the same as per of "takeInput()" function.
If you try to insert ith Node at Index 0 it won't print according to the inserted node.
The problem is that you consider the Node as the linked list. While this is valid, the whole point of the linked list is that you don't lose track of the head. You could use two approaches:
Don't iterate over the head. Instead, use a temporary reference to the head.
Implement a Linked List wrapper. You can keep a constant reference to the head while performing operations over the node.
You pass head by value. Any changes you do to the variable receiving the value of head inside the functions are made to the local variable inside the function only and will not be visible from the call site.
Take your PrintLL function as an example:
void PrintLL(Node *head) { // head is here a local variable
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
This could be rewritten without the extra variable temp. The name head doesn't make it the same head you used to call the function with:
void PrintLL(Node* head) {
while (head != nullptr) {
cout << head->data << ' ';
head = head->next;
}
}
and it would not affect the head you passed in as a parameter.
Similarly:
void foo(int x) {
++x;
//
}
int main() {
int x = 10;
foo(x);
std::cout << x << '\n'; // prints 10
}
Related
The below code is for merge sorting a linked list. Its giving out a segmentation fault. I really dont know how to deal with the above. All I could find was that I was trying to access a restricted part of the memory, the only place I think i could've gone wrong is re combining the two linked lists after splitting and sorting them under the split function body. I'd appreciate if I could get some guidance on how to deal with segmentation faults from here on & how to rectify them.
//Segmentation fault
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int data)
{
this->data = data;
next = NULL;
}
};
void print(Node *head)
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
Node *insert()
{
int data;
cin >> data;
Node *head = NULL;
Node *tail = NULL;
while (data != -1)
{
Node *n = new Node(data);
if (head == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
cin >> data;
}
return head;
}
Node *sortedMerge(Node *h1, Node *h2)
{
// Node *fHead = NULL;
// Node *fTail = NULL;
if (!h1)
{
return h2;
}
if (!h2)
{
return h1;
}
if (h1->data < h2->data)
{
h1->next = sortedMerge(h1->next, h2);
return h1;
}
else
{
h2->next = sortedMerge(h1, h2->next);
return h2;
}
}
void split(Node *head, Node *h1, Node *h2)
{
Node *slow = head;
Node *fast = head->next;
while (fast != NULL)
{
fast = fast->next;
if (fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
}
h1 = head;
h2 = slow->next;
slow->next = NULL;
}
void mergeSort_LL(Node *head)
{
Node *temp = head;
Node *h1;
Node *h2;
if ((temp == NULL) || (temp->next == NULL))
{
return;
}
split(temp, h1, h2);
mergeSort_LL(h1);
mergeSort_LL(h2);
head = sortedMerge(h1, h2);
}
int main()
{
Node *head = insert();
print(head);
cout << endl;
mergeSort_LL(head);
cout << "Sorted List is : " << endl;
print(head);
return 0;
}
Your call to split will not make h1 or h2 get a value. Arguments are passed by value. Since you evidently need h1 and h2 to get a different value from that split call, you should pass their addresses:
split(temp, &h1, &h2)
The function itself should therefore accept these addresses instead of the node pointers themselves:
void split(Node *head, Node **h1, Node **h2) {
// ...
*h1 = head;
*h2 = slow->next;
// ...
}
Currently, I am studying the linked list structure.
As I searched, linked list deletion function utilizing 'double pointer'.
In below code, the node is successfully deleted by double pointer in delete function.
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
};
class LinkedList
{
private:
node* head;
node* tail;
public:
LinkedList()
{
head = nullptr;
tail = nullptr;
}
void add_node(int n)
{
node* temp = new node;
temp->data = n;
temp->next = nullptr;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else
{
tail->next = temp;
tail = tail->next;
}
}
node* gethead()
{
return head;
}
void display(node * head)
{
if(head == nullptr)
{
cout << "nullptr : No data" << endl;
return;
}
else
{
node* temp;
temp = head;
while(temp != nullptr)
{
cout << temp->data << endl;
temp = temp->next;
}
}
}
void del(node* head, int value)
{
if(!head)
{
return;
}
else
{
node** nd = &head;
while(*nd && (*nd)->data != value)
nd = &(*nd)->next;
if(*nd)
{
node* temp = *nd;
*nd = (*nd)->next;
delete temp;
}
else
{
cout << "No matching data in the node" <<endl;
}
}
}
};
int main()
{
LinkedList la;
la.add_node(10);
la.add_node(20);
la.add_node(30);
la.add_node(40);
la.add_node(50);
la.display(la.gethead()); //10 20 30 40 50
la.del(la.gethead(), 40);
la.display(la.gethead()); //10 20 30 50
return 0;
}
I just want to know why the below code is not working.
I am trying to simplify the code by not using a double-pointer.
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
};
class LinkedList
{
private:
node* head;
node* tail;
public:
LinkedList()
{
head = nullptr;
tail = nullptr;
}
void add_node(int n)
{
node* temp = new node;
temp->data = n;
temp->next = nullptr;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else
{
tail->next = temp;
tail = tail->next;
}
}
node* gethead()
{
return head;
}
void display(node * head)
{
if(head == nullptr)
{
cout << "nullptr : No data" << endl;
return;
}
else
{
node* temp;
temp = head;
while(temp != nullptr)
{
cout << temp->data << endl;
temp = temp->next;
}
}
}
void del(node* head, int value)
{
if(!head)
{
return;
}
else
{
node* pp = head;
while((pp)->data != value)
pp = pp->next;
if(pp)
{
node* temp = pp;
pp = pp->next;
delete temp;
}
else
{
cout << "No matching data in the node" <<endl;
}
}
}
};
int main()
{
LinkedList la;
la.add_node(10);
la.add_node(20);
la.add_node(30);
la.add_node(40);
la.add_node(50);
la.display(la.gethead()); //10 20 30 40 50
la.del(la.gethead(), 40);
la.display(la.gethead()); //10 20 30 50
return 0;
}
Could you please give me advice about why the above code does not delete the node like the first code?
I think that the second code has to be worked because it deletes the node by utilizing pointer(which saves the address of the node).
Thanks in advance.
First of all, the term is "Pointer to pointer" and not "double pointer". Double pointer is a pointer to a variable of type double.
You should really realize that pointers are simply addresses in your memory.
When you are copying pointer (i.e.: node* pp = head;), you put the address that head points to in pp.
What it means? that both pp and head are pointing to the same address.
But, it is also important to remember that pp and head are variables, and thus are written in the memory as well. Saying that - pp and head also have addresses, but since pp and head are distinct variables, they have distinct addresses.
So the problem comes when you are trying to modify the content of head.
On the first occurence:
node** nd = &head;
while(*nd && (*nd)->data != value)
nd = &(*nd)->next;
You don't modify the content of head (or *nd) at all. And thus, you could used the version with pp.
You problem is with this piece of code:
pp = pp->next;
Here, pp is a copy of the address of the original linked list item, and since it is only a copy, then pp = pp->next does practicly nothing. In this case, you really should have written *nd = *nd->next, because this way change the original value and not a copy you created.
Note: even if you will change in your second example the variable pp to be a pointer-to-pointer, you code will still not be able to delete the first element in the list, since it is passed as a regular pointer to head, and thus only your first version is valid.
I'm trying to implement my own version of a linked list for learning. I have the following code. The reverseList function works correctly and if I print it inside that function it is good.
However, when I leave the function and then call the print method I get the the first value and then nothing (null). I'm guessing when I get out of the function it brings me back to the original first ([99]) element which is now actually the last element. So my print method outputs the element sees null is the next and ends.
Or I was thinking the changes I was making in the function were somehow only in that function's scope even though I passed a pointer, but that doesn't make sense because if that's the case then I should have all the original data still.
struct ListNode
{
int value;
ListNode* next = NULL;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
list = cur;
std::cout << cur->value << " list:" << list->value << std::endl;
}
void testLinkedList()
{
srand(time(NULL));
ListNode nodes;
nodes.value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(&nodes, i);
//insertList(&nodes, val);
}
printList(&nodes);
reverseList(&nodes);
printList(&nodes);
}
int main()
{
testLinkedList();
return 0;
}
Appreciative of any help you guys can give me,
Thanks!
Update:
By passing the ListNode *list to reverseList, you create a copy of your pointer which point to the same address with nodes. Inside the function, you assign list to the updated cur pointer but the copy will be destroyed at the end. list still points to the same address as before passing to reverseList but its next has changed.
I have modified your code a little bit:
#include <cstdlib>
#include <iostream>
struct ListNode
{
int value;
ListNode* next = nullptr;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == nullptr)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != nullptr)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode** list)
{
ListNode* cur = *list;
ListNode* next = cur->next;
ListNode* prev = nullptr;
while(cur != nullptr)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
*list = prev;
}
void cleanNodes(ListNode *list) {
// clean goes here
}
void testLinkedList()
{
srand(time(nullptr));
ListNode *nodes = new ListNode();
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
reverseList(&nodes);
printList(nodes);
cleanNodes(nodes);
}
int main()
{
testLinkedList();
return 0;
}
Try to compile with: -std=gnu++11
You don't change nodes in reverseList you're just changing list you're just changing a pointer on your struct which is a temporary object so physically nodes steel the same and pointed on the same first element which now has next attribute pointing on Null so the result of printList is correct. You need to work with pointers e.g.
#include <iostream>
#include <cstdlib>
struct ListNode
{
int value;
ListNode* next = NULL;
~ListNode(){
if(this->next)
delete this->next;
}
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
ListNode * reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
std::cout << cur->value << " list:" << list->value << std::endl;
return cur;
}
void testLinkedList()
{
srand(time(NULL));
ListNode * nodes = new ListNode;
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
nodes = reverseList(nodes);
printList(nodes);
delete nodes;
}
int main()
{
testLinkedList();
return 0;
}
Also, don't forget to delete object created dynamically
Reversing a linked list is not a fundamental operation. It does not belong among the basis operations of your class. It is easier (and safer) to implement it in terms of your other operations. Roughly:
Create an empty list.
While the first list is not empty, remove a node from the front of the first list and insert it into the front of the second list.
The second list is now the reverse of the original.
my assignment is to find the beginning of a loop in a circular linked list. Since the list is not provided i decided to make a liat by getting the user input for the size of the list then run a for loop with that size. The very last input (last node) is going to point somewhere in the linked list to create a cycle. My function to create the linked list is working, if i cout the head->data while getting the input from the user it prints the right value but when i call the function in the main the head pointer points to NULL and i get a segmentation fault. Can someone take a look at my code and explain why something like that is happening?
#include <iostream>
using namespace std;
struct node{
int data;
node *next;
};
node *head = NULL;
node *tail = NULL;
node *slow = NULL;
node *fast = NULL;
int findLoop(node * head);
void getList(node * head, int listSize);
bool isEmpty(node * head);
int main(){
int listSize;
cout <<"\nEnter the size of the list: ";
cin >> listSize;
getList(head, listSize);
if(head != NULL){
cout << "\n\n\nprinting head " << head->data; //Seg Fault
}
else{
cout << "Head is NULL" << endl;
}
findLoop(head);
return 0;
}
int findLoop(node *head){
slow = head;
fast = head;
if(head == NULL){
cout << "\nThe list is empty\n";
}
bool isLoop = false;
while(slow != NULL && fast != NULL){
if(slow == fast && isLoop == false){
slow = head;
isLoop = true;
}
else if(slow == fast && isLoop == true){
cout <<"\nThe loop starts at: ";
return slow->data;
}
slow = slow->next;
fast = fast->next->next;
}
cout <<"\nThere is no loop\n";
return 0;
}
void getList(node * head, int listSize){
int userData;
for(int i=0; i<listSize; i++){
node *temp = new node;
cout <<"\nEnter a number: ";
int NodeValue = 0;
cin >> NodeValue;
temp->data = NodeValue;
if(head == NULL){
head = temp;
cout << head->data << endl; //Test for appropriate pointing.
}
if(tail != NULL){
tail->next = temp;// point to new node with old tail
}
tail = temp;// assign tail ptr to new tail
temp->next = tail;
if(i == listSize-1){
node *temp2;
temp2 = head;
int iNumber = rand() % i;
for(int j=0; j<iNumber; j++){
temp2 = temp2->next;
}
tail->next = temp2;
}
}
}
Minimal change to actually return new list would be passing pointer by reference:
void getList(node*&, int );
or better do define pointer type
using nodePtr = node*;
void getList(nodePtr&, int);
I am a newbie to programming
Here I wrote a code for accepting and displaying the values using linked list.
However the code takes all the values but displays only the last value
Here is the code
#include <iostream>
using namespace std;
struct node {
int value;
node* next;
};
class llist {
public:
void create();
void display();
node* head = NULL;
};
void llist::create()
{
struct node* temp;
temp = NULL;
struct node* p;
p = new struct node;
cin >> p->value;
if (head == NULL) {
head = p;
}
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
}
void llist::display()
{
struct node* temp = head;
while (temp != NULL) {
cout << "VALUE:" << temp->value << endl;
temp = temp->next;
}
}
int main()
{
int n, i;
llist l1;
cin >> n;
for (i = 0; i < n; i++)
l1.create();
cout << "Displaying list\n";
l1.display();
return 0;
}
Input:
4
1
2
3
4
Displaying list
VALUE:4
I am wondering what went wrong...
Change this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
to this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
}
When inserting a new element at the end of a linked list, you find the last element inside the while loop and put it in the temp variable. Then you assign its next value to your new p element. The way you were doing before, you were just overriding the integer number of the last element. That is why when you printed your list you only got the last number you entered.
Also, when creating a new element p, be sure to initialize its next value to NULL:
p = new struct node;
p->next = NULL;
Problem is with the last 2 lines in the else block.
You are overwriting the value and maintaining just the single mode in your list class. And that's the reason, only last value is displayed.
Replace
temp->value = p->value;
temp->next = NULL;
With
temp->next = p;