Jan 082013
 

Given a Singly linked list with each node containing either 0, 1 or 2. Write code to sort the list.

Input List: 1 -> 1 -> 2 -> 0 -> 2 -> 0 -> 1 -> 0
Output    : 0 -> 0 -> 0 -> 1 -> 1 -> 1 -> 2 -> 2

Solution:

Usually Merge Sort can used to sort a Random linked list. But since this is special list, we can do the sorting in linear time. Below are the two methods, both linear time (O(n)-Time) which can be used to sort.

1. Counting occurrences.

1.Count the occurences of o's 1's and 2's in the list.
    (let ct0, ct1, ct2 represent the number of 0's, 1's and 2's in the list respectively)
2.traverse the list and
  - set first ct0 Nodes to 0
  - set next ct1 Nodes to 1
  - set first ct2 Nodes to 2

Code:

/** 
 * Sorts a Special list where each Node is either 0, 1 or 2.
 * Will bring all the zeros toward the head, All 2's toward the tail 
 * and leave all the 1's as it is. 
 * 
 * head passed by value, because nodes are not changing. Just copying data to the Node.
 */
void sortUsingcounting(Node* head)
{
    if(head == NULL || head->link == NULL)
        return;

    int count0 = 0;
    int count1 = 0;
    int count2 = 0;

    // Counting the occurences
    for(Node* temp=head; temp!=NULL; temp=temp->link)
    {
        switch(temp->data)
        {
        case 0:
            count0++; break;
        case 1:
            count1++; break;
        case 2:
            count2++; break;
        }
    }

    for(int i=0; i<count0; i++)
    {
        head->data = 0; 
        head = head->link;
    }

    for(int i=0; i<count1; i++)
    {
        head->data = 1; 
        head = head->link;
    }

    for(int i=0; i<count2; i++)
    {
        head->data = 2; 
        head = head->link;
    }
}

2. Moving Nodes to front & end of list.

For each Node in the list.
 - If it has 0
      Move to the Front of list
 - If it has 2 
      Move to the End of list 
 - If it has 1
      Do nothing.

 Code:

/** 
 * Sorts a Special list where each Node is either 0, 1 or 2.
 * Will bring all the zeros toward the head, All 2's toward the tail 
 * and leave all the 1's as it is. 
 * 
 * head passed by reference, because it may change.  
 */
void sortList(Node*& head)
{
    // Single element list is already sorted
    if(head == NULL || head->link == NULL)
        return;

    // pointer to last node in the list
    Node* last = head;
    int numOfNodes = 1;

    while(last->link != NULL)
    {
        last = last->link;
        numOfNodes++;
    }

    Node *tail = last;
    Node *ptr = head;
    Node *prev = head;

    for(int i=0; i<numOfNodes; i++)
    {
        Node* temp = ptr;
        ptr = ptr->link;

        if(temp->data == 0)
        {
            // Inserting at head (If First Node - Skip)
            if(prev != temp)
            {
                temp->link = head;
                head = temp;
                prev->link = ptr;
            }
        }
        else if(temp->data == 2)
        {
            // Inserting at the End.
            tail->link = temp;
            temp->link = NULL;
            tail = temp;

            // If first Node.
            if(prev == temp)
                head = prev = ptr;
            else
                prev->link = ptr;
        }
        else
        {
            if(prev != temp)
                prev = prev->link;
        }
    }
}

Time Complexity: Both the solutions takes O(n) time.
Extra space used: O(1) – Constant.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)