How to display all list values without endless loop - c++

I have a list and I want to display it's values.
I want to see 1 2 3 4, but I have a endless loop like 1 2 3 4 1 2 3 4 1 2..
Can't understand, why?
struct node
{
int item;
node *next;
node(int x, node *t)
{
item = x;
next = t;
}
};
int main()
{
node *firstElement = new node(1, NULL);
firstElement->next = firstElement;
node *lastElement = firstElement;
for (int i = 2; i < 5; i++)
lastElement = (lastElement->next = new node(i, firstElement));
for (node *first = lastElement; first != 0; first = first->next)
cout << first->item << " ";
delete firstElement;
return 0;
}

Try using this code:
struct node
{
int item;
node *next;
node(int x, node *t)
{
item = x;
next = t;
}
};
int main()
{
node *firstElement = new node(1, NULL);
node *lastElement = firstElement;
for (int i = 2; i < 5; i++)
lastElement = (lastElement->next = new node(i, nullptr));
for (node *first = firstElement; first != 0; first = first->next)
cout << first->item << " ";
return 0;
}
IdeOne live code
The problem is that you set the "next" link of your last node to this node itself, not nullptr.
Also, it's better to delete the memory allocated

The problem is that your data structure has an infinite loop in itself: this line
firstElement->next = firstElement;
makes firstElement point back to itself, creating a circular list. When you add more elements, your list remains circular, so exit condition first == 0 is never achieved.
If you want your list to remain linear, not circular, your insertion code should be modified as follows:
node *firstElement = new node(1, NULL);
node *lastElement = firstElement;
for (int i = 2; i < 5; i++) {
lastElement->next = new node(i, lastElement->next)
lastElement = lastElement->next;
}
The printing code should start with firstElement:
for (node *current = firstElement; current != 0; current = current->next)
cout << current->item << " ";
Finally, deleting a single firstItem is not sufficient. You need a loop to traverse the whole list. Alternatively, you could chain deletion in the destructor by calling delete next, but this is dangerous, because recursive invocation of destructors may overflow the stack.

You have a loop in your list, because lastElement->next always points to firstElement. This is why first will never be equal to 0.
If you really need a loop I think you should write something like this:
node* p = firstElement;
do {
cout << p->item << " ";
p = p->next;
} while (p != firstElement);

The problem is that you create every node with firstElement as its next.
This would make sense if you were adding nodes to the front of the list, but you're adding them at the back, so the last node will point back to the start.
Since you're adding to the back, terminate the list on every insertion instead:
lastElement->next = new node(i, nullptr))

Related

Inserting a node in nth position in a linked list

#include<iostream>
using namespace std;
struct node {
int data;
node *link;
};
node *head = NULL;
void insert(int data, int n)
{
node *temp = new node();
temp->data = data;
if (n == 1)
{
temp->link = head;
head = temp;
}
else
{
node* ptr = head;
for (int i = 1; i <= n - 1; i++)
ptr = ptr->link;
temp->link = ptr->link;
ptr->link = temp;
}
}
void print()
{
cout << "list is: ";
node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->link;
}
cout << endl;
}
int main()
{
insert(2, 1);
insert(3, 2);
insert(4, 3);
insert(5, 4);
insert(6, 5);
print();
return 0;
}
This is a code to implement insertion in a linked list at nth position. The data and position are being passed from the main position.
I am not getting what is the possible error I have made, it has something to do with the for loop.
Its not executing, however if i make the following change:
for(int i=0;i<n-2;i++)
it works fine.
First insert(2,1) works fine. So you have linked list like this
(2)->NULL
|
head
In the second insert, Lets follow the code,
1. else
2. {
3. node* ptr = head;
4. for (int i = 1; i <= n - 1; i++)
5. ptr = ptr->link;
6. temp->link = ptr->link;
7. ptr->link = temp;
8. }
Line 3, ptr points to head. n is 2
(2)->NULL
|
head
|
ptr
Line 4, 1 <= (2-1) is true because 1 == 1, so for loop runs once
Line 5, ptr moves one step, so it points to NULL
(2)->NULL
| |
head |
|
ptr
Line 6, ptr->link is called, which is NULL->link. So it crashes here.
When you do for(int i=0;i<n-2;i++), n is 2, so 0 < (2-2) is false, so it runs fine. Note: Works only when insert calls are made in order like your example. If they are called in wrong order, it wont work.
Changing Line 6 to temp->link = ptr;, should also work without changing the loop.
"Inserting a node in nth position in a linked list" :
Use a std::list rather than rolling your own. Then use std::list::insert.
Also; consider just using a std:: vector instead. A list is a terrible (pointer chasing, cache miss inducing) data structure to use on modern CPUs. A std::vector will almost always beat it (regardless of what your textbooks say about theoretical performance).

