Given a doubly-linked list containing N nodes, where each node is at most K away from its target position in the list, the task is to sort the given doubly linked list.
Examples:
Input: DLL: 3<->6<->2<->12<->56<->8, K = 2
Output:
2<->3<->6<->8<->12<->56Input: DLL: 3<->2<->1<->5<->4
Output:
1<->2<->3<->4<->5
Note: Approaches using Insertion sort and using Min Heap Data structure have been discussed here.
Approach: Shell sort, which is a variation of Insertion sort can be used to solve this problem as well, by initializing the gap with K instead of N, as the list is already K-sorted.
Below is an implementation of the above approach:
C++
#include <bits/stdc++.h> using namespace std; // A class to represent a node in a doubly linked list class Node { public : int data; // data of the node Node* next; // pointer to the next node Node* prev; // pointer to the previous node // constructor to initialize the node Node( int d) { data = d; next = prev = nullptr; } }; // function to print the doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " " ; node = node->next; } } // function to return the ceiling value of gap/2 int nextGap( double gap) { if (gap < 2) return 0; return ( int )std:: ceil (gap / 2); } // function to sort a k sorted doubly linked list Node* sortAKSortedDLL(Node* head, int k) { if (head == nullptr || head->next == nullptr) return head; // for all gaps for ( int gap = k; gap > 0; gap = nextGap(gap)) { Node *i = head, *j = head; int count = gap; // move j pointer k nodes ahead while (count-- > 0) j = j->next; // i and j pointers compare and swap for (; j != nullptr; i = i->next, j = j->next) { if (i->data > j->data) { // if i is head, then replace head with j if (i == head) head = j; // swap i & j pointers Node* iTemp = i; i = j; j = iTemp; // i & j pointers are swapped because // below code only swaps nodes by // swapping their associated // pointers(i.e. prev & next pointers) // Now, swap both the // nodes in linked list Node *iPrev = i->prev, *iNext = i->next; if (iPrev != nullptr) iPrev->next = j; if (iNext != nullptr) iNext->prev = j; i->prev = j->prev; i->next = j->next; if (j->prev != nullptr) j->prev->next = i; if (j->next != nullptr) j->next->prev = i; j->prev = iPrev; j->next = iNext; } } } return head; } void push(Node** head_ref, int new_data) { Node* new_node = new Node(new_data); new_node->prev = nullptr; new_node->next = *head_ref; if (*head_ref != nullptr) { (*head_ref)->prev = new_node; } *head_ref = new_node; } //Driver code int main() { Node* head = nullptr; push(&head, 8); push(&head, 56); push(&head, 12); push(&head, 2); push(&head, 6); push(&head, 3); int k = 2; cout << "Original Doubly linked list:" << std::endl; printList(head); Node* sortedDLL = sortAKSortedDLL(head, k); cout << endl; cout << "Sorted Doubly linked list:" << std::endl; printList(sortedDLL); return 0; } // This code is contributed by lokeshpotta20. |
Java
// Java implementation to sort a k sorted doubly import java.util.*; class DoublyLinkedList { static Node head; static class Node { int data; Node next, prev; Node( int d) { data = d; next = prev = null ; } } // this method returns // the ceiling value of gap/2 int nextGap( double gap) { if (gap < 2 ) return 0 ; return ( int )Math.ceil(gap / 2 ); } // Sort a k sorted Doubly Linked List // Time Complexity: O(n*log k) // Space Complexity: O(1) Node sortAKSortedDLL(Node head, int k) { if (head == null || head.next == null ) return head; // for all gaps for ( int gap = k; gap > 0 ; gap = nextGap(gap)) { Node i = head, j = head; int count = gap; while (count-- > 0 ) j = j.next; for (; j != null ; i = i.next, j = j.next) { // if data at jth node is less than // data at ith node if (i.data > j.data) { // if i is head // then replace head with j if (i == head) head = j; // swap i & j pointers Node iTemp = i; i = j; j = iTemp; // i & j pointers are swapped because // below code only swaps nodes by // swapping their associated // pointers(i.e. prev & next pointers) // Now, swap both the // nodes in linked list Node iPrev = i.prev, iNext = i.next; if (iPrev != null ) iPrev.next = j; if (iNext != null ) iNext.prev = j; i.prev = j.prev; i.next = j.next; if (j.prev != null ) j.prev.next = i; if (j.next != null ) j.next.prev = i; j.prev = iPrev; j.next = iNext; } } } return head; } /* UTILITY FUNCTIONS */ // Function to insert a node // at the beginning of the // Doubly Linked List void push( int new_data) { // allocate node Node new_node = new Node(new_data); // since we are adding at the beginning, // prev is always NULL new_node.prev = null ; // link the old list of the new node new_node.next = head; // change prev of head node to new node if (head != null ) { head.prev = new_node; } // move the head to point // to the new node head = new_node; } // Function to print nodes // in a given doubly linked list // This function is same as // printList() of singly linked list void printList(Node node) { while (node != null ) { System.out.print(node.data + " " ); node = node.next; } } // Driver code public static void main(String[] args) { DoublyLinkedList list = new DoublyLinkedList(); // 3<->6<->2<->12<->56<->8 list.push( 8 ); list.push( 56 ); list.push( 12 ); list.push( 2 ); list.push( 6 ); list.push( 3 ); int k = 2 ; System.out.println( "Original Doubly linked list:" ); list.printList(head); Node sortedDLL = list.sortAKSortedDLL(head, k); System.out.println( "" ); System.out.println( "Doubly Linked List after sorting:" ); list.printList(sortedDLL); } } |
Python3
# Python implementation to sort a k sorted doubly linked list class Node: def __init__( self , data): self .data = data self . next = None self .prev = None class DoublyLinkedList: def __init__( self ): self .head = None # this method returns the ceiling value of gap/2 def next_gap( self , gap): if gap < 2 : return 0 return int (gap / 2 + 0.5 ) # Sort a k sorted Doubly Linked List # Time Complexity: O(n*log k) # Space Complexity: O(1) def sort_k_sorted_dll( self , head, k): if not head or not head. next : return head # for all gaps for gap in range (k, 0 , - 1 ): i = head j = head count = gap while count > 0 and j: j = j. next count - = 1 while j: # if data at jth node is less than data at ith node if i.data > j.data: # if i is head then replace head with j if i = = head: head = j # swap i & j pointers i_temp = i i = j j = i_temp # Now, swap both the nodes in linked list i_prev = i.prev i_next = i. next if i_prev: i_prev. next = j if i_next: i_next.prev = j i.prev = j.prev i. next = j. next if j.prev: j.prev. next = i if j. next : j. next .prev = i j.prev = i_prev j. next = i_next i = i. next j = j. next return head # Function to insert a node # at the beginning of the # Doubly Linked List def push( self , new_data): # allocate node new_node = Node(new_data) # since we are adding at the beginning, # prev is always None new_node.prev = None # link the old list of the new node new_node. next = self .head # change prev of head node to new node if self .head: self .head.prev = new_node # move the head to point # to the new node self .head = new_node # Function to print nodes # in a given doubly linked list def print_list( self , node): while node: print (node.data, end = " " ) node = node. next if __name__ = = "__main__" : dll = DoublyLinkedList() # 3<->6<->2<->12<->56<->8 dll.push( 8 ) dll.push( 56 ) dll.push( 12 ) dll.push( 2 ) dll.push( 6 ) dll.push( 3 ) # setting k value k = 2 # print("Original Doubly linked list:") dll.print_list(dll.head) # sorting the linked list sorted_dll = dll.sort_k_sorted_dll(dll.head, k) print ( "\nDoubly Linked List after sorting:" ) dll.print_list(sorted_dll) |
C#
// C# implementation to sort a k sorted doubly using System; public class DoublyList { public static Node head; public class Node { public int data; public Node next, prev; public Node( int d) { data = d; next = prev = null ; } } // this method returns // the ceiling value of gap/2 int nextGap( double gap) { if (gap < 2) return 0; return ( int )Math.Ceiling(gap / 2); } // Sort a k sorted Doubly Linked List // Time Complexity: O(n*log k) // Space Complexity: O(1) Node sortAKSortedDLL(Node head, int k) { if (head == null || head.next == null ) return head; // for all gaps for ( int gap = k; gap > 0; gap = nextGap(gap)) { Node i = head, j = head; int count = gap; while (count-- > 0) j = j.next; for (; j != null ; i = i.next, j = j.next) { // if data at jth node is less than // data at ith node if (i.data > j.data) { // if i is head // then replace head with j if (i == head) head = j; // swap i & j pointers Node iTemp = i; i = j; j = iTemp; // i & j pointers are swapped because // below code only swaps nodes by // swapping their associated // pointers(i.e. prev & next pointers) // Now, swap both the // nodes in linked list Node iPrev = i.prev, iNext = i.next; if (iPrev != null ) iPrev.next = j; if (iNext != null ) iNext.prev = j; i.prev = j.prev; i.next = j.next; if (j.prev != null ) j.prev.next = i; if (j.next != null ) j.next.prev = i; j.prev = iPrev; j.next = iNext; } } } return head; } /* UTILITY FUNCTIONS */ // Function to insert a node // at the beginning of the // Doubly Linked List void Push( int new_data) { // allocate node Node new_node = new Node(new_data); // since we are adding at the beginning, // prev is always NULL new_node.prev = null ; // link the old list of the new node new_node.next = head; // change prev of head node to new node if (head != null ) { head.prev = new_node; } // move the head to point // to the new node head = new_node; } // Function to print nodes // in a given doubly linked list // This function is same as // printList() of singly linked list void printList(Node node) { while (node != null ) { Console.Write(node.data + " " ); node = node.next; } } // Driver code public static void Main(String[] args) { DoublyList list = new DoublyList(); // 3<->6<->2<->12<->56<->8 list.Push(8); list.Push(56); list.Push(12); list.Push(2); list.Push(6); list.Push(3); int k = 2; Console.WriteLine( "Original Doubly linked list:" ); list.printList(head); Node sortedDLL = list.sortAKSortedDLL(head, k); Console.WriteLine( "" ); Console.WriteLine( "Doubly Linked List after sorting:" ); list.printList(sortedDLL); } } // This code is contributed by umadevi9616 |
Javascript
<script> // javascript implementation to sort a k sorted doubly var head; class Node { constructor(val) { this .data = val; this .prev = null ; this .next = null ; } } // this method returns // the ceiling value of gap/2 function nextGap(gap) { if (gap < 2) return 0; return parseInt( Math.ceil(gap / 2)); } // Sort a k sorted Doubly Linked List // Time Complexity: O(n*log k) // Space Complexity: O(1) function sortAKSortedDLL(head , k) { if (head == null || head.next == null ) return head; // for all gaps for ( var gap = k; gap > 0; gap = nextGap(gap)) { var i = head, j = head; var count = gap; while (count-- > 0) j = j.next; for (; j != null ; i = i.next, j = j.next) { // if data at jth node is less than // data at ith node if (i.data > j.data) { // if i is head // then replace head with j if (i == head) head = j; // swap i & j pointers var iTemp = i; i = j; j = iTemp; // i & j pointers are swapped because // below code only swaps nodes by // swapping their associated // pointers(i.e. prev & next pointers) // Now, swap both the // nodes in linked list var iPrev = i.prev, iNext = i.next; if (iPrev != null ) iPrev.next = j; if (iNext != null ) iNext.prev = j; i.prev = j.prev; i.next = j.next; if (j.prev != null ) j.prev.next = i; if (j.next != null ) j.next.prev = i; j.prev = iPrev; j.next = iNext; } } } return head; } /* UTILITY FUNCTIONS */ // Function to insert a node // at the beginning of the // Doubly Linked List function push(new_data) { // allocate node var new_node = new Node(new_data); // since we are adding at the beginning, // prev is always NULL new_node.prev = null ; // link the old list of the new node new_node.next = head; // change prev of head node to new node if (head != null ) { head.prev = new_node; } // move the head to point // to the new node head = new_node; } // Function to print nodes // in a given doubly linked list // This function is same as // printList() of singly linked list function printList(node) { while (node != null ) { document.write(node.data + " " ); node = node.next; } } // Driver code // 3<->6<->2<->12<->56<->8 push(8); push(56); push(12); push(2); push(6); push(3); var k = 2; document.write( "Original Doubly linked list:<br/>" ); printList(head); var sortedDLL = sortAKSortedDLL(head, k); document.write( "<br/>" ); document.write( "Doubly Linked List after sorting:<br/>" ); printList(sortedDLL); // This code contributed by umadevi9616 </script> |
Original Doubly linked list: 3 6 2 12 56 8 Doubly Linked List after sorting: 2 3 6 8 12 56
Time Complexity: O(N*log K)
gap is initialized with k and reduced to the ceiling value of gap/2 after each iteration. Hence, log k gaps will be calculated, and for each gap, the list will be iterated.
Space Complexity: O(1)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!