Skip to content
Related Articles

Related Articles

Sort a K sorted Doubly Linked List | Set 2 (Using Shell Sort)

View Discussion
Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 12 Jan, 2022
View Discussion
Improve Article
Save Article

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<->56

Input: 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:

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 off 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);
    }
}

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 off 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 off 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>

Output: 

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)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!