0% found this document useful (0 votes)
54 views

Linked List

The document describes how to implement merge sort to sort a linked list. It involves dividing the linked list into two halves recursively, sorting each half using merge sort recursively, and then merging the two sorted halves using a sorted merge operation. Key steps include: 1. Recursively dividing the linked list into two halves using a front/back split. 2. Recursively applying merge sort to each half. 3. Merging the two sorted halves using a sorted merge operation that compares nodes and inserts in sorted order.

Uploaded by

sri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views

Linked List

The document describes how to implement merge sort to sort a linked list. It involves dividing the linked list into two halves recursively, sorting each half using merge sort recursively, and then merging the two sorted halves using a sorted merge operation. Key steps include: 1. Recursively dividing the linked list into two halves using a front/back split. 2. Recursively applying merge sort to each half. 3. Merging the two sorted halves using a sorted merge operation that compares nodes and inserts in sorted order.

Uploaded by

sri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 22

LINKEDLIST

Reverse a Linked List in groups of given size


• Given a linked list, write a function to reverse every k node (where k is
an input to the function).
• Example:

• Input: 1->2->3->4->5->6->7->8->NULL, K = 3
• Output: 3->2->1->6->5->4->8->7->NULL
• Input: 1->2->3->4->5->6->7->8->NULL, K = 5
• Output: 5->4->3->2->1->8->7->6->NULL
Algorithm
• reverse(head, k)

• Reverse the first sub-list of size k. While reversing keep track of the next
node and previous node. Let the pointer to the next node be next and
pointer to the previous node be prev. See this post for reversing a
linked list.
• head->next = reverse(next, k) ( Recursively call for rest of the list and
link the two sub-lists )
• Return prev ( prev becomes the new head of the list (see the diagrams
of an iterative method of this post )
Node* reverse(Node* head, int k)
#include <bits/stdc++.h> {
using namespace std; // base case
if (!head)
/* Link list node */ return NULL;
class Node { Node* current = head;
Node* next = NULL;
public:
Node* prev = NULL;
int data; int count = 0;
Node* next;
}; /*reverse first k nodes of the linked list */
while (current != NULL && count < k) {
/* Reverses the linked list in groups next = current->next;
current->next = prev;
of size k and returns the pointer
prev = current;
to the new head node. */ current = next;
count++;
}
/* next is now a pointer to (k+1)th node void push(Node** head_ref, int new_data)
Recursively call for the list starting from {
current. /* allocate node */
And make rest of the list as next of first Node* new_node = new Node();
node */
if (next != NULL) /* put in the data */
head->next = reverse(next, k); new_node->data = new_data;

/* prev is new head of the input list */ /* link the old list off the new node */
return prev; new_node->next = (*head_ref);
}
/* move the head to point to the new node
/* UTILITY FUNCTIONS */ */
/* Function to push a node */ (*head_ref) = new_node;
}
push(&head, 9);
/* Function to print linked list */
push(&head, 8);
void printList(Node* node)
push(&head, 7);
{
push(&head, 6);
while (node != NULL) {
push(&head, 5);
cout << node->data << " ";
push(&head, 4);
node = node->next;
push(&head, 3);
}
push(&head, 2);
}
push(&head, 1);
/* Driver code*/
cout << "Given linked list \n";
int main() printList(head);
{ head = reverse(head, 3);
/* Start with the empty list */
Node* head = NULL; cout << "\nReversed Linked list \n";
printList(head);
/* Created Linked list return (0);
is 1->2->3->4->5->6->7->8->9 */ }
Output
Given linked list
123456789

Reversed Linked list


321654987

Complexity Analysis:
Time Complexity: O(n).
Traversal of the list is done only once, and it has ‘n’ elements.
Auxiliary Space: O(n/k).
For each Linked List of size n, n/k or (n/k)+1 calls will be made during the
recursion.
Merge Sort for Linked Lists
• Merge sort is often preferred for sorting a linked list.

• The slow random-access performance of a linked list makes some


other algorithms (such as quicksort) perform poorly, and others (such
as heapsort) completely impossible.
MergeSort(headRef)

1) If the head is NULL or there is only one element in the Linked List
then return.

2) Else divide the linked list into two halves.


FrontBackSplit(head, &a, &b); /* a and b are two halves */

3) Sort the two halves a and b.


MergeSort(a);
MergeSort(b);

4) Merge the sorted a and b (using SortedMerge() discussed here)


