I'm trying to implement Linked List on C++ by utilizing three separate functions:
Insert(int x, int n) - Takes the number to be inserted (x) and the position to be inserted at (n) starting with position 1.
Delete(int n) - Deletes the number at position (n) starting with position 1;
Print() - Prints the elements of the linked list.
Here is my code in C++:
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
struct Node {
int data;
Node* next;
};
Node* head;
void Print()
{
cout << "The List is:" ;
Node* temp = head;
while (temp -> next != NULL)
{
temp = temp -> next;
cout << " " << temp -> data;
}
}
void Delete(int n)
{
if ( n == 1 )
{
Node* temp = head;
head = temp -> next;
delete temp;
return;
}
Node* temp1 = head;
for(int i = 0; i < n-2; i++)
{
temp1 = temp1 -> next;
}
Node* temp2 = temp1 -> next;
temp1 -> next = temp2 -> next;
delete temp2;
}
void Insert(int x, int n)
{
Node* temp = new Node();
temp -> data = x;
temp -> next = NULL;
if ( n == 1 )
{
temp -> next = head;
head = temp;
return;
}
Node* temp1 = head;
for (int i = 0; i < n-2; i++)
{
temp1 = temp1 -> next;
}
temp -> next = temp1 -> next;
temp1 -> next = temp;
}
int main()
{
head = NULL;
Insert(2,1);
Insert(3,1);
Insert(99,3);
Insert(4,2);
Insert(5,3); // 3, 4, 5, 99, 2
Print(); // 1st call
Delete(2);
Delete(3); // 3,5,2
Print(); // 2nd call
return 0;
}
The problem is that, according to my configuration, 1st call of the print function produces 4, 5, 2, 99 instead of 3, 4, 5, 2, 99. Also the second call shows 5, 99.
The problem is in your print function, try this:
void Print()
{
cout << "The List is:";
Node* temp = head;
while (temp != NULL)
{
cout << " " << temp->data;
temp = temp->next;
}
}
You need to print till temp itself is not NULL.
And in C++ I suggest using nullptr instead of NULL.
The two lines in the while loop, in the print function are inverted. You are moving your pointer to the next element and then printing, so you never print the first. Your function must look like this:
void Print()
{
cout << "The List is:" ;
Node* temp = head;
while (temp -> next != NULL)
{
cout << " " << temp -> data;
temp = temp -> next;
}
}
Related
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
}
I need to define a class of linked list,List, in a way such that object of class can be defined in two ways,
List obj1 = L1();//head=0
List obj2 = L2(given_arr[], size of array) // I would be given an array, whose elements are elements of list
so, I need to form a construter for both,
for obj1, Its easy.
List(){head=0};
But I am not abe to do so for second type of object.
I tried to form a program for this.
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head;
int arr[];
List() { head = 0; }
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
int i;
head->val = arr[0];
for (i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[4] = {9, 89, 0, 43};
List* M = new List();
List* L = new List(barr[4], 4);
L->display();
return 0;
}
This program doesn't work. Please suggest a way to do so.
Make these changes to your main().
int main() {
int barr[] = {9, 89, 0, 43}; // No need to specify size if you're initializing
// List* M = new List(); // unused
// Your array is barr, barr[4] makes no sense. You also don't allocate the List,
// the list allocates
List L = List(barr, sizeof(barr) / sizeof(barr[0]);
L.display(); // -> to .
return 0;
}
This now compiles, but immediately segfaults. Simply running the program in the debugger shows a simple error. The line head->val = arr[0]; attempts to dereference a null pointer. Which takes us to the next thing. Use nullptr, not NULL or 0.
Your array constructor was over-complicated, you just need this:
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
Your addnode() function already handled an empty list. Fixing that, your code should run. I made a couple other small changes, mostly trimming cruft out. Here's your complete code:
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head = nullptr;
List() = default;
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[] = {9, 89, 0, 43};
List L = List(barr, sizeof(barr) / sizeof(barr[0]));
L.display();
return 0;
}
I've been learning Data Structures and currently working with Linked List. I'm trying to add a node at the end of the linked list but not able to figure out the correct logic for it. I've tried inserting a node at the beginning and it works fine.
This is the code:
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node* next;
};
Node* head; // global
void Insert(int data) {
Node* temp = new Node();
temp -> data = data;
temp -> next = head;
head = temp;
} // insert an integer
void Print(){
Node* temp = head;
cout << "List is: ";
while (temp != NULL) {
cout << temp -> data << " ";
temp = temp -> next;
}
cout << endl;
} // print all elements in the list
void Delete(int n){
Node* temp1 = head;
if(n == 1) {
head = temp1 -> next; // head now points to second node
delete temp1;
return;
}
int i;
for(i = 0; i < n-2; i++)
temp1 = temp1 -> next;
// temp1 points to (n-1)th Node
Node* temp2 = temp1 -> next; // nth Node
temp1 -> next = temp2 -> next; // (n+1)th Node
delete temp2; // delete temp2
} // Delete node at position n
int main() {
head = NULL; // empty list
Insert(2);
Insert(4);
Insert(6);
Insert(5); // List: 2,4,6,5
Print();
int n;
cout << "Enter a postion: " << endl;
cin >> n;
Delete(n);
Print();
}
This code deletes a node at nth position. The node here is being adding from the beginning and I'm trying to figure out the logic to insert it from the end.
Any suggestions and advises on this will be very helpful.
Thanking you in advance.
Play with the code.
void insert_end(int data) {
Node* temp = new Node(); // 1
temp->data = data;
temp -> next = nullptr;
Node* n = head;
if (!n) { // 2
head = temp;
return;
}
while(n->next) { // 3
n = n->next;
}
n->next = temp;
}
Short explanation of the method:
1: You create a new Node and set the data.
2: Check if the list is empty. If it is, insert the new element at the head.
3: If the list is not empty, you read the next element of the list until you have the last Node in your list. If you would write while(n)... here, you would get to the end of the list, meaning a nullptr and the code would break.
My program is meant to run several functions, insertnode takes values from the user and creates a list of them using nodes and sorts them in order from least to greatest, printlist prints the values separated by spaces, mergelist merges the two lists in order, and reverselist reverses the list. The command prompt accepts values but once the stopping condition (0) is entered for the second list it crashes. Visual Studio shows no errors. I figure something is either wrong with the functions or the pointers. Someone spoke to me of a memory leak but Im unsure as to how to fix that.
#include <iostream>
#include <stack>
using namespace std;
class node {
private:
double num;
node *link;
public:
node() { }
node(double m, node *n) { num = m; link = n; }
node* getlink() { return link; }
double getdata() { return num; }
void setdata(double m) { num = m; }
void setlink(node* n) { link = n; }
};
typedef node* nodeptr;
void insertnode(nodeptr& head, double m);
void printlist(nodeptr head);
nodeptr mergelists(nodeptr& head1, nodeptr& head2);
void reverselist(nodeptr& head);
int main()
{
double input;a
nodeptr head1 = NULL; // Pointer to the head of List #1
nodeptr head2 = NULL; // Pointer to the head of List #2
nodeptr temp;
// Part 1 - Create two sorted lists
cout << "-------------------------------------" << endl;
cout << "CREATE LIST #1: " << endl;
cout << "-------------------------------------" << endl;
do {
cout << "Enter value (0 to quit): ";
cin >> input;
insertnode(head1, input);
} while (input != 0);
cout << "-------------------------------------" << endl;
cout << "CREATE LIST #2: " << endl;
cout << "-------------------------------------" << endl;
do {
cout << "Enter value (0 to quit): ";
cin >> input;
insertnode(head2, input);
} while (input != 0);
// Part 1 - Print the lists to make sure that they are correct.
printlist(head1);
printlist(head2);
// Part 2 - Merge the two lists and display the new merged list
temp = mergelists(head1, head2);
printlist(temp);
// Part 3 - Reverse the merged list and then display it
reverselist(temp);
printlist(temp);
return 0;
}
void insertnode(nodeptr& head, double m){
nodeptr p = head;
nodeptr k = p;
if (!p){
nodeptr n = new node(m, NULL);
}
else {
while (m >= p->getdata()){
k = p;
p = p->getlink();
}
nodeptr n = new node;
n->setdata(m);
k->setlink(n);
if (p){
n->setlink(p);
}
}
}
void printlist(nodeptr head){
nodeptr p = head;
while (p){
double m = p->getdata();
cout << m << " ";
p = p->getlink();
}
cout << endl;
}
nodeptr mergelists(nodeptr &head1, nodeptr &head2){
nodeptr result = 0, last = 0;;
if (head1->getdata() <= head2->getdata()){
result = head1;
head1 = head1->getlink();
}
else {
result = head2;
head2 = head2->getlink();
}
last = result;
while (head1 && head2){
if (head1->getdata() <= head2->getdata()){
last->setlink(head1);
last = head1;
head1 = head1->getlink();
}
else{
last->setlink(head2);
last = head2;
head2 = head2->getlink();
}
}
if (head1)
last->setlink(head1);
else if (head2)
last->setlink(head2);
last = 0;
head1 = 0;
head2 = 0;
return result;
}
void reverselist(nodeptr& head){
stack<double> holder;
nodeptr p = head;
while (p){
holder.push(p->getdata());
p = p->getlink();
}
p = head;
while (p){
p->setdata(holder.top());
holder.pop();
p = p->getlink();
}
}
There are a few issues with this method:
void insertnode(nodeptr& head, double m){
nodeptr p = head;
nodeptr k = p;
if (!p)
{
head = new node(m, NULL); // Update head
}
else
{
while (p && m >= p->getdata()) // Check for p!=NULL
{
k = p;
p = p->getlink();
}
nodeptr n = new node;
n->setdata(m);
k->setlink(n);
if (p)
{
n->setlink(p);
}
}
}
The simplified version:
void insertnode(nodeptr& head, double m)
{
nodeptr p = head;
nodeptr k = nullptr;
while (p && m >= p->getdata())
{
k = p;
p = p->getlink();
}
if (!k)
{
head = new node(m, p);
}
else
{
k->setlink(new node(m, p));
}
}
There are two issue is that you are not updating the head node when you insert into the linked list. The previous answer by #uncletall outlined this.
The second issue is very simple -- you failed to initialize the link to NULL when you default construct a node. Make the following change in your node class:
class node {
private:
double num;
node *link;
public:
node() : link(0) { } // here is the change here
//...
//... the rest of your code
};
When you default construct a node the link is now initialized. Without this change, your link node was a garbage value, thus you were not traversing the links properly when you were inserting more items in the list.
The change is similar to (but not exactly) the same as this:
class node {
private:
double num;
node *link;
public:
node() { link = 0; } // here is the change here
//...
//... the rest of your code
};
The difference is that link is assigned in the body of the constructor here, while the first example initializes the link to 0 before the constructor has started. Both wind up doing the same thing.
I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.