Visual studio 2017 code not outputting after a certain line

I am writing a program that takes 8 user inputted integers and makes a linked list out of them. I have the program print the linked list, then I delete the last node and print the list in reverse. Along the way I've been testing to program to make sure each part works, and it's worked up to the point of printing out the original linked list.
When I finished writing the code for the modification and then printing part, I ran into a problem - the program won't output anything after printing out the original list. So for example, if I input 1,2,3,4,5,6,7,8, it will output:
1
2
3
4
5
6
7
8
and that's it. I've tried putting cout << "testing"; at different points to see where my code stops outputting and the latest point where it successfully outputs is right before the while loop.
I'm not sure why a while loop would cause the program to straight up stop outputting anything, even an arbitrary cout statement that has nothing to do with the while loop itself, so I figured I'd ask on here. I'm using visual studio 2017 if that helps. Thanks for any and all help!
#include <iostream>
using namespace std;
void getdata(int & info); //function that assigns a user inputted value to each node
const int nil = 0;
class node_type // declaration of class
{
public:
int info;
node_type *next;
};
int main()
{
node_type *first, *p, *q, *r, *newnode;
first = new node_type;
newnode = new node_type;
int info;
getdata(info); //first node
(*first).info = info;
(*first).next = nil;
getdata(info); //second node
(*newnode).info = info;
(*first).next = newnode;
(*newnode).next = nil;
p = newnode;
for (int i = 2; i < 8; i++) //nodes 3-8
{
newnode = new node_type;
getdata(info);
(*newnode).info = info;
(*p).next = newnode;
p = newnode;
(*newnode).next = nil;
}
q = first;
while (q != nil) // printing linked list
{
cout << (*q).info << "\n";
q = (*q).next;
}
//deletes last node then reverses list
p = first;
q = (*p).next;
r = (*q).next;
if (first == nil) //if list is empty
cout << "Empty list";
else if ((*first).next == nil) //if list has one node
first = nil;
else if (r == nil) //if list has two nodes
q = nil;
else //general case
{
(*first).next = nil; //last line where when i put a cout << ""; it prints in the output window
while ((*r).next != nil)
{
(*q).next = p;
(*r).next = q;
p = q;
q = r;
r = (*r).next;
}
(*q).next = p;
first = q;
}
q = first;
while (q != nil) // printing newly modified list.
{
cout << (*q).info << "\n";
q = (*q).next;
}
return 0;
}
void getdata(int & info)
{
cout << "Enter number: \n";
cin >> info;
}
else //general case
{
(*first).next = nil; //last line where when i put a cout << ""; it prints in the output window
while ((*r).next != nil)
{
(*q).next = p;
(*r).next = q;
p = q;
q = r;
r = (*r).next;
}
(*q).next = p;
first = q;
}
You run into an infinite loop when reversing your list. That's why it doesn't output anything.
As soon as you link element 2 to element 3, you link element 3 to element 2 in the next step.
That causes an infinite loop when iterating through the list while reversing it.
A proper way to reverse it in the general case would be like that:
else //general case
{
node_type* current = first;
node_type* next = first->next;
(*first).next = nil; //last line where when i put a cout << ""; it prints in the output window
while (next)
{
node_type* temp = next->next;
next->next = current;
current = next;
next = temp;
}
first = current;
}
On a sidenote, you should use bla->foo to dereference, instead of (*bla).foo.

Circular linked list: Infinite loop

I'm trying to make a circular link list but i'm facing with a problem.
If i run the program with those 2 lines of code above, when i compile and run, it gets an infinite loop of cin if the number of elements is higher than 2. Without them works fine but it isn't anymore a circular linked list. Can you help ?
The problem is right here:
toPush->next = head;
head->pred = toPush;
Full code:
#include <iostream>
using namespace std;
typedef int data;
// Nodes
struct elements {
data value;
elements* next;
elements* pred;
};
// Function that pushes the element to the end
void insertElementEnding(elements* &head, data var) {
elements* toPush = new elements;
toPush->value = var;
toPush->next = NULL;
toPush->pred = NULL;
if(head == NULL) {
head = toPush;
} else {
elements* node = new elements;
node = head;
while(node->next != NULL) {
node = node->next;
}
node->next = toPush;
toPush->pred = node;
toPush->next = head;
head->pred = toPush;
}
}
// Function that prints the list
void showList(elements* head, int numbers) {
for(int i = 0; i < numbers && head != NULL; i++) {
cout << head->value;
head = head->next;
}
}
int main() {
elements* head = NULL;
int var, n;
cout << "Introduce the number of elements: ";
cin >> n;
for(int i = 0; i < n; i++) {
cin >> var;
insertElementEnding(head, var);
}
showList(head, n);
return 0;
}
Thanks in advance.
You need to look for the start of the loop, not NULL, ie
while(node->next != NULL)
should be
while(node->next != head)
As a sidenote, you should use nullptr instead of NULL in C++.
Also you have a memory leak in your program. You dont need to allocate new memory just to get a pointer for iterating your list. This right here is the problem:
elements* node = new elements;
node = head;
A better way would just be
elements* node = head;
First, validation for NULL makes sense only to check if the list is not initialized, before inserting the first element in it.
For all other cases it is redundant as the head should always have previous and following elements for the circle. In case it is just one in the least, it points to itself.
Then if you change the function slightly, it will resolve the problem
void insertElementEnding(elements* &head, data var) {
elements* toPush = new elements;
toPush->value = var;
if(head == NULL) {
head = toPush;
head->next = toPush;
head->pred = toPush;
} else {
// insert the new element before the head
head->pred->next = toPush;
head->pred = toPush;
}
}

Linked List: issues finding index of node to remove at [index not incrementing correctly]

I am creating a linked list program, and one of the functions is supposed to remove a node at a given index.
My idea is to locate the node one before the node at the index I wish to remove, then set it's next pointer to the ->next pointer of the node I wish to remove, therefore "skipping" it and removing it from the list.
At the moment my for loop does not seem to be working. After the the for loop has run, the value of temp->data is always the data of the second node in the list.
for example, with the list of nodes
15
14
13
12
11
10 (10 being the start of the list)
if I want to remove at the index of 4.
temp->data returns 11, instead of 14.
Here is the code I have:
NODE * removeAt(NODE * pList, int index)
{
NODE * temp = pList;
for (int i = 0; i < index - 1; i++)
{
temp = temp->next;
}
NODE * next = temp->next->next;
temp->next = next;
return temp;
}
Any help is appreciated!
First of all, you have an indexing convention problem. If you say you expect the-next-after-removed to be 14, that means you want to remove the number 13. But it is a number 3 if you start from 0.
You say "My idea is to locate the node one before the node at the index I wish to remove". Imagine you want to remove the start node (data=10), will your idea work here? There is no any "one before" node in this case. Same about the last. There would be no the-next-after-removed.
Also, you need to check for null pointers everywhere. And you must destroy the removed node to avoid memory leaks.
And you need to check how do you insert nodes. Is the start one really 10?
I would improve your code like this:
#include <iostream>
#include <vector>
using namespace std;
struct NODE
{
int data;
NODE * next;
};
NODE * removeAt(NODE * pList, int index)
{
if (!pList)
return nullptr;
NODE * temp = pList;
if (index == 0)
{
temp = pList->next;
std::cout << "removing " << pList->data << endl;
delete pList;
return temp;
}
// after this loop temp points to the node before
for (int i = 0; i < index -2; i++)
{
temp = temp->next;
if (!temp || !temp->next) // to guarantee both the-node-before and the-node-to-remove exist
return nullptr;
}
NODE * next = temp->next->next;
std::cout << "removing " << temp->next->data << endl;
delete temp->next;
temp->next = next;
return next;
}
int main()
{
std::vector<int> vec {15, 14, 13, 12, 11, 10};
NODE * root = nullptr;
for (const int v : vec)
{
std::cout << v << ' ' << endl;
NODE * cur = new NODE;
cur->data = v;
cur->next = root;
root = cur;
}
removeAt(root, 4);
return 0;
}

Inserting and finding nodes - Linked Lists in C++

1) I'm still trying to wrap my head around how linked lists work in c++. Currently I'm trying to insert a new node in between other nodes. Although I'm able to add the desired node, anything after that new node seems to be deleted once I print it:
void InsertNode(int pos, int val) {
Node *n = new Node();
n->data = val;
Node *pnt = head;
for (int i = 0; i < pos; i++) {
pnt = pnt->next;
}
pnt->next = n;
DisplayList();
}
2) And then I want to be able to create another operation that can search for an element in the list and output its position (if it exists). However from what I know so far I don't see how I can compare a value that I want to find to an element in a list.
Here's what I'd imagine it would look like, but I know the if statement isn't valid.
void SearchElement(int val) {
Node *list = head;
int i = 0;
while (list) {
list = list->next;
i++;
if (list == val) { cout << "The value is at position: " << i << endl; }
}
//print statement saying it doesn't exist
}
You have to append the rest of the list to n before you insert the new node:
n->next = pnt->next;
pnt->next = n;
For the second question: Your value is in list->data.
int i = 0;
while (list) {
if (list->data == val) {
cout << "The value is at position: " << i << endl;
break;
}
list = list->next;
i++;
}