C++ reordering Singly Linked List - c++

Hi I'm trying to write a code for singly linked list that reorders the nodes so that:
L1->L2->L3->...->Ln to L1->Ln->L2->Ln-1->L3->Ln-2...
So I tried to do this by finding the node at the end of the list and setting that node as the next of current node and then finishing the loop by setting the current node as the next next of current node.
#include <cstdlib>
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* newNode(int x){
ListNode* temp = new ListNode;
temp->val = x;
temp->next = NULL;
return temp;
}
void printlist(ListNode* head)
{
while (head != NULL) {
cout << head->val << " ";
if (head->next)
cout << "-> ";
head = head->next;
}
cout << endl;
}
void reorderList(ListNode* head){
ListNode *curr = head;
ListNode *temp=head;
ListNode *last=NULL;
while(curr->next != NULL){
while(temp->next != NULL){
temp=temp->next;
last=temp;
}
curr->next=last;
last->next=curr->next->next;
curr=curr->next->next;
temp=curr->next;
}
}
int main(int argc, char** argv) {
ListNode* head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
printlist(head); // Print original list
reorderList(head); // Modify the list
printlist(head); // Print modified list
return 0;
}
So far, after displaying the original list, the program stops by saying that the run failed. I'm having some problem understanding the singly linked list and I don't know what I'm doing wrong.

I have modified your code to show a correct answer:
#include <iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode(): val( 0 ), next( nullptr ) {}
ListNode( int x ): val( x ), next( nullptr ) {}
ListNode( int x, ListNode* next ): val( x ), next( next ) {}
};
void printlist( ListNode* head )
{
while( head != nullptr ) {
std::cout << head->val << " ";
if( head->next )
std::cout << "-> ";
head = head->next;
}
std::cout << std::endl;
}
void reorderList( ListNode* head ) {
ListNode* pf = head;
ListNode* pt = nullptr;
ListNode* tmp = nullptr;
while( true )
{
// find n-1 node
tmp = pf;
while( tmp && tmp->next && tmp->next->next )
tmp = tmp->next;
// check to see n-1 node is not equal to the first node
if( tmp == pf )
break;
// reorder
pt = tmp;
tmp = pf->next;
pf->next = pt->next;
pt->next->next = tmp;
pf = tmp;
pt->next = nullptr;
}
}
int main( int argc, char** argv ) {
ListNode* head = new ListNode( 1 );
head->next = new ListNode( 2 );
head->next->next = new ListNode( 3 );
head->next->next->next = new ListNode( 4 );
head->next->next->next->next = new ListNode( 5 );
head->next->next->next->next->next = new ListNode( 6 );
printlist( head ); // Print original list
reorderList( head ); // Modify the list
printlist( head ); // Print modified list
return 0;
}
and the result is like below:
1 -> 2 -> 3 -> 4 -> 5 -> 6
1 -> 6 -> 2 -> 5 -> 3 -> 4

There could be many solutions to your problem. I just modified your logic and added comments which could help you to understand. Happy link list coding.
#include <cstdlib>
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* newNode(int x){
ListNode* temp = new ListNode;
temp->val = x;
temp->next = NULL;
return temp;
}
void printlist(ListNode* head)
{
while (head != NULL) {
cout << head->val << " ";
if (head->next)
cout << "-> ";
head = head->next;
}
cout << endl;
}
void reorderList(ListNode* head){
ListNode *curr = head;
ListNode *temp=head;
ListNode *last=NULL,*prev;
while(curr->next != NULL){
while(temp->next != NULL){
//Prev variable is being used for remove last node connection from it previous node
// For example 1->2->3
// We need to remove 2->3 connection before adding 1->3
// Otherwise it will create cycle i.e 1->3->2->3->2....
prev = temp;
temp=temp->next;
last=temp;
}
// If node number is even this condition will check adding mid+1 node twice
if(last==NULL) {
break;
}
temp = curr->next;
curr->next=last;
last->next=temp;
curr=curr->next->next;
temp=curr->next;
// Removing last node connection from it previous node
prev->next = NULL;
last = NULL;
}
}
int main(int argc, char** argv) {
ListNode* head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
//head->next->next->next->next->next = newNode(8);
printlist(head); // Print original list
reorderList(head); // Modify the list
printlist(head); // Print modified list
return 0;
}

Related

How Can I Create A Single function that can create multiple Linked Lists

as shown in the code , i have to use 2 similar functions for creating 2 linked lists . isn't there a way i can create as many lists as i want with just one function , i tried using struct Node **p and struct Node *p as a parameter to the function but the didn't work
can someone help me to create multiple linked lists using this same function
and i want to create a append function not a insert function which asks for position as well.
#include <iostream>
using namespace std;
struct Node
{
int data = 10 ;
struct Node *next;
} *first , *second , *third;
void Display(struct Node *p)
{
while (p)
{
cout<<p->data<<" ";
p = p->next ;
}
cout<<"\n";
}
void Append_1(int elem)
{
Node* t , *last;
t = new Node;
t->data = elem;
t->next = NULL;
if(first == 0)
first = last = t;
else
{
last->next = t;
last = t;
}
}
void Append_2(int elem)
{
Node* t , *last;
t = new Node;
t->data = elem;
t->next = NULL;
if(second == 0)
second = last = t;
else
{
last->next = t;
last = t;
}
}
//void SortMerge(struct Node *p , struct Node *q);
int main()
{
Append_1(3);
Append_1(7);
Display(first);
Append_2(10);
Append_2(14);
Append_2(21);
Display(second);
//SortMerge(first , second);
Display(third);
return 0;
}
You can create a class like here:
struct Node{
int data;
Node* next;
Node* previous;
};
class Graph{
public:
Graph(int = 0);
~Graph();
void display_left_right();
void display_right_left();
void append(int);
void append_at_pos(int,int);
void prepend(int);
int get_num_elt();
int get_data_at_pos(int);
private:
Node* head;
Node* tail;
int num_elt=0;
};
Graph::Graph(int first_data){
head = new Node;
head->next = NULL;
head->previous = NULL;
head->data = first_data;
tail = head;
num_elt++;
}
Graph::~Graph(){
Node* main_traverser = head;
while(main_traverser){
main_traverser = head->next;
delete head;
head = main_traverser;
}
std::cout <<"Graph deleted!" << std::endl;
}
void Graph::display_left_right(){
Node* traverser = head;
while(traverser != NULL){
std::cout << traverser->data << " ";
traverser = traverser->next;
}
std::cout << std::endl;
}
void Graph::display_right_left(){
Node* traverser = tail;
while(traverser != NULL){
std::cout << traverser->data << " ";
traverser = traverser->previous;
}
std::cout << std::endl;
}
void Graph::append(int new_data){
Node* add = new Node;
add->data = new_data;
add->next = NULL;
add->previous = tail;
tail->next = add;
tail = add;
num_elt++;
}
void Graph::append_at_pos(int pos, int new_data){
if(pos > num_elt+1 || pos<=0){std::cout << "Wrong position!" << std::endl; return;}
if(pos==1){
prepend(new_data);
return;
}
if(pos==num_elt+1){
append(new_data);
return;
}
Node* add = new Node;
Node* traverser = head;
add->data = new_data;
for(int i=0; i<pos-2; i++){
traverser = traverser->next;
}
add->next = traverser->next;
add->previous = traverser;
traverser->next->previous = add;
traverser->next = add;
}
void Graph::prepend(int new_data){
Node* add = new Node;
add->next = head;
add->previous = NULL;
add->data = new_data;
head->previous = add;
head = add;
num_elt++;
}
int Graph::get_num_elt(){
return num_elt;
}
int Graph::get_data_at_pos(int pos){
Node* traverser = head;
if(pos <=0 || pos> num_elt){std::cout << "Wrong position!" << std::endl; return 0;}
for(int i=0; i<pos-1; i++){
traverser = traverser->next;
}
return traverser->data;
}
main(){
Graph a(2);
a.append(3);
a.append(4);
a.prepend(1);
a.display_left_right();
a.append_at_pos(1,6);
a.display_left_right();
std::cout << "data at 1: " << a.get_data_at_pos(1) << std::endl;
}
When you say "create multiple linked lists," I think you mean creating nodes to a linked list, which you have 2 append functions. I think the reason you have these 2 functions is because you do not know where to start traversing your linked list. For this reason, I think in your main function you should declare the head of the linked list, a single node that is the start. Set it's data and next to null, and then pass the head value into a function so it can start traversing from the head. Here is a generic append function that adds a node on the end, where the parameters are a reference to the head node, and the value for the new node:
void append(Node ** head, int new_data)
{
Node * select_node = * head;
// select node is set to the head node, and will traverse until it is at the end
while (select_node -> next != NULL)
{
// select node is set to the next node until it is NULL (end of linked list)
select_node = select_node -> next;
}
// now that select node is the last node, we need to make it's next value a node
// and that node should be a new node (allocated in heap) with the value of the input value
//and the next value be NULL (because it's the end of the linked list)
Node * next_node = new Node();
next_node -> data = new_data;
next_node -> next = NULL;
select_node -> next = next_node;
}

Swap two ListNode* in C++

Please help, I am totally lost here. This is leetcode problem no. 24, swap nodes in pairs.
I am getting this error in screeshot.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
void recurse(ListNode* head){
if(head!=nullptr and head->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next;
current->next = previous->next->next;
previous->next->next = current;
recurse(current);
}
}
public:
ListNode* swapPairs(ListNode* head) {
auto front = new ListNode(0, head);
recurse(front);
return front->next;
}
};
UPD: I add some comments to illustrate the OP's correct solution:
if(head!=nullptr and head->next!=nullptr
and head->next->next!=nullptr){
// p->[c]->[x]->y; swap(c, x); y can be null
auto previous = head, current = head->next;
// p->c->x->y
previous->next = current->next;
// p->x->y; c->x->y
current->next = previous->next->next;
// c->y; p->x->y
previous->next->next = current;
// p->x->c->y
recurse(current);
}
original answer 👇
if(head!=nullptr and head->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next; // previous->next = head->next->next
current->next = previous->next->next; // current->next = head->next->next->next
previous->next->next = current;
recurse(current);
}
In this if branch you only checked the head and head->next valid.
However you are attempt to invoke head->next->next->next later. Since head->next->next can be nullptr, your program will stop here.
You can find the right solution in the leetcode platform, and here I only reply on why this code doesn't work.
Thank you tieway59, you were right I just figured it out by myself. I was missing one more validation of head->next->next in if block of recurse function.
Here's my working code :
class Solution {
void recurse(ListNode* head){
if(head!=nullptr and head->next!=nullptr
and head->next->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next;
current->next = previous->next->next;
previous->next->next = current;
recurse(current);
}
}
public:
ListNode* swapPairs(ListNode* head){
auto front = new ListNode(0, head);
recurse(front);
return front->next;
}
};
To swap two existent adjacent nodes of a list there is no need to create a new node as you are doing
auto front = new ListNode(0, head);
Otherwise there will be a memory leak.
Instead what you need is to pass a pointer to a node by reference.
There is already standard function std::swap in the C++ library that can be used in your recursion function.
Here is a demonstration program.
#include <iostream>
#include <utility>
#include <functional>
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
void clear( ListNode * &head )
{
while ( head )
{
delete std::exchange( head, head->next );
}
}
void create( ListNode * &head, const int a[], size_t n )
{
clear( head );
for ( ListNode **current = &head; n--; current = &( *current )->next )
{
*current = new ListNode( *a++ );
}
}
std::ostream & display( const ListNode * head, std::ostream &os = std::cout )
{
for ( const ListNode *current = head; current != nullptr; current = current->next )
{
os << current->val << " -> ";
}
return os << "null";
}
void swap( ListNode * &current )
{
if ( current && current->next )
{
ListNode * &next = current->next;
std::swap( current, next );
std::swap( current->next, next->next );
swap( next );
}
}
int main()
{
ListNode *head= nullptr;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( head, a, sizeof( a ) / sizeof( *a ) );
display( head ) << '\n';
swap( head );
display( head ) << '\n';
clear( head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 0 -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> null

Reverse a linked list using recursion

The void reve(struct Node *head) and display(struct Node *head) methods take one argument - the head of the linked list. I want to print the whole linked list but my display function print only 4.
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *link;
};
void display(struct Node *head) {
if (head == NULL) {
return;
}
cout << head->data << "\t";
display(head->link);
//head = head->link;
}
struct Node *reve(struct Node *head) {
struct Node *p = head;
if (p->link == NULL) {
head = p;
return head;
}
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
struct Node *insert(struct Node *head, int new_data) {
Node *new_node = new Node();
new_node->data = new_data;
new_node->link = head;
head = new_node;
return head;
}
int main() {
Node *head = NULL;
head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
cout << "The linked list is: ";
//display(head);
head = reve(head);
display(head);
return 0;
}
Output
If you want the recursive way:
Node* reverse(Node* head)
{
if (head == NULL || head->next == NULL)
return head;
/* reverse the rest list and put
the first element at the end */
Node* rest = reverse(head->next);
head->next->next = head;
head->next = NULL;
/* fix the head pointer */
return rest;
}
/* Function to print linked list */
void print()
{
struct Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
The function reve does not return a value if p->link is not NULL.
Since head has more than 1 element, head = reve(head); has undefined behavior.
Reversing a linked list is much easier to implemented in a simple loop than with recursion:
struct Node *reve(struct Node *p) {
if (p != NULL) {
struct Node *prev = NULL;
while (p->link) {
struct Node *next = p->link;
p->link = prev;
prev = p;
p = next;
}
}
return p;
}
If your task requires recursion, you can make a extract the first node, reverse the remainder of the list and append the first node. Beware that this is not tail recursion, hence any sufficiently long list may cause a stack overflow.
struct Node *reve(struct Node *head) {
if (head != NULL && head->link != NULL) {
struct Node *first = head;
struct Node *second = head->link;
head = reve(second);
first->link = NULL; // unlink the first node
second->link = first; // append the first node
}
return head;
}
In C++ you need not to use keywords struct or class when an already declared structure or a class is used as a type specifier.
The function reve has undefined behavior.
First of all head can be equal to nullptr. In this case this statement
if (p->link == NULL) {
invokes undefined behavior.
Secondly the function returns nothing in the case when p->link is not equal to nullptr.
//...
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
Here is a demonstrative program that shows how the functions can be implemented. I used your C approach of including keyword struct when the structure is used as a type specifier.
#include <iostream>
struct Node
{
int data;
struct Node *link;
};
struct Node * insert( struct Node *head, int data )
{
return head = new Node{ data, head };
}
struct Node * reverse( struct Node *head )
{
if ( head && head->link )
{
struct Node *tail = head;
head = reverse( head->link );
tail->link->link = tail;
tail->link = nullptr;
}
return head;
}
std::ostream & display( struct Node *head, std::ostream &os = std::cout )
{
if ( head )
{
os << head->data;
if ( head->link )
{
os << '\t';
display( head->link, os );
}
}
return os;
}
int main()
{
struct Node *head = nullptr;
const int N = 10;
for ( int i = 0; i < N; i++ )
{
head = insert( head, i );
}
display( head ) << '\n';
head = reverse( head );
display( head ) << '\n';
return 0;
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
display is fine.
First thing I have notices is that you are trying to modify a copied value. For example, line 16. This code has no effect.
Note that you have a bug on insert: You return head instead of new_node.
Your version fails for lists with more than 1 item. reve() is supposed to return the last node of the original list, which you do not, hence lastNode would not point to the last node of the reversed list. So my advice is that you keep it aside.
So, reve:
struct Node* reve(struct Node* head) {
if (head->link == NULL) {
return head;
}
struct Node* lastNode = reve(head->link);
lastNode->link = head;
head->link = NULL;
return head;
}
and main:
int main() {
Node* head = NULL;
Node* last_node = head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
head = reve(head);
cout << "The linked list is: ";
// Now, last_node is the new head
display(last_node);
return 0;
}

Memory error in the destructor when reverse a linked list

I'm writing my own linked list class (for educational purposes) and here it is:
The node
#define PRINT(x) #x << " = " << x << " "
struct ListNode {
int val;
ListNode *next = nullptr;
ListNode(int x) : val(x), next(nullptr) {}
};
The class
class LinkedList{
private:
ListNode* _head;
unsigned long long int _size;
public:
LinkedList():_head(nullptr), _size(0) {}
LinkedList(ListNode* _h):_head(_h), _size(0) {
ListNode *node = _head;
while (node != nullptr) {
_size++;
node = node -> next;
}
}
~LinkedList() {
while (_head != nullptr) {
remove();
}
}
void add(const int& value) {
ListNode *node = new ListNode(value);
node -> next = _head;
_head = node;
_size++;
}
int remove() {
int v = _head -> val;
ListNode *node = _head;
_head = _head -> next;
delete node;
_size--;
return v;
}
void print() {
if (size() == 0) {
cout << "List is empty" << endl;
return;
}
ListNode *node = _head;
while (node -> next != nullptr) {
cout << node -> val << " -> ";
node = node -> next;
}
cout << node -> val << endl;
}
unsigned long long int size() { return _size; }
ListNode* head() { return _head; }
};
I've decided to solve a LeetCode problem Reverse Linked List and here's the solution that works:
// Returns the head of the reversed list
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* current = head;
while(current != nullptr) {
ListNode* next_elem = current -> next;
current -> next = prev;
prev = current;
current = next_elem;
}
return prev;
}
The problem is the following: LeetCode doesn't want my main() function, so for testing purposes I obviously used my own. Here it is:
int main() {
LinkedList L;
L.add(4);
L.add(3);
L.add(2);
L.add(1);
L.print();
LinkedList L2 (reverseList(L.head()));
cout << PRINT(L2.size()) << endl;
L2.print();
return 0;
}
The problem with that function is that I get this error: IO_FILE(3853,0x7fff75d44000) malloc: *** error for object 0x7f92284031b0: pointer being freed was not allocated
I can't figure out at what moment I'm trying to free a pointer that was not allocated. Where am I doing it?
It's not quite as I said in my comment, but the the rule of three is still a good read.
The problem is sligthly different: The constructor
LinkedList(ListNode* _h)
Just takes ownership of _h. When you initialize a LinkedList with this constructor like in
LinkedList L2 (reverseList(L.head()));
head is the same in L1 and L2. When those two lists go out of scope both will try to delete the same nodes (which works only once of cause).

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