How to make linked list with localy declared head? - c++

I need to make a program which connects two linked lists before I used global pointer for the head of the list, but now I need to make it locally so I can insert new element(node) to each of them, but I have a problem with double-pointer, not sure when to use **, when * and when &. I can find any example similar to that.
Down below is what I have now.
#include<stdio.h>
#include<stdlib.h>
typedef struct element_{
int x;
struct element_ *next;
}element;
void insert(element **head, int x) {
element *new_ = new element;
element *p;
new_->x = x;
new_->next = NULL;
if (head == NULL) {
*head = new_;
return;
}
else {
for (p = *head;p->next != NULL;p = p->next) {}
p->next = new_;
}
}
int main(){
element **head = NULL;
insert(head,1);
insert(head,3);
insert(head,3);
insert(head,4);
for (element *p = *head;p != NULL;p = p->next){
printf("%d ", p->x);
}
}

There is nothing from C++ in the program except the operator new. So if to substitute the operator new for a call of malloc then you will get a pure C program.
So a C looking function insert can be defined like
void insert(element **head, int x)
{
element *new_ = new element;
new_->x = x;
new_->next = NULL;
while ( *head != NULL )
{
head = &( *head )->next;
}
*head = new_;
}
And in main you should write
element *head = NULL;
insert( &head, 1 );
insert( &head, 3 );
insert( &head, 3 );
insert( &head, 4 );
for (element *p = head; p != NULL; p = p->next )
{
printf("%d ", p->x);
}
Something that looks like a C++ function insert can be defined the following way
void insert( element * &head, int x )
{
element *new_ = new element { x, nullptr };
element **current = &head;
while ( *current != NULL )
{
current = &( *current )->next;
}
*current = new_;
}
And in main you should write
element *head = nullptr;
insert( head, 1 );
insert( head, 3 );
insert( head, 3 );
insert( head, 4 );
for (element *p = head; p != nullptr; p = p->next )
{
std::cout << p->x << ' ';
}
But to call the program indeed as C++ program then you should define the list as a class. Moreover if new nodes are appended to the tail of the singly-linked list then you should define the list a singly-linked two-sided list.
Here is a demonstrative program.
#include <iostream>
#include <functional>
class List
{
private:
struct Node
{
int data;
Node *next;
} *head = nullptr, *tail = nullptr;
public:
List() = default;
List( const List & ) = delete;
List & operator =( const List & ) = delete;
~List()
{
clear();
}
void clear()
{
while ( head )
{
delete std::exchange( head, head->next );
}
tail = head;
}
void push_front( int data )
{
head = new Node { data, head };
if ( !tail ) tail = head;
}
void push_back( int data )
{
Node *node = new Node { data, nullptr };
if ( tail )
{
tail = tail->next = node;
}
else
{
head = tail = node;
}
}
friend std::ostream & operator <<( std::ostream &os, const List &list )
{
for ( Node *current = list.head; current; current = current->next )
{
std::cout << current->data << " -> ";
}
return std::cout << "null";
}
};
int main()
{
List list;
list.push_back( 1 );
list.push_back( 3 );
list.push_back( 3 );
list.push_back( 4 );
std::cout << list << '\n';
}
Its output is
1 -> 3 -> 3 -> 4 -> null

Your code is nearly correct C code.
If head in main is a pointer to a pointer to element you have to dynamically allocate memory for it. It makes the code unnecessary complex. I made head in main a pointer to element. But you want to change it's value in insert so you have to pass by reference. The C way of pass by value is to pass the address. Also there is no new in C. Use malloc. And remember to clean up at the end. You have to call one free for each malloc.
If it really is supposed to be C++ code you have much to do. E.g, you wouldn't use pointers to pointers but references, you would use smart pointers instead of dynamic memory allocation, ...
Even though this is not the C++ way of programming it's also valid C++ code (I'm not sure about the headers).
#include <stdio.h>
#include <stdlib.h>
typedef struct element_{
int x;
struct element_ *next;
} element;
void insert(element **head, int x) {
element *new_ = malloc(sizeof(element));
element *p;
new_->x = x;
new_->next = NULL;
if (*head == NULL) {
*head = new_;
return;
} else {
for (p = *head;p->next != NULL;p = p->next) {}
p->next = new_;
}
}
void clean(element **p) {
if ((*p)->next != NULL) clean(&(*p)->next);
free(*p);
*p = NULL;
}
int main(){
element *head = NULL;
insert(&head, 1);
insert(&head, 3);
insert(&head, 3);
insert(&head, 4);
for (element *p = head; p != NULL; p = p->next){
printf("%d ", p->x);
}
clean(&head);
}

Related

Remove Singly Linked List at nth position

# include <iostream>
using namespace std;
class Node
{
public:
int d;Node*temp1;
Node*next;Node*temp2;
};
void insert(Node*&head,int x)
{
Node*node = new Node(); // allocate memory 2 node let node be an abstract data
node->d = x; // define data in the new node as new data (saving data define in there)
node->next = head; // Let next of the new node as head
head = node; // let pointer name head point new node
}
void print(Node*node)
{
while (node != NULL)
{
cout<<' '<<node->d;
node = node->next;
}
}
void Delete(Node*&head,int n) // Delete node at position
{
int i;Node*node=head;// temp1 points 2(n-1)th
if(n==1)
{
head = node->next; // head now points 2 second node.
return;
}
for(i=0;i<n-2;i++)
{
head = node->next;
} // temp1 points 2 (n-1)th Node
Node*nnode= node->next; // nth node temp1=node temp2=nnode
node-> next = nnode->next; //(n+1)th Node
}
int main()
{
Node*head = NULL; // Start with empty List
int a,n,i,x;
cin>>n;
for(i=0;i<n;i++)
{
cin>>x;
insert(*&head,x);
}
cout<<"Enter a position:";
cin>>a;
Delete(head,a);print(head);
}
The Output is:
3 // how many number that singly linked list can received
1 2 3 // define many numbers
Enter a position : 1
2 1 // false output it should be 2 3
The output should be:
3
1 2 3
Enter a position : 1
Linked List is 1->2->3
position 1 is remove // at any position we want 2 remove it will show that position we remove
2->3
Enter a position : 4
No data at 4th position
Linked List is 2->3
In the Delete function you have the loop
for(i=0;i<n-2;i++)
{
head = node->next;
}
Because you pass head by reference, you actively destroy the list with this loop. Furthermore since you have node = head earlier, the assignment is effectively head = head->next in the first iteration.
You need to use the variable node instead of head:
for(i=0;i<n-2;i++)
{
node = node->next;
}
You also need to protect against going beyond the end of the list:
for(i = 0; (i < n - 2) && (node->next != nullptr) ;i++)
For starters the declaration of the node of a singly linked list has redundant data members temp1 and temp2 that do not make sense.
The declarations can look like
struct Node
{
int data;
Node *next;
};
In this case the function insert (that you could call like
insert(head,x);
instead of
insert(*&head,x);
as you are doing) will look like
void insert( Node * &head, int x )
{
head = new Node { x, head };
}
In C++ (and in C) indices start from 0. So the function delete also shall accept indices starting from 0. The type of the corresponding parameter shall be an unsigned integer type for example size_t. Otherwise the user can pass a negative number as an index.
The function produces memory leaks because it in fact does not free allocated nodes. It can invoke undefined behavior when the pointer to the head node is equal to NULL. And in general the function does not make sense.
It can be defined the following way
bool Delete( Node * &head, size_t n )
{
Node **current = &head;
while ( *current && n-- )
{
current = &( *current )->next;
}
bool success = *current != nullptr;
if ( success )
{
Node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
return success;
}
Here is a demonstrative program.
#include <iostream>
struct Node
{
int data;
Node *next;
};
void insert( Node * &head, int x )
{
head = new Node { x, head };
}
bool Delete( Node * &head, size_t n )
{
Node **current = &head;
while ( *current && n-- )
{
current = &( *current )->next;
}
bool success = *current != nullptr;
if ( success )
{
Node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
return success;
}
std::ostream & print( Node * &head, std::ostream &os = std::cout )
{
for ( Node *current = head; current != nullptr; current = current->next )
{
os << current->data << " -> ";
}
return os << "null";
}
int main()
{
Node *head = nullptr;
for ( int i = 3; i != 0; i-- ) insert( head, i );
print( head ) << '\n';
size_t pos = 0;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 4;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 1;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 0;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
return 0;
}
Its output is
1 -> 2 -> 3 -> null
2 -> 3 -> null
No data at the position 4
2 -> null
null

Why am I getting segmentation fault while implementing linked list?

In this function, I get segmentation fault. I think it has something to do with memory allocation. What mistake am I making?
Now, if I initialize Node* a =NULL, i get my head pointer as NULL in the end.
struct Node {
int data;
struct Node* next;
Node(int x) {
data = x;
next = NULL;
}
};
Node* addTwoLists(Node* first, Node* second) {
// Code here
Node *a;
Node *head = a;
int bor = 0;
while(first->next && second->next) {
int ans = first->data + second->data;
a = new Node((ans%10)+bor);
bor = ans/10;
a=a->next;
first = first->next;
second = second->next;
}
return head;
}
a is uninitialized. You must not use a until you assign a value
you never again assign to head, so it could never be anything else.
It's not the allocation, it's the pointer use that is all wrong.
Here's how it should look. This code maintains a variable last which is the last node added to the list. You need this variable so you can at the end of the list. You were obviously trying to do this yourself, but got the logic wrong.
Node* addTwoLists(Node* first, Node* second) {
Node *last = NULL;
Node *head = NULL;
int bor = 0;
while(first->next && second->next) {
int ans = first->data + second->data;
Node* a = new Node((ans%10)+bor);
if (head == NULL) {
head = last = a; // first node, update head and end of list
}
else {
last->next = a; // add a to the end of the list
last = a; // update the end of the list
}
bor = ans/10;
first = first->next;
second = second->next;
}
return head;
}
Untested code.
For starters the variable head has indeterminate value and is not changed in the function.
Node *a;
Node *head = a;
Changing the variable a does not mean changing of the value of the expression a->next.
// ...
a = new Node((ans%10)+bor);
//...
a=a->next;
The function can be written the following way (without testing)
Node * addTwoLists( const Node *first, const Node *second )
{
const int Base = 10;
Node *head = nullptr;
int bor = 0;
Node **current = &head;
for ( ; first != nullptr && second != nullptr; first = first->next, second = second->next )
{
int sum = first->data + second->data + bor;
*current = new Node( sum % Base );
bor = sum / Base;
current = &( *current )->next;
}
if ( bor )
{
*current = new Node( bor );
}
return head;
}
Here is a demonstrative program
#include <iostream>
struct Node
{
explicit Node( int data, Node *next = nullptr ) : data( data ), next( next )
{
}
int data;
Node *next;
};
void push_front( Node **head, int x )
{
*head = new Node( x, *head );
}
Node * addTwoLists( const Node *first, const Node *second )
{
const int Base = 10;
Node *head = nullptr;
int bor = 0;
Node **current = &head;
for ( ; first != nullptr && second != nullptr; first = first->next, second = second->next )
{
int sum = first->data + second->data + bor;
*current = new Node( sum % Base );
bor = sum / Base;
current = &( *current )->next;
}
if ( bor )
{
*current = new Node( bor );
}
return head;
}
std::ostream & display_list( const Node *head, std::ostream &os = std::cout )
{
for ( ; head != nullptr; head = head->next )
{
os << head->data << ' ';
}
return os;
}
int main()
{
const int N = 10;
Node *list1 = nullptr;
Node *list2 = nullptr;
for ( int i = 1; i < N; i++ ) push_front( &list1, i );
for ( int i = N; --i != 0; ) push_front( &list2, i );
display_list( list1 ) << '\n';
display_list( list2 ) << '\n';
Node *list3 = addTwoLists( list1, list2 );
display_list( list3 ) << '\n';
}
Its output is
9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9
0 1 1 1 1 1 1 1 1 1
You may get segmentation fault for various reasons here.
If first or second is NULL then you will get segmentation fault. So make sure that if these two nodes are not NULL.
You didn't initialize a. So initialize it first.
And as you want head variable should contain starting node of the answer list so you need to assign node whenever you get start of the list.
Just add this line after a = new Node((ans%10)+bor);
if(head == NULL) head = a;

Creation of LInked List

I want to display the string "Jimmy" but nothing appears. What is my mistake?
#include<iostream>
#include<string>
struct Node
{
std::string s;
Node* next;
};
struct Node* head = NULL;
void insert(const std::string& name)
{
struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
newnode->s = name;
newnode->next = NULL;
head = newnode;
}
void display()
{
struct Node* ptr;
ptr = head;
while (ptr != NULL) {
std::cout << ptr->s << std::endl;
}
}
int main()
{
insert("Jimmy");
display();
return 0;
}
No outputs are shown in this code. Please give some recommendation. I am still new to this data structure.
The standard C function malloc allocates raw memory knowing nothing about the object that will be placed in the memory.
So neither constructor of the object will be called.
The structure Node contains data member of the type std::string for which a constructor shall be called.
In C++ use the operator new instead of calling the C function malloc. The operator not only allocates memory but also calls a constructor for the created object.
It is a bad idea to use global objects in function definitions without passing them through parameters.
The function display can have an infinite loop in case when head is not equal to null pointer because the variable ptr (that is assigned with head) used in the loop is not changed.
void display()
{
struct Node* ptr;
ptr = head;
while (ptr != NULL) {
std::cout << ptr->s << std::endl;
}
}
The function insert can be called only once
void insert(const std::string& name)
{
struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
newnode->s = name;
newnode->next = NULL;
head = newnode;
}
because otherwise it can result in memory leaks
You should free nodes before exiting the program.
Here is a modified your program that does not have the drawbacks of the original program.
#include <iostream>
#include <string>
struct Node
{
std::string s;
Node *next;
};
void insert( Node * &head, const std::string &s )
{
head = new Node { s, head };
}
std::ostream & display( const Node * head, std::ostream &os = std::cout )
{
for ( const Node *current = head; current != nullptr; current = current->next )
{
os << current->s << '\n';
}
return os;
}
void clear( Node * &head )
{
while ( head )
{
Node *tmp = head;
head = head->next;
delete tmp;
}
}
int main()
{
Node *head = nullptr;
insert( head, "Jimmy" );
display( head );
clear( head );
return 0;
}
Its output is
Jimmy

Merging 2 linked lists and appending to the end of linked lists c++

I don't have much so far but I am trying to get the hang of using linked lists.
Struct:
struct Node
{
int value;
Node *next;
};
How can I add a node to the end of the list? I am just trying to take in a pointer for the head of a list and an int value to add in as a new node. When I try running what I have currently I get an exception.
void addNode(Node* head, int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = NULL;
if(!head)
{
head = temp;
return;
}
else
{
Node* last = head;
while(last->next)
last=last->next;
last->next = temp;
}
}
I haven't really begun to work on merging the two lists. I just know that I need to take in 2 linked lists (or pointers to the head of 2 linked lists?) and then run through the lists for all the nodes.
E.G: Linked list 1 has 3 nodes: 4, 10, 20.
Linked List 2 has 4 nodes: 2, 5, 15, 60.
The merge list function would results in a new linked list with 2,4,5,10,15,20,60 as the nodes.
EDIT: In my main, I am calling the addNode function like so:
Node *head = new Node;
insertAtEnd(head,20);
Is that correct or could that be the cause of the exception?
By doing this:
void addNode(Node* head, int x)
// here ---------^
and then later this:
head = temp; // here
you're simply modifying the local head pointer, which took on the address value passed from the caller. Since head is not an actual reference to a pointer (it's just a pointer), the result is the caller's pointer passed as head remains unaltered. You never append your allocated node to your list, leak memory, it becomes a sad day...
Pass the pointer by reference instead. Fixing that, then fixing the invalid data member, which should actually be value and a pointer-to-pointer for walking the list to find the end, the result could look something like this:
#include <iostream>
struct Node
{
int value;
Node *next;
};
void addNode(Node*& head, int x)
{
Node **pp = &head;
while (*pp)
pp = &(*pp)->next;
*pp = new Node;
(*pp)->value = x;
(*pp)->next = nullptr;
}
void printList(const Node *head)
{
for (; head; head = head->next)
std::cout << head->value << ' ';
std::cout << '\n';
}
void freeList(Node *&head)
{
while (head)
{
Node *p = head;
head = p->next;
delete p;
}
}
int main()
{
Node *head = nullptr;
for (int i=1; i<=5; ++i)
addNode(head, i);
printList(head);
freeList(head);
}
Output
1 2 3 4 5
I leave the task of implementing an actual merge to you, but this should be enough to get you a manageable list up and running.
Update: From the OP's edited question:
Node *head = new Node;
insertAtEnd(head,20);
Apart from now-being a completely different named function, your node is default-initialized. In your case that means the resulting Node from new Node; has indeterminate values for both value and next. You're then passing that to your function, which assumes a determinate value (null) to terminate your loop.
This can be fixed any number of ways; the mechanics of the code above is one such way. There is no need to pre-allocate a head node in the first place if the list management code is of the understanding that NULL means no-list. Your addNode original post seemed to at-least-try to follow that mantra.
Declare the function the following way
void addNode( Node* &head, int x) ;
And instead of this code snippet
Node *head = new Node;
insertAtEnd(head,20);
You have to call the function the first time the following way
Node *head = nullptr; // or NULL
addNode(head,20);
Notice that there is no function with name insertAtEnd in your post. There is function addNode.:)
If you need to merge two lists then you can use this demonstrative program as a sample. Of course you will need to add some other functions as for example deleting lists that to get a complete project.
#include <iostream>
struct Node
{
int value;
Node *next;
};
Node * insert( Node *current, int value )
{
Node *tmp;
if ( current == nullptr )
{
tmp = new Node { value, nullptr };
}
else
{
tmp = new Node { value, current->next };
current->next = tmp;
}
return tmp;
}
std::ostream & display( Node *head,
std::ostream &os = std::cout,
const char *delimiter = " " )
{
for ( ; head; head = head->next ) os << head->value << delimiter;
return os;
}
Node * merge( Node * &head1, Node * &head2 )
{
Node *new_head = nullptr;
Node *current = nullptr;
while ( head1 != nullptr && head2 != nullptr )
{
Node *tmp;
if ( head2->value < head1->value )
{
tmp = head2;
head2 = head2->next;
}
else
{
tmp = head1;
head1 = head1->next;
}
tmp->next = nullptr;
if ( new_head == nullptr )
{
new_head = tmp;
current = new_head;
}
else
{
current->next = tmp;
current = current->next;
}
}
if ( head1 != nullptr ) new_head == nullptr ? new_head : current->next = head1;
if ( head2 != nullptr ) new_head == nullptr ? new_head : current->next = head2;
head2 = nullptr;
head1 = new_head;
return new_head;
}
int main()
{
Node *list1 = nullptr;
Node *list2 = nullptr;
list1 = insert( list1, 4 );
insert( insert( list1, 10 ), 20 );
display( list1, std::cout << "List1: " ) << std::endl;
list2 = insert( list2, 2 );
insert( insert( insert( list2, 5 ), 15 ), 60 );
display( list2, std::cout << "List2: " ) << std::endl;
std::cout << std::endl;
merge( list1, list2 );
display( list1, std::cout << "List1: " ) << std::endl;
display( list2, std::cout << "List2: " ) << std::endl;
return 0;
}
The program output is
List1: 4 10 20
List2: 2 5 15 60
List1: 2 4 5 10 15 20 60
List2:
this may be a cause of exception:
struct Node
{
int value; <----- Node structure has value property
Node *next;
};
Node* temp = new Node;
temp->data = x; <------ Assigning to data property of Node which does not exists
temp->next = NULL;
To add list you may use same approach
void addNode(Node* head, Node* head2)
{
Node* last = head;
while(last->next) last=last->next;
last->next = head2;
}
EDIT: In my main, I am calling the addNode function like so:
Node *head = new Node;
insertAtEnd(head,20);
This is wrong. You didn't initialize head->next, so within insertAtEnd the code while(last->next) last=last->next; will attempt to compare uninitialized pointer and if it isn't null, will dereference it. This will likely crash your program rather than throw an exception though. Then again, it's undefined behaviour, so anything may happen.
Since your insert function already covers the case of inserting to empty list, I would simply call
head = nullptr;
insertAtEnd(head,20)`;
Besides that, there's the bug of never updating the head pointer outside the function, which has already been covered in other answers.

Swapping adjacent elements of linked list

The below is my code to recursive swap the adjacent elements of a linked list. I am losing the pointer to every second element after the swap.
The input is 1->2->3->4->5->6->7, I expected the output 2->1->4->3->6->5->7,
but my output is 1->3->5->7.
void nodelist::swap(node* head)
{
node* temp = head->next;
if (head->next!= nullptr)
{
node* temp2 = temp->next;
temp->next = head;
head->next = temp2;
head = head->next;
temp = nullptr;
temp2 = nullptr;
swap(head);
}
}
Any help would be appreciated,thanks in advance.
In fact it is enough to swap only the data members of nodes. There is no need to swap the pointers themselves.
Nevertheless if to use your approach then the function can look like
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
Here is a demonstrative program
#include <iostream>
#include <utility>
struct node
{
int value;
node *next;
};
node * AddNode( node *head, int value )
{
head = new node { value, head };
return head;
}
void PrintList( node *head )
{
for ( ; head != nullptr; head = head->next )
{
std::cout << head->value << ' ';
}
}
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
int main()
{
node *head = nullptr;
for ( int i = 10; i != 0; )
{
head = AddNode( head, --i );
}
PrintList( head );
std::cout << std::endl;
SwapList( head );
PrintList( head );
std::cout << std::endl;
return 0;
}
The output is
0 1 2 3 4 5 6 7 8 9
1 0 3 2 5 4 7 6 9 8
You can use the shown function as a template (or base) for your function.
With no recursion:
void swap(node **head)
{
while (*head && (*head)->next)
{
node* tmp = *head;
*head = tmp->next;
tmp->next = (*head)->next;
(*head)->next = tmp;
head = &tmp->next;
}
}
Invoke swap( & list_head_ptr).
Alternatively, you can pass the head pointer by reference-to-pointer and utilize a local pointer-to-pointer member:
void swap(node*& head)
{
node **pp = &head;
while (*pp && (*pp)->next)
{
node* tmp = *pp;
*pp = tmp->next;
tmp->next = (*pp)->next;
(*pp)->next = tmp;
pp = &tmp->next;
}
}
and invoke as swap(list_head_ptr). Either method works.
Using recursion:
void nodelist::swap(node** head) {
if (!*head || !(*head)->next) return;
node* const sw = (*head)->next;
(*head)->next = sw->next;
sw->next = *head;
*head = sw;
swap(&(sw->next->next));
}
If head is the pointer which stores the address of firstNode (value=1), then try following function:
void nodelist::swap(node* head){
node* temp = head->next; //head->next is first-node which needs to switch with it's next node
if (temp!= nullptr && temp->next!=nullptr){
head->next=temp->next; //move second node to first
temp->next = head->next->next; //put second's next in first's
head->next->next = temp; //and first will be second's next
temp = nullptr; // swaping done
swap(head->next->next); //do it for next couple
}
}
http://coliru.stacked-crooked.com/a/e1cc0d02b5599da4
OR
http://coliru.stacked-crooked.com/a/a1e200b687825d80
If head itself is the firstNode (value=1), then passing head by value will not work, either you need to pass it by address/reference OR do it like in following link:
http://coliru.stacked-crooked.com/a/a1e200b687825d80