How to print a simple linked list (C++)? - c++

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!

Related

New and Delete operator on singly linked list in C++

#include <iostream>
#include <assert.h>
using namespace std;
struct node {
int num;
node *link;
};
int main (void) {
node *head, *tail;
tail = new node;
head = tail;
int i = 1;
while (i < 20) {
tail -> num = i;
tail -> link = new node;
assert(tail->link != NULL);
tail = tail->link;
i++;
}
tail -> num = i;
tail -> link = head;
for (int x = 0;x<100;x++) {
cout<<head->num<<" ";
head = head->link;
}
delete head;
return 0;
}
This source code is running but I feel like the delete operator is wrong? Like out of place? It's not suppose to be head. I expect to delete all the new nodes. But how?
Each new needs a corresponding delete. As you have it, you're only deleting the head of the list. All the other nodes will leak memory. Also, some weirdness with that extra node you allocate at the beginning for tail.
This is closer to what you want:
int main (void) {
node *head, *tail;
head = nullptr;
tail = nullptr;
int i = 1;
// allocate 20 nodes into a list
while (i < 20) {
node* newNode = new node();
newNode->num = i;
newNode->link = nullptr;
if (head == nullptr) {
head = newNode;
tail = newNode;
} else {
tail->link = newNode;
}
i++;
}
// print all the nodes out
node* probe = head;
while (probe) {
cout << probe->num << " ";
probe = probe->next;
}
// delete all the nodes in the list
probe = head;
while (probe) {
node* n = probe;
probe = probe->link;
delete n;
}
// don't leave invalid state
head = nullptr;
tail = nullptr;
return 0;
}

Freeing memory space when deleting a node in a circular LinkedList without declaring a new pointer

I've come across a problem in dynamic programming in which we are asked to delete nodes of a circular LinkedList, in the following manner.
Delete the first node then skip one and delete the next, then skip two and delete the next, then skip three and delete the next and it continues until we are left with only one node, and that one node is our answer.
For example, if we have 5 nodes, then the nodes will be deleted in the following order – 1 3
2 5 4, and the last node would be 4.
Similarly, if we have 4 nodes, then the nodes will be deleted in the following order – 1 3 4
2, and the last node would be 2.
This is a screenshot of the part of the code that requires improvement
using this code in c++, I've been successful in solving the problem but I want to free the memory using delete command as I delink a node. Can anyone please help me to solve this problem by improving this code (while using minimal memory)?
The node can be deleted by declaring another pointer, but that would only increase the memory usage, which I don't want at the moment.
The entire code is given below
#include<iostream>
using namespace std;
class linked {
public:
int x;
linked* next;
//methods
linked(int p); //constructor
static void insert(linked*& head, int p);//method to insert new node
static int print(linked* head);//method to print the result
static void del(linked*head, int size) {//method to delete all the undesired nodes
linked* temp = head;
while (temp->next != head) {//traversing until we find the node just behind the node we want to del
temp = temp->next;
}
for(int i=1;i < size;i++) {
for (int k = 1; k < i; k++) {//del nodes with increment
temp = temp->next;
}
temp->next = temp->next->next; //delinking the
}
}
};
int main() {
int no_of_nodes;
cout << "enter the number of nodes you want to have" << endl;
cin >> no_of_nodes;
linked* head = new linked(1);
for (int i = 1; i <= no_of_nodes; i++) {
linked::insert(head, i);//for inserting nodes, as desired by the user
}
linked::del(head, no_of_nodes);
cout<< linked::print(head);
}
linked::linked(int p) {
x = p;
next = NULL;
}
void linked::insert(linked*& head, int p) {
linked* temp = head;
linked* n = new linked(p);//for the new node
if (p == 1) {
head->next = head;
return;
}
while (temp->next != head) {
temp = temp->next;
}
temp->next = n;
n->next = head;
}
int linked::print(linked* head) {
linked* temp = head;
for (int i = 0; i < 25; i++) {//this can go longer(or shorter), i limited it to 25 only, just to ensure that it is a circular linked list
temp = temp->next;
if (temp == temp->next) {
return temp->x;
}
}
cout << endl;
}
P.S. The problem was taken from ICPC Asia Topi 2022, link: (https://giki.edu.pk/wp-content/uploads/2022/03/ICPC_Day_2.pdf)
It seems neither professional programmer are going to help you.:)
So we, beginners, should help each other.:)
You should declare a class of the circular singly-linked list with non-static member functions.
As for the task to remove all elements from the circular singly-linked list except one using the described algorithm then I can suggest the following approach.
At first within the function remove the cycling. This will make easy to remove elements from the circular singly-linked list.
After all elements except one will be removed then restore the cycling.
Here is a demonstration program.
#include <iostream>
#include <utility>
#include <stdexcept>
class CircularList
{
private:
struct Node
{
int data;
Node *next;
} *head = nullptr;
public:
CircularList() = default;
CircularList( const CircularList & ) = delete;
CircularList &operator =( const CircularList & ) = delete;
~CircularList()
{
clear();
}
void clear()
{
if (head)
{
Node *current = head;
do
{
delete std::exchange( current, current->next );
} while (current != head);
head = nullptr;
}
}
void insert( int data )
{
Node *new_node = new Node{ data };
if (not head)
{
new_node->next = new_node;
head = new_node;
}
else
{
Node *current = head;
while (current->next != head) current = current->next;
new_node->next = head;
current->next = new_node;
}
}
const int & top() const
{
if (not head)
{
throw std::out_of_range( "Error. The list is empty." );
}
return head->data;
}
void remove_except_one()
{
if (head)
{
Node *last = head;
while (last->next != head) last = last->next;
last->next = nullptr;
Node **current = &head;
for (size_t n = 0; head->next != nullptr; ++n)
{
for (size_t i = 0; i != n; i++)
{
current = &( *current )->next;
if (*current == NULL) current = &head;
}
Node *tmp = *current;
// The statement below is uncommented for the debug pyrpose.
std::cout << ( *current )->data << '\n';
*current = ( *current )->next;
if (*current == nullptr) current = &head;
delete tmp;
}
head->next = head;
}
}
friend std::ostream &operator <<( std::ostream &os, const CircularList &list )
{
if (list.head)
{
const Node *current = list.head;
do
{
os << current->data << " -> ";
current = current->next;
} while (current != list.head);
}
return os << "null";
}
};
int main()
{
CircularList list;
for (int i = 0; i < 5; i++)
{
list.insert( i + 1 );
}
std::cout << "The list: ";
std::cout << list << '\n';
list.remove_except_one();
std::cout << "The list: ";
std::cout << list << '\n';
list.clear();
std::cout << '\n';
for (int i = 0; i < 4; i++)
{
list.insert( i + 1 );
}
std::cout << "The list: ";
std::cout << list << '\n';
list.remove_except_one();
std::cout << "The list: ";
std::cout << list << '\n';
}
The program output is
The list: 1 -> 2 -> 3 -> 4 -> 5 -> null
1
3
2
5
The list: 4 -> null
The list: 1 -> 2 -> 3 -> 4 -> null
1
3
4
The list: 2 -> null
Within the function remove_except_one this statement
std::cout << ( *current )->data << '\n';
is present for the debug purpose only. You may remove or comment it if you want.
There are some problems with your code:
1) empty list should be nullptr
In main:
linked* head = new linked(1);
should be
linked* head = nullptr;
You start with an empty list. You do not know what data you will insert first and you assume the first value inserted will be 1. With this change you also have to change your insert:
if (p == 1) {
has to check
if (head == nullptr) {
2) replace head with tail
In a circular single linked list you always need the previous node to delete a node or to insert at the head. That means you have to traverse the whole list when given the head to find the previous. This is rather slow, so store the tail of the list instead. Then the head is tail->next and you can delete the head or insert at the head directly.
3) del breaks head
static void del(linked*head, int size) {
If this deletes the first node in the list then the head the caller passed in becomes a dangling pointer. There is no way to update the pointer the caller holds for the list. Just like with insert you need to pass in a reference:
static void del(linked*&head, int size) {
Now for your problem of how to delete the node without extra memory:
You can't. You always need extra memory to temporarily store the node to be deleted while you fix up the links in the list and then delete it. You already needed that extra memory to find the tail of the list and you called it temp.
static void del(linked*&tail) {
if (tail == nullptr) return; // no list, nothing to delete
for (std::size_t skip = 0; tail->next != tail; ++skip) { // keep going till only one node is left
for(std::size_t i = 0; i < skip; ++i) tail = tail->next; // skip nodes
// delete node
linked* temp = tail->next;
tail->next = tail->next->next;
delete temp;
}
}

Dynamic allocated lists - create a function that deletes all the elements which contain an even value

As I homework, I have to create a program which deletes all the nodes which contain an even value.
Here is how I've done it:
#include <iostream>
using namespace std;
struct node {
int info;
node* next;
};
void sterge(node*& p)
{
node* t;
t = new node;
if (p->info % 2 == 0)
{
p = p->next;
}
t = p;
while (t != NULL)
{
if (t->next != NULL)
{
if (t->next->info % 2 == 0)
{
node* aux;
aux = t->next;
t->next = t->next->next;
delete aux;
}
}
t = t->next;
}
}
int main()
{
node* head = new node;
head->info = 5;
node* p = new node;
node* t = new node;
t->info = 2;
head->next = t;
p = head;
node* x = new node;
x->info = 4;
node* w = new node;
w->info = 6;
t->next = x;
x->next = w;
w->next = nullptr;
sterge(head);
//Loop through the list and print each value
while (p != NULL) {
cout << p->info << endl;
p = p->next;
}
return 0;
}
But the output for the nodes created in main is 5 and 4.
I know the reason why but I don't know how to fix it.
Basically, I verify the next node if it has an even value, and then go to the next node. So it would look like this:
5 -> next is even so 2 is deleted
-> go to the next node which is 4
^now the problem is that this node is not being checked because I always check the next one. So it is considered by the program valid.
So how can I fix my program?
Put a continue after your delete.
That way, the next iteration will begin immediately, without the rest of the current iteration being executed, so the unwanted t = t->next will be skipped.

Function moving list elements to the end of the list not working multiple times

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();
}

Reverse doubly-link list in C++

I've been trying to figure out how to reverse the order of a doubly-linked list, but for some reason, in my function void reverse() runs while loop once and then crashes for some reason. To answer some questions ahead, I'm self-teaching myself with my brothers help. This isn't all of the code, but I have a display() function which prints all nodes chronologically from start_ptr and a switch which activates certain functions like
case 1 : add_end(); break;
case 2 : add_begin(); break;
case 3 : add_index(); break;
case 4 : del_end(); break;
case 5 : del_begin(); break;
case 6 : reverse(); break;
This is the geist of my code:
#include <iostream>
using namespace std;
struct node
{
char name[20];
char profession[20];
int age;
node *nxt;
node *prv;
};
node *start_ptr = NULL;
void pswap (node *pa, node *pb)
{
node temp = *pa;
*pa = *pb;
*pb = temp;
return;
}
void reverse()
{
if(start_ptr==NULL)
{
cout << "Can't do anything" << endl;
}
else if(start_ptr->nxt==NULL)
{
return;
}
else
{
node *current = start_ptr;
node *nextone = start_ptr;
nextone=nextone->nxt->nxt;
current=current->nxt;
start_ptr->prv=start_ptr->nxt;
start_ptr->nxt=NULL;
//nextone=nextone->nxt;
while(nextone->nxt!= NULL)
{
pswap(current->nxt, current->prv);
current=nextone;
nextone=nextone->nxt;
}
start_ptr=nextone;
}
}
Try this:
node *ptr = start_ptr;
while (ptr != NULL) {
node *tmp = ptr->nxt;
ptr->nxt = ptr->prv;
ptr->prv = tmp;
if (tmp == NULL) {
end_ptr = start_ptr;
start_ptr = ptr;
}
ptr = tmp;
}
EDIT: My first implementation, which was correct but not perfect.
Your implementation is pretty complicated. Can you try this instead:
node * reverse(Node * start_ptr)
{
Node *curr = start_ptr;
Node * prev = null;
Node * next = null;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
Here is my updated solution:
node * reverse()
{
node *curr = start_ptr;
node * prev = NULL;
node * next = NULL;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
The logic was correct. But the issue was that I was accepting in input argument start_ptr. Which means that I was returning the local copy of it. Now it should be working.
You can simplify your reverse() quite a bit. I'd do something like this:
void reverse()
{
if(start_ptr == NULL)
{
cout << "Can't do anything" << endl;
}
else
{
node *curr = start_ptr;
while(curr != NULL)
{
Node *next = curr->next;
curr->next = curr->prev;
curr->prev = next;
curr = next;
}
start_ptr = prev;
}
}
Explanation: The basic idea is simply to visit each Node and swap the links to previous and next. When we move curr to the next Node, we need to store the next node so we still have a pointer to it when we set curr.next to prev.
Simple solution. reverses in less than half a number of total iterations over the list
template<typename E> void DLinkedList<E>::reverse() {
int median = 0;
int listSize = size();
int counter = 0;
if (listSize == 1)
return;
DNode<E>* tempNode = new DNode<E>();
/**
* A temporary node for swapping a node and its reflection node
*/
DNode<E>* dummyNode = new DNode<E>();
DNode<E>* headCursor = head;
DNode<E>* tailCursor = tail;
for (int i = 0; i < listSize / 2; i++) {
cout << i << "\t";
headCursor = headCursor->next;
tailCursor = tailCursor->prev;
DNode<E>* curNode = headCursor;
DNode<E>* reflectionNode = tailCursor;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* insert a dummy node for reflection
* for even sized lists
*/
curNode->next = dummyNode;
dummyNode->prev = curNode;
reflectionNode->prev = dummyNode;
dummyNode->next = reflectionNode;
}
/**
* swap the connections from previous and
* next nodes for current and reflection nodes
*/
curNode->prev->next = curNode->next->prev = reflectionNode;
reflectionNode->prev->next = reflectionNode->next->prev = curNode;
/**
* swapping of the nodes
*/
tempNode->prev = curNode->prev;
tempNode->next = curNode->next;
curNode->next = reflectionNode->next;
curNode->prev = reflectionNode->prev;
reflectionNode->prev = tempNode->prev;
reflectionNode->next = tempNode->next;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* remove a dummy node for reflection
* for even sized lists
*/
reflectionNode->next = curNode;
curNode->prev = reflectionNode;
}
/**
* Reassign the cursors to position over the recently swapped nodes
*/
tailCursor = curNode;
headCursor = reflectionNode;
}
delete tempNode, dummyNode;
}
template<typename E> int DLinkedList<E>::size() {
int count = 0;
DNode<E>* iterator = head;
while (iterator->next != tail) {
count++;
iterator = iterator->next;
}
return count;
}
I suggest maintaining a link to the last node.
If not, find the last node.
Traverse the list using the "previous" links (or in your case, prv).
There is no need to actually change the links around. Traversing using the prv pointer will automatically visit the nodes in reverse order.
Look at
valuesnextone=nextone->nxt->nxt;
Here nextone->nxt can be null.
Apart from that, try to use pointers to pointers in the swap function.
Your pswap function is wrong
your should swap the pointer not try to create temporary objects and swap them.
Should be like that (there might be other mistake later)
void pswap (node *&pa, node *&pb)
{
node* temp = pa;
pa = pb;
pb = temp;
return;
}
A very simple and O(n) solution using two pointers:
start = head of the doubly LL
struct node *temp, *s;
s = start;
while(s != NULL){
temp = s->prev;
s->prev = s->next;
s->next = temp;
s = s->prev;
}
//if list has more than one node
if(current != NULL){
start = temp->prev;
}
My code for reversing doubly linked list,
Node* Reverse(Node* head)
{
// Complete this function
// Do not write the main method.
if(head != NULL) {
Node* curr = head;
Node* lastsetNode = curr;
while(curr != NULL) {
Node* frwdNode = curr->next;
Node* prevNode = curr->prev;
if(curr==head) {
curr->next = NULL;
curr->prev = frwdNode;
lastsetNode = curr;
}
else {
curr->next = lastsetNode;
curr->prev = frwdNode;
lastsetNode = curr;
}
curr = frwdNode;
}
head = lastsetNode;
}
return head;
}
I thought I'd add a recursive solution here.
node* reverse_and_get_new_head(node* head) {
if (head == nullptr) { return nullptr; }
// This can be avoided by ensuring the initial,
// outer call is with a non-empty list
std::swap(head->prev, head->next);
if (head->prev == nullptr) { return head; }
return reverse_and_get_new_head(head->prev);
}
void reverse() {
start_ptr = reverse_and_get_new_head(start_ptr);
}