void LinkedList::insert(int num, int pos) {
Node *newNode = new Node;
newNode->data = num;
newNode->next = NULL;
if(pos == 0) {
newNode->next = head;
head = newNode;
}
else {
Node *temp = head;
for (int i = 1; i < pos-1; ++i) {
if (temp != NULL) {
temp = temp->next;
}
}
if (temp != NULL) {
newNode->next = temp->next;
temp->next = newNode;
}
else {
cout << " The previous node is full.";
}
}
}
This is my insert function.
The code that runs in main.cpp is:
// adding through insert
nums.insert(1, 0);
nums.insert(5, 4);
nums.insert(3, 7);
And the output is:
List after append:
8 6 7 8 0 9
List after inserting:
1 8 6 5 7 8
As you can see, something is getting overwritten, or the end of the list just gets cut off. I have searched the internet for hours to no avail. The output needs to increase the length of the list and not overwrite anything. Any help would be appreciated.
The problem is this for loop
for (int i = 1; i < pos-1; ++i) {
if (temp != NULL) {
temp = temp->next;
}
}
Let's assume that pos is equal to 2. In this case the loop will not iterate and temp will be equal to head. So the new node will be inserted before the second mode instead to be inserted before the third node.
You need to write
for (int i = 1; temp != nullptr && i < pos; ++i) {
temp = temp->next;
}
Also instead of writing this message
cout << " The previous node is full.";
(it is the caller of the function should decide whether to output a message) I would declare the function like
bool LinkedList::insert(int num, int pos) {
and return either true or false dependent on whether a node was inserted.
Related
I can't for the life of me figure this out I've spent days on this exercise but to no avail.
I'm trying to delete nodes with the value 0 from a singly liked list.
Let's say i have |1|3|0|4|0|5|0|0|. The outcome should be |1|3|4|5|
Here is all the code for reference
#include <iostream>
#include <fstream>
using namespace std;
struct node {
int data;
node* next;
};
node* head, *last;
int n;
void creating_list()
{
node* aux;
ifstream f("in.txt");
f >> n;
for(int i=0;i<n;i++)
{
if (head == NULL)
{
head = new node;
f >> head->data;
head->next = NULL;
last = head;
}
else
{
aux = new node;
f >> aux->data;
last->next = aux;
aux->next = NULL;
last = aux;
}
}
}
void displaying_list()
{
node* a;
a = head;
if (a == NULL)
cout << "List is empty! ";
else
{
cout << "Elements of list are: | ";
while (a)
{
cout << a->data<<" | ";
a = a->next;
}
}
}
void delete_first_node()
{
if (head == NULL)
cout << "List is empty";
else
{
cout << "Deleting first node\n";
node* aux;
aux = head;
head = head->next;
delete aux;
}
}
void delete_last_node()
{
if (head == NULL)
cout << "List is empty";
else
{
if (head == last)
{
delete head;
head = last = NULL;
}
else
{
node* current;
current = head;
while (current->next != last)
current = current->next;
delete current->next;
current->next = NULL;
last = current;
}
}
}
void delete_value_0()
{
node* aux;
if (head == NULL)
cout << "List is empty. Can't delete! ";
else
// if (head->data == 0)
// delete_first_node();
// if (last->data == 0)
// delete_last_node();
// else
{
node* a;
a = head;
while (a)
if (a->next->data != 0)
{
a = a->next;
cout << a->data<<" | ";
}
else
if (a->next != last)
{
aux = a->next;
a->next = a->next->next;
delete aux;
break;
}
}
}
int main()
{
creating_list();
displaying_list(); cout <<endl;
delete_value_0();
return 0;
}
Here is the problem that gives me metal problems
I've tried to move one node short of the node that has the 0 value, store the value in another node, aux in this case and delete aux;
I've put comment on those lines because if I don't and the condition it's met it doesn't execute the rest of the code...
If I put break at the end it only shows me the first few numbers until the 0 and then stops short, doesn't move through the full list.
if I don't put break the the program is doesn't stop, it's in an infinite loop, it doesn't exit with code 0
void delete_value_0()
{
node* aux;
if (head == NULL)
cout << "List is empty. Can't delete! ";
else
// if (head->data == 0)
// delete_first_node();
// if (last->data == 0)
// delete_last_node();
// else
{
node* a;
a = head;
while (a)
if (a->next->data != 0)
{
a = a->next;
cout << a->data<<" | ";
}
else
if (a->next != last)
{
aux = a->next;
a->next = a->next->next;
delete aux;
break;
}
}
}
Honestly I'm at a loss I've spent so much time trying to figure this out, and this should be a very simple exercise. I feel like the answear Is really simple but i don't know what to do anymore, Maybe this is not for me.
This is much simpler than it appears on the first glance. The trick to this task is instead of using a pointer to the current node, a pointer to the pointer to the current node gets used instead. The entire task becomes laughably trivial: only one loop, and one if statement that takes care of all possibilities: the list is empty; the node to delete is the first node in the list; ot the last node in the list; or anywhere in the middle of it.
void delete_value_0()
{
node **p= &head;
while (*p)
{
if ((*p)->data == 0)
{
node *nextptr=*p;
*p=(*p)->next;
delete nextptr;
}
else
{
p= &(*p)->next;
}
}
}
The naive solution is something like this:
void delete_value_0()
{
while (head && head->data == 0)
delete_first_node();
if (head == nullptr)
return;
node *cur = head->next;
node *pre = head;
while (cur)
{
if (cur->data == 0)
{
pre->next = cur->next;
delete cur;
cur = pre->next;
}
else
{
pre = cur;
cur = cur->next;
}
}
}
The key point is that you need to have a pointer to both the element you are inspecting and to the previous element in the list. This allows you to pull the current element out if it has data == 0.
The issue with this is that you have to treat the first element special (since it has no previous element).
My suggestion is to study this solution until you understand how it works, then move on to the (much better) solution by #Sam Varshavchik and study that - it does basically the same, but uses a pointer to pointer in a clever way to make the special cases here irrelevant.
I've put comment on those lines because if I don't and the condition it's met it doesn't execute the rest of the code...
OK why there the sketchy iteration is in else for if (last->data == 0)? Your input seems to have 0 as last item so in this case it would never be triggered. Also, if you want to have first/last items as special case, instead of
if (head->data == 0)
delete_first_node();
you would want something like
while (head && head->data == 0)
delete_first_node();
That being said, the real WTF is treating first/last item specially instead of using just single iteration. Also, you don't really check whether the pointers are non-null before trying to access the contents. With C (or C++ in the case you try it at some point) you need to take care with memory access when dealing with pointers.
Some random pieces of help:
You need to break from last item when it's 0 to exit loop simply because you don't assign a to the next item in this case.
If this is your schoolwork this might not be your fault, reading amount of items from the input file (assuming it was given part of the assignment) before actual items is huge WTF as you're reading into a linked list. There is no need to loop for any n items when you can be simply reading a line of input at the time until the file runs out.
Arguments and return values. You should learn those.
#include <iostream>
struct Node {
int data;
Node* next;
};
// Function to delete nodes with the value 0 in a singly linked list
void deleteNodes(Node** head) {
// Edge case: empty list
if (*head == nullptr) {
return;
}
// Delete all nodes with the value 0 at the beginning of the list
while (*head != nullptr && (*head)->data == 0) {
Node* temp = *head;
*head = (*head)->next;
delete temp;
}
// Edge case: list with only one node
if (*head == nullptr) {
return;
}
// Delete nodes with the value 0 in the rest of the list
Node* current = *head;
while (current->next != nullptr) {
if (current->next->data == 0) {
Node* temp = current->next;
current->next = temp->next;
delete temp;
} else {
current = current->next;
}
}
}
int main() {
// Create a singly linked list: 1 -> 0 -> 2 -> 0 -> 3 -> 0 -> 4
Node* head = new Node{1, new Node{0, new Node{2, new Node{0, new Node{3, new Node{0, new Node{4, nullptr}}}}}};
// Delete nodes with the value 0
deleteNodes(&head);
// Print the resulting list: 1 -> 2 -> 3 -> 4
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
return 0;
}
hope it help
I need to make a function that moves the nth element in a singly linked list to the end of the list. I created some code that does that but it only works once if I try to do it again it moves the selected element to the end but the one that was moved previously gets deleted/dissapears. My theory is that it doesnt actually change the tail reference. so im stuck right now!
void move(int n)
{
if (head == NULL || head->next == NULL)
{
return;
}
node *first = head;
node *temp =new node;
for (int i = 1; i < n-1; i++)
{
first=first->next;
}
temp = first->next;
first->next=first->next->next;
temp->next = NULL;
tail->next = temp;
tail=temp;
}
my input:
1 2 3 4 5
after moving the 3rd element for the first time:
1 2 4 5 3
after moving the 3rd element(4) for the 2nd time:
1 2 5 4
but it should be
1 2 5 3 4
I checked your code with my own implementation. Your function move() is working fine. However, you should not be using 'new' in your 8th line of code as highlighted by #molbdnilo and #PaulMakenzie. But it is not responsible for this problem. There is a problem with some other part of your code.
#include<iostream>
using namespace std;
class List
{
struct Node
{
int number;
Node* next;
};
Node* head;
Node* tail;
public:
List()
{
head = NULL;
tail = NULL;
}
void insert(int num)
{
Node* temp = new Node();
temp->number = num;
temp->next = NULL;
if (head == NULL)
{
head = temp;
tail = temp;
}
else
{
Node* point = head;
while (point->next != NULL)
point = point->next;
point->next = temp;
tail = point->next;
}
}
void display()
{
Node* point = head;
while (point != NULL)
{
cout << point->number << " ";
point = point->next;
}
}
void move(int n)
{
if (head == NULL || head->next == NULL)
{
return;
}
Node *first = head;
Node *temp;
for (int i = 1; i < n-1; i++)
{
first=first->next;
}
temp = first->next;
first->next=first->next->next;
temp->next = NULL;
tail->next = temp;
tail=temp;
}
};
int main()
{
List a;
a.insert(1);
a.insert(2);
a.insert(3);
a.insert(4);
a.insert(5);
a.move(3);
a.move(3);
a.display();
}
The code that I have made is this:
struct node
{
int value;
node *prev;
node *next;
};
void play()
{
node *head = NULL, *temp = NULL, *run = NULL;
for (int x = 1; x > 10; x++)
{
temp = new node(); //Make a new node
temp -> value = x; //Assign value of new node
temp -> prev = NULL; //Previous node (node before current node)
temp -> next = NULL; //Next node (node after current node)
}
if (head == NULL)
{
head = temp; //Head -> Temp
}
else
{
run = head; //Run -> Head
while (run -> next != NULL)
{
run = run -> next; //Go from node to node
}
run -> next = temp; //If next node is null, next node makes a new temp
temp -> prev = run;
}
run = head; //Play from start again
while (run != NULL) //Printing
{
printf("%d\n", run -> value);
run = run -> next;
}
}
int main()
{
play();
system ("pause");
return 0;
}
However, it is not working. There is no output (completely blank). How can I get this linked list to print properly? I want it to output:
1 2 3 4 5 6 7 8 9 10
Other options that I have is to make another separate function for the printing or move the whole thing to int main but I have already tried that and it still does not output anything.
For starters there is a typo in the condition of the first for-loop in the function
for (int x = 1; x > 10; x++)
^^^^^^
There must be
for (int x = 1; x <= 10; x++)
^^^^^^
Secondly the code that tries to add a new node to the list is outside the for-loop. So only the last allocated node will be added to the list. You have to place the code inside the loop.
Also if here is a double-linked list then it is desirable to have a tail node to which a new node will be appended.
And you should free all allocated memory before exiting the function.
The function can look the following way as it is shown in the demonstrative program.
#include <iostream>
#include <cstdlib>
struct node
{
int value;
node *prev;
node *next;
};
void play()
{
const int N = 10;
node *head = nullptr, *tail = nullptr;
for (int i = 0; i < N; i++)
{
node *temp = new node{ i + 1, tail, nullptr };
if (tail == nullptr)
{
head = tail = temp;
}
else
{
tail = tail->next = temp;
}
}
for (node *current = head; current != nullptr; current = current->next)
{
std::cout << current->value << ' ';
}
std::cout << std::endl;
while (head != nullptr)
{
node *temp = head;
head = head->next;
delete temp;
}
tail = head;
}
int main()
{
play();
// system("pause");
return 0;
}
The program output is
1 2 3 4 5 6 7 8 9 10
You could make the function more flexible by adding one parameter that specifies the number of nodes in the created list instead of using the magic number 10.
For example
void play( int n )
{
node *head = nullptr, *tail = nullptr;
for (int i = 0; i < n; i++)
{
node *temp = new node{ i + 1, tail, nullptr };
if (tail == nullptr)
{
head = tail = temp;
}
else
{
tail = tail->next = temp;
}
}
for (node *current = head; current != nullptr; current = current->next)
{
std::cout << current->value << ' ';
}
std::cout << std::endl;
while (head != nullptr)
{
node *temp = head;
head = head->next;
delete temp;
}
tail = head;
}
In this case the function can be called for example like
play( 10 );
or
play( 20 );
and so on.
When you run play(), you create 10 new nodes, but you store them nowhere before creating a new one. Thus, you "lose" all the nodes - except the last one, which is still in temp.
Instead, you should do something like:
for (int x = 1; x < 10; x++)
{
if (temp == nullptr) {
temp = new node();
temp -> value = x;
temp -> prev = nullptr;
temp -> next = nullptr;
head = temp;
} else {
temp -> next = new node();
temp -> next -> value = x;
temp -> next -> prev = temp;
temp -> next -> next = nullptr;
temp = temp -> next
}
}
Then, you can print your linked list as you already do:
run = head; //Play from start again
while (run != nullptr) //Printing
{
printf("%d\n", run -> value);
run = run -> next;
}
As noticed by #Vlad from Moscow, don't forget to free allocated memory before exiting the function.
Note that I use nullptr instead of NULL. It's a C++11 keyword that replaces NULL. Explications are here.
First your program never enters the for loop. Your loop is equivalent to:
int x=1;
while(x>10) { // always false
// do stuff
x++;
}
Therefore, temp is NULL, head is initialize to NULL and nothing happens.
Second, the initialization of your list is not in the loop, so at most only the head would be initialized. Move the closing bracket of the for loop at the end of your function (and adjust indentations etc).
In a second time, and if your compiler allows it, you might consider using more C++ idioms instead of C idioms (if your goal is to learn C++), using nullptr, cout, smart pointers... but it's an other story!
I have a problem with deleting nodes in linked list. This is my code (except for addElement function which works fine). I initialize nodes in the list trough input, then call the function which removes the nodes on right side with higher value and then print the modified list, lastly delete the list.
The problem is that with certain inputs my program doesn't work properly.
For example if I input 1,2,3,4,3 then the output should be 1 and 3 (the 2nd three) but my output is only 1.
What could be the problem? Can't seem to figure it out.
Edit 1: Here's the includes.
Edit 2: Included the addElement function
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct digits {
int value;
digits *next
};
int main() {
int a, b, c;
digits *head = NULL, *tale = NULL, *current;
cout << "How many digits you want in the linked list?" << endl;
cin >> a;
for (int i = 0; i < a; i++) {
cin >> b;
current = new digits;
current->value = b;
current->next = NULL;
if (head == NULL)
head = tale = current;
else {
tale->next = current;
tale = current;
}
if (!cin.good()) {
cin.clear();
cin.ignore(256, '\n');
cout << "Input can be int value! You can still input " << (a - i) - 1
<< " digits." << endl;
continue;
}
}
cout << "Want to add element? Press J if so, otherwise any other key" << endl;
cin >> add;
if (add == 'J') {
cin >> c;
addElement(&head, c);
}
removeElement(head);
for (current = head; current != NULL; current = current->next)
cout << current->value << endl;
current = head;
while (current != NULL) {
head = head->next;
delete current;
current = head;
}
}
// function which removes elements which have greater value on right side
void removeElement(struct digits *head) {
struct digits *current = head;
struct digits *max = head;
struct digits *temp;
while (current != NULL && current->next != NULL) {
if (current->next->value > max->value) {
temp = current->next;
current->next = temp->next;
free(temp);
} else {
current = current->next;
max = current;
}
}
}
void addElement(struct digits **head, int a) {
struct digits *newelem = (struct digits*) malloc(sizeof (struct digits));
newelem->value = a;
newelem->next = NULL;
struct digits *temp = *head;
if (*head == NULL) {
*head = newelem;
} else {
while (temp->next != NULL)
temp = temp->next;
temp->next = newelem;
}
}
This gets much easier if you can start at the end and work towards the head.
You can't do this directly with a singly-linked list, but you can use recursion.
First, if the list isn't empty, clean out the rest of the list.
Then you see if the node to the right is greater and remove it if it is.
And then you're done.
void scrub(digits* link)
{
if (link != nullptr)
{
scrub(link->next);
if (link->next != nullptr && link->next->value > link->value)
{
digits* scrap = link->next;
link->next = link->next->next;
delete scrap;
}
}
}
Why your code won't work:
Have a close look at this code:
while (current != NULL && current->next != NULL) {
if (current->next->value > max->value) {
temp = current->next;
current->next = temp->next;
free(temp);
}
You are changing current but not max. Having max var in your code seems totally irrelevant.
Actually you never enter into the else part of the code, current value is always compared with max which throughout remains fixed at 1, and eventually while loop finishes when current is the last node(value = 3), as current->next != NULL fails for last node. So, it fails to get rid of last node. As a result of that, you get:
1(first node) and 3(last node)
Solution: Try this iterative approach:
Node *last, *lastTail = NULL;
current = *head;
int last_val = INT_MAX;
while (current != NULL) {
if(current->value > last_val) {
last = current;
last_val = current->value;
current = current->next;
if(lastTail) {
lastTail->next = current;
}
else {
*head = current;
lastTail = current;
}
delete last;
}
else{
lastTail = current;
last_val = current->value;
current = current->next;
}
}
That may seem kind of vague so really sorry. I am writing to a file and printing to a console the sorted nodes in this singly linked list. Unfortunately, in the sort list, it both prints and writes an extra 0 at the front and cuts a value off the end. Here is the code:
void SLLIntStorage::Read(istream& r)
{
char c[13];
r >> c;
r >> numberOfInts;
head = new Node;
head->next = NULL;
tail = head;
r >> head->data;
for (int i = 0; i < numberOfInts; i++)
{
Node* newNode = new Node;
r >> newNode->data;
if(_sortRead)
{
if(newNode->data > tail->data)
{
tail->next = newNode;
tail = newNode;
}
else if(head->data > newNode->data)
{
newNode->next = head;
head = newNode;
}
else
{
current = head;
while(current->next != NULL)
{
if(current->next->data > newNode->data)
{
newNode->next = current->next;
current->next = newNode;
break;
}
else
{
current = current->next;
}
}
}
}
else
{
tail->next = newNode;
tail = newNode;
}
}
print();
}
void SLLIntStorage::Write(ostream& w)
{
current = head;
for(int i = 0; i < numberOfInts; i++)
{
w << current->data << endl;
if (current->next != NULL)
current = current->next;
}
}
void SLLIntStorage::print()
{
current = head;
for(int i = 0; i < numberOfInts; i++)
{
cout << current->data << endl;
//system("pause");
if(current->next != NULL)
{
current = current->next;
}
}
}
File sample:
0
0
1
2
2
3
........
9995
9996
9996
9998
//supposed to be another 9998 here
It seems you read one entry too much. You first read an entry in the line r >> head->data;
just before the for-loop. Then you read an additional numberOfInts entries in the for-loop for a total of numberOfInts+1 entries.