and update the head pointer using headRef.
*headRef = SortedMerge(a, b);
#include <bits/stdc++.h> void MergeSort(Node** headRef)
using namespace std; {
Node* head = *headRef;
Node* a;
/* Link list node */ Node* b;
class Node {
public: /* Base case -- length 0 or 1 */
int data; if ((head == NULL) || (head->next == NULL)) {
return;
Node* next; }
};
/* Split head into 'a' and 'b' sublists */
/* function prototypes */ FrontBackSplit(head, &a, &b);
Node* SortedMerge(Node* a, Node* b);
/* Recursively sort the sublists */
void FrontBackSplit(Node* source, MergeSort(&a);
Node** frontRef, Node** MergeSort(&b);
backRef);
/* answer = merge the two sorted lists together */
/* sorts the linked list by changing next *headRef = SortedMerge(a, b);
}
pointers (not data) */
/* UTILITY FUNCTIONS */
Node* SortedMerge(Node* a, Node* b)
/* Split the nodes of the given list into front and back
{
halves,and return the two lists using the reference
Node* result = NULL;
parameters. If the length is odd, the extra node should
go in the front list.
/* Base cases */
Uses the fast/slow pointer strategy. */
if (a == NULL)
void FrontBackSplit(Node* source,
return (b);
Node** frontRef, Node** backRef)
else if (b == NULL)
{
return (a);
Node* fast;
Node* slow;
/* Pick either a or b, and recur */
slow = source;
if (a->data <= b->data) {
fast = source->next;
result = a;
/* Advance 'fast' two nodes, and advance 'slow' one
result->next = SortedMerge(a->next, b);
node */
}
while (fast != NULL) {
else {
fast = fast->next;
result = b;
if (fast != NULL) {
result->next = SortedMerge(a, b->next);
slow = slow->next;
}
fast = fast->next;
return (result);
}
}
}
/* 'slow' is before the midpoint in the list, so /* Function to insert a node at the beginning of
split it in two the linked list */
at that point. */ void push(Node** head_ref, int new_data)
*frontRef = source; {
*backRef = slow->next; /* allocate node */
slow->next = NULL; Node* new_node = new Node();
}
/* put in the data */
/* Function to print nodes in a given linked list new_node->data = new_data;
*/
void printList(Node* node) /* link the old list off the new node */
{ new_node->next = (*head_ref);
while (node != NULL) {
cout << node->data << " "; /* move the head to point to the new node
node = node->next; */
} (*head_ref) = new_node;
} }
/* Driver program to test above functions*/
int main()
{ Output:
/* Start with the empty list */ Sorted Linked List is:
Node* res = NULL;
Node* a = NULL; 2 3 5 10 15 20

/* Let us create a unsorted linked lists to test the functions


Created lists shall be a: 2->3->20->5->10->15 */
push(&a, 15); Time Complexity: O(n*log n)
push(&a, 10);
push(&a, 5); Space Complexity: O(n*log n)
push(&a, 20);
push(&a, 3);
push(&a, 2);

/* Sort the above created Linked List */


MergeSort(&a);

cout << "Sorted Linked List is: \n";


printList(a);

return 0;
}
QuickSort on Singly Linked List
/* A utility function to insert a node at
#include <cstdio> thebeginning of* linked list */
void push(struct Node** head_ref, int
#include <iostream> new_data)
using namespace std; {
/* allocate node */
struct Node* new_node = new Node;
/* a node of the singly linked
/* put in the data */
list */ new_node->data = new_data;
struct Node {
/* link the old list off the new node */
int data; new_node->next = (*head_ref);
struct Node* next;
/* move the head to point to the new node
}; */
(*head_ref) = new_node;
}
/* A utility function to print linked list */ // Partitions the list taking the last element as
void printList(struct Node* node) the pivot
{ struct Node* partition(struct Node* head,
while (node != NULL) { struct Node* end,
printf("%d ", node->data); struct Node** newHead,
node = node->next; struct Node** newEnd)
} {
printf("\n"); struct Node* pivot = end;
} struct Node *prev = NULL, *cur = head, *tail
= pivot;
// Returns the last node of the list
struct Node* getTail(struct Node* cur) // During partition, both the head and end of
{ the list
while (cur != NULL && cur->next != NULL) // might change which is updated in the
cur = cur->next; newHead and
return cur; // newEnd variables
}
else // If cur node is greater than pivot
while (cur != pivot) {
{
if (cur->data < pivot->data) { // Move cur node to next of tail,
// First node that has a value and change
less than the // tail
// pivot - becomes the new if (prev)
head prev->next = cur->next;
if ((*newHead) == NULL) struct Node* tmp = cur->next;
cur->next = NULL;
(*newHead) = cur;
tail->next = cur;
tail = cur;
prev = cur; cur = tmp;
cur = cur->next; }
} }
// here the sorting happens exclusive of the
// If the pivot data is the smallest element in end node
the struct Node* quickSortRecur(struct Node*
// current list, pivot becomes the head head,
if ((*newHead) == NULL) struct Node* end)
(*newHead) = pivot; {
// base condition
// Update newEnd to the current last node if (!head || head == end)
(*newEnd) = tail; return head;

// Return the pivot node Node *newHead = NULL, *newEnd = NULL;


return pivot;
} // Partition the list, newHead and newEnd
will be
// updated by the partition function
struct Node* pivot
= partition(head, end, &newHead,
&newEnd);
// If pivot is the smallest element - no need to recur // Recur for the list after the pivot element
// for the left part. pivot->next = quickSortRecur(pivot->next,
if (newHead != pivot) { newEnd);
// Set the node before the pivot node as NULL
struct Node* tmp = newHead; return newHead;
while (tmp->next != pivot) }
tmp = tmp->next;
tmp->next = NULL; // The main function for quick sort. This is a
wrapper over
// Recur for the list before pivot // recursive function quickSortRecur()
newHead = quickSortRecur(newHead, tmp); void quickSort(struct Node** headRef)
{
// Change next of last node of the left half to (*headRef)
// pivot = quickSortRecur(*headRef,
tmp = getTail(newHead); getTail(*headRef));
tmp->next = pivot; return;
} }
int main()
{ Output
struct Node* a = NULL; Linked List before sorting
push(&a, 5);
push(&a, 20); 30 3 4 20 5
push(&a, 4); Linked List after sorting
push(&a, 3); 3 4 5 20 30
push(&a, 30);
Time Complexity: O(nlogn)
cout << "Linked List before sorting \n";
printList(a); It takes O(n^2) in worst case and
quickSort(&a); O(nlogn) in average or best case.

cout << "Linked List after sorting \n"; Auxiliary Space: O(n)
printList(a);

return 0;
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy