Open In App

Flattening a linked list | Set 2

Improve
Improve
Like Article
Like
Save
Share
Report

Given a linked list where every node represents a linked list and contains two pointers of its type:  

  • Pointer to next node in the main list (we call it ‘right’ pointer in the below code)
  • Pointer to a linked list where this node is head (we call it ‘down’ pointer in the below code).

All linked lists are sorted. See the following example

Examples: 

Input: 
5 -> 10 -> 19 -> 28
| | | |
V V V V
7 20 22 35
| | |
V V V
8 50 40
| |
V V
30 45
Output: 5->7->8->10->19->20->22->28->30->35->40->45->50
Input:
5 -> 10 -> 19 -> 28
| |
V V
7 22
| |
V V
8 50
|
V
30
Output: 5->7->8->10->19->20->22->30->50

In the previous post, we have to use the merge() process of merge sort for linked lists to flatten the linked list. 
In this post, we will solve it using Heap.

Approach: The idea is to observe that from each top node there are N nodes that are connected in a downward direction but observe that all the downward nodes are in sorted order. So the task is to sort this entire thing in increasing order(or decreasing order).

  1. Push the head of all the linked lists in the downward list in the priority queue.
  2. Pop the smallest node from the priority queue.
  3. Check the location of the node so that the next node pointed by the current node can be pushed into the priority queue.
  4. Again pop out the smallest element and insert the next node pointed by the current node till the heap becomes empty.
  5. Keep on adding the data of nodes in a new linked list that are popped out to the new list.
  6. Print the linked list formed above.

Below is the implementation of the above approach:

C++




// C++ program for Flattening
// a linked list using Heaps
#include <bits/stdc++.h>
using namespace std;
 
// Structure of given Linked list
struct Node {
    int data;
    struct Node* right;
    struct Node* down;
 
    Node(int x)
    {
        data = x;
        right = NULL;
        down = NULL;
    }
};
 
// Function to print the
// linked list
void printList(Node* Node)
{
    while (Node != NULL) {
        printf("%d ", Node->data);
        Node = Node->down;
    }
}
 
// Function that compares the value
// pointed by node and returns true
// if first data is greater
struct compare {
    bool operator()(Node* a, Node* b)
    {
        return a->data > b->data;
    }
};
 
// Function which returns the root
// of the flattened linked list
Node* flatten(Node* root)
{
    Node* ptr = root;
    Node* head = NULL;
 
    // Min Heap which will return
    // smallest element currently
    // present in heap
    priority_queue<Node*,
            vector<Node*>,
             compare> pq;
 
    // Push the head nodes of each
    // downward linked list
    while (ptr != NULL) {
        pq.push(ptr);
        ptr = ptr->right;
    }
 
    // This loop will execute
    // till the map becomes empty
    while (!pq.empty()) {
 
        // Pop out the node that
        // contains element
        // currently in heap
        Node* temp = pq.top();
        pq.pop();
 
        // Push the next node pointed by
        // the current node into heap
        // if it is not null
        if (temp->down != NULL) {
            pq.push(temp->down);
        }
 
        // Create new linked list
        // that is to be returned
        if (head == NULL) {
            head = temp;
            ptr = temp;
            ptr->right = NULL;
        }
        else {
            ptr->down = temp;
            ptr = temp;
            ptr->right = NULL;
        }
    }
 
    // Pointer to head node
    // in the linked list
    return head;
}
 
// Create and push new nodes
void push(Node** head_ref, int new_data)
{
    Node* new_node = (Node*)malloc(sizeof(Node));
    new_node->right = NULL;
    new_node->data = new_data;
    new_node->down = (*head_ref);
 
    (*head_ref) = new_node;
}
 
// Driver Code
int main()
{
    Node* root = NULL;
 
    // Given Linked List
    push(&root, 30);
    push(&root, 8);
    push(&root, 7);
    push(&root, 5);
 
    push(&(root->right), 20);
    push(&(root->right), 10);
 
    push(&(root->right->right), 50);
    push(&(root->right->right), 22);
    push(&(root->right->right), 19);
 
    push(&(root->right->right->right), 45);
    push(&(root->right->right->right), 40);
    push(&(root->right->right->right), 35);
    push(&(root->right->right->right), 20);
 
    // Flatten the list
    root = flatten(root);
 
    // Print the flattened linked list
    printList(root);
 
    return 0;
}


Java




// Java program for Flattening
// a linked list using Heaps
import java.util.*;
 
// Linked list Node
class Node {
    int data;
    Node right, down;
    Node(int data)
    {
        this.data = data;
        right = null;
        down = null;
    }
}
 
class pair {
    int val;
    Node head;
 
    pair(Node head, int val)
    {
        this.val = val;
        this.head = head;
    }
}
 
// Class that compares the value
// pointed by node and make
// LinkedList sorted
class pairComp implements Comparator<pair> {
    public int compare(pair p1, pair p2)
    {
        return p1.val - p2.val;
    }
}
 
class GFG {
 
    // Function which returns the root
    // of the flattened linked list
    public static Node flatten(Node root)
    {
        Node ptr = root;
        Node h = null;
 
        // Min Heap which will return
        // smallest element currently
        // present in heap
        PriorityQueue<pair> pq
            = new PriorityQueue<pair>(
                        new pairComp());
 
        // Push the head nodes of each
        // downward linked list
        while (ptr != null) {
            pq.add(new pair(ptr, ptr.data));
            ptr = ptr.right;
        }
 
        // This loop will execute
        // till the pq becomes empty
        while (!pq.isEmpty()) {
 
            // Pop out the node that
            // contains element
            // currently in heap
            Node temp = pq.poll().head;
 
            // Push the next node pointed by
            // the current node into heap
            // if it is not null
            if (temp.down != null) {
                pq.add(new pair(temp.down,
                                temp.down.data));
            }
 
            // Create new linked list
            // that is to be returned
            if (h == null) {
                h = temp;
                ptr = temp;
                ptr.right = null;
            }
            else {
                ptr.down = temp;
                ptr = temp;
                ptr.right = null;
            }
        }
 
        // Pointer to head node
        // in the linked list
        return h;
    }
 
    // Create and push new nodes
    public static Node push(Node head_ref,
                            int data)
    {
 
        // Allocate the Node &
        // Put in the data
        Node new_node = new Node(data);
 
        // Make next of new Node as head
        new_node.down = head_ref;
 
        // Move the head to point to new Node
        head_ref = new_node;
 
        // return to link it back
        return head_ref;
    }
 
    // Function to print the
    // linked list
    public static void printList(Node h)
    {
        while (h != null) {
            System.out.print(h.data + " ");
            h = h.down;
        }
    }
 
    // Driver code
    public static void main(String args[])
    {
        Node head = null;
 
        head = push(head, 30);
        head = push(head, 8);
        head = push(head, 7);
        head = push(head, 5);
 
        head.right = push(head.right, 20);
        head.right = push(head.right, 10);
 
        head.right.right = push(
                  head.right.right, 50);
        head.right.right = push(
                  head.right.right, 22);
        head.right.right = push(
                  head.right.right, 19);
 
        head.right.right.right
            = push(
          head.right.right.right, 45);
        head.right.right.right
            = push(
              head.right.right.right, 40);
        head.right.right.right
            = push(
              head.right.right.right, 35);
        head.right.right.right
            = push(head.right.right.right, 20);
 
        // Flatten the list
        head = flatten(head);
 
        printList(head);
    }
}
 
// This code is contributed by Naresh Saharan
// and Sagar Jangra and Tridib Samanta


Python3




import heapq
 
# Linked list Node
class Node:
    def __init__(self, data):
        self.data = data
        self.right = None
        self.down = None
 
class pair:
    def __init__(self, head, val):
        self.val = val
        self.head = head
    def __lt__(self, other):
        return self.val < other.val
 
# Class that compares the value
# pointed by node and make
# LinkedList sorted
class pairComp:
    def __lt__(self, p1, p2):
        return p1.val < p2.val
 
# Function which returns the root
# of the flattened linked list
def flatten(root):
    ptr = root
    h = None
 
    # Min Heap which will return
    # smallest element currently
    # present in heap
    pq = []
 
    # Push the head nodes of each
    # downward linked list
    while ptr:
        heapq.heappush(pq, pair(ptr, ptr.data))
        ptr = ptr.right
 
    # This loop will execute
    # till the pq becomes empty
    while pq:
 
        # Pop out the node that
        # contains element
        # currently in heap
        temp = heapq.heappop(pq).head
 
        # Push the next node pointed by
        # the current node into heap
        # if it is not null
        if temp.down:
            heapq.heappush(pq, pair(temp.down, temp.down.data))
 
        # Create new linked list
        # that is to be returned
        if not h:
            h = temp
            ptr = temp
            ptr.right = None
        else:
            ptr.down = temp
            ptr = temp
            ptr.right = None
 
    # Pointer to head node
    # in the linked list
    return h
 
# Create and push new nodes
def push(head_ref, data):
    # Allocate the Node &
    # Put in the data
    new_node = Node(data)
 
    # Make next of new Node as head
    new_node.down = head_ref
 
    # Move the head to point to new Node
    head_ref = new_node
 
    # return to link it back
    return head_ref
 
# Function to print the
# linked list
def printList(h):
    while h:
        print(h.data, end=' ')
        h = h.down
 
# Driver code
head = None
 
head = push(head, 30)
head = push(head, 8)
head = push(head, 7)
head = push(head, 5)
 
head.right = push(head.right, 20)
head.right = push(head.right, 10)
 
head.right.right = push(head.right.right, 50)
head.right.right = push(head.right.right, 22)
head.right.right = push(head.right.right, 19)
 
head.right.right.right = push(head.right.right.right, 45)
head.right.right.right = push(head.right.right.right, 40)
head.right.right.right = push(head.right.right.right, 35)
head.right.right.right = push(head.right.right.right, 20)
 
# Flatten the list
head = flatten(head)
 
printList(head)


C#




using System;
using System.Collections.Generic;
 
class Node
{
    public int data;
    public Node right, down;
 
    public Node(int data)
    {
        this.data = data;
        right = null;
        down = null;
    }
}
 
class pair
{
    public int val;
    public Node head;
 
    public pair(Node head, int val)
    {
        this.val = val;
        this.head = head;
    }
}
 
class pairComp : IComparer<pair>
{
    public int Compare(pair p1, pair p2)
    {
        return p1.val - p2.val;
    }
}
 
class PriorityQueue<T>
{
    // List to store items and IComparer to handle comparison
    private List<T> items = new List<T>();
    private IComparer<T> comparer;
 
    // Constructor to initialize the PriorityQueue
    public PriorityQueue(IComparer<T> comparer)
    {
        this.comparer = comparer;
    }
 
    // Method to add items to the PriorityQueue
    public void Add(T item)
    {
        items.Add(item);
        items.Sort(comparer); // Sorts the items after each addition
    }
 
    // Method to check if the PriorityQueue is empty
    public bool IsEmpty()
    {
        return items.Count == 0;
    }
 
    // Method to get the top item from the PriorityQueue (by priority)
    public T Poll()
    {
        T first = items[0];
        items.RemoveAt(0);
        return first;
    }
}
 
class GFG
{
    // Method to flatten the linked list
    public static Node Flatten(Node root)
    {
        Node ptr = root;
        Node h = null;
 
          // Create a priority queue of pair elements
        var pq = new PriorityQueue<pair>(new pairComp());
 
        // Traverses the linked list and adds nodes to the priority queue
        while (ptr != null)
        {
            pq.Add(new pair(ptr, ptr.data));
            ptr = ptr.right;
        }
 
        // Flatten the linked list by rearranging nodes based on priority
        while (!pq.IsEmpty())
        {
            Node temp = pq.Poll().head;
 
            if (temp.down != null)
            {
                  // Add down nodes to the priority queue
                pq.Add(new pair(temp.down, temp.down.data));
            }
 
            if (h == null)
            {
                h = temp;
                ptr = temp;
                ptr.right = null;
            }
            else
            {
                ptr.down = temp;
                ptr = temp;
                ptr.right = null;
            }
        }
 
        return h;
    }
 
    // Method to push a new node with data at the start of the list
    public static Node push(Node head_ref, int data)
    {
        Node new_node = new Node(data);
        new_node.down = head_ref;
        head_ref = new_node;
        return head_ref;
    }
 
    // Method to print the linked list
    public static void printList(Node h)
    {
        while (h != null)
        {
            Console.Write(h.data + " ");
            h = h.down;
        }
    }
 
    public static void Main(string[] args)
    {
        // Create the linked list structure
        Node head = null;
 
        // Add nodes to the linked list
        head = push(head, 30);
        head = push(head, 8);
        head = push(head, 7);
        head = push(head, 5);
 
        head.right = push(head.right, 20);
        head.right = push(head.right, 10);
 
        head.right.right = push(head.right.right, 50);
        head.right.right = push(head.right.right, 22);
        head.right.right = push(head.right.right, 19);
 
        head.right.right.right = push(head.right.right.right, 45);
        head.right.right.right = push(head.right.right.right, 40);
        head.right.right.right = push(head.right.right.right, 35);
        head.right.right.right = push(head.right.right.right, 20);
 
        // Flatten the list
        head = Flatten(head);
 
        // Print the flattened list
        printList(head);
    }
}


Javascript




// JavaScript program for Flattening
// a linked list using Heaps
 
// Linked list Node
class Node {
    constructor(data) {
        this.data = data;
        this.right = null;
        this.down = null;
    }
}
 
class Pair {
    constructor(head, val) {
        this.val = val;
        this.head = head;
    }
 
    // Compare the value
    // pointed by node and make
    // LinkedList sorted
    static compare(p1, p2) {
        return p1.val - p2.val;
    }
}
 
// Function which returns the root
// of the flattened linked list
function flatten(root) {
    let ptr = root;
    let h = null;
 
    // Array which will return
    // smallest element currently
    // present in heap
    const pq = [];
 
    // Push the head nodes of each
    // downward linked list
    while (ptr) {
        pq.push(new Pair(ptr, ptr.data));
        ptr = ptr.right;
    }
 
    // This loop will execute
    // till the pq becomes empty
    while (pq.length > 0) {
 
        // Pop out the node that
        // contains element
        // currently in heap
        const temp = pq.sort(Pair.compare).shift().head;
 
        // Push the next node pointed by
        // the current node into heap
        // if it is not null
        if (temp.down) {
            pq.push(new Pair(temp.down, temp.down.data));
        }
 
        // Create new linked list
        // that is to be returned
        if (!h) {
            h = temp;
            ptr = temp;
            ptr.right = null;
        } else {
            ptr.down = temp;
            ptr = temp;
            ptr.right = null;
        }
    }
 
    // Pointer to head node
    // in the linked list
    return h;
}
 
// Create and push new nodes
function push(head_ref, data) {
    // Allocate the Node &
    // Put in the data
    const new_node = new Node(data);
 
    // Make next of new Node as head
    new_node.down = head_ref;
 
    // Move the head to point to new Node
    head_ref = new_node;
 
    // return to link it back
    return head_ref;
}
 
// Function to print the
// linked list
function printList(h) {
    let temp = [];
    while (h) {
        temp.push(h.data, ' ');
        h = h.down;
    }
    console.log(temp.join(''));
}
 
// Driver code
let head = null;
 
head = push(head, 30);
head = push(head, 8);
head = push(head, 7);
head = push(head, 5);
 
head.right = push(head.right, 20);
head.right = push(head.right, 10);
 
head.right.right = push(head.right.right, 50);
head.right.right = push(head.right.right, 22);
head.right.right = push(head.right.right, 19);
 
head.right.right.right = push(head.right.right.right, 45);
head.right.right.right = push(head.right.right.right, 40);
head.right.right.right = push(head.right.right.right, 35);
head.right.right.right = push(head.right.right.right, 20);
 
// Flatten the list
head = flatten(head);
 
printList(head);
 
// Contributed by sdeadityasharma


Output

5 7 8 10 19 20 20 22 30 35 40 45 50 

Time Complexity: O(k * log k) + O((N-k) * log k) = O(N * log k), where ‘k‘ is the number of nodes in the topmost horizontal linked list and ‘N‘ is the total number of nodes among all the linked lists. ‘log k‘ time is taken for the min-heapify procedure.
Auxiliary Space: O(k) for the min-heap, where ‘k‘ is the number of nodes in the topmost horizontal linked list. The min-heap will have at the most ‘k‘ number of nodes at any time.
 



Last Updated : 25 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads