Showing posts with label linked list. Show all posts
Showing posts with label linked list. Show all posts

Saturday, April 26, 2014

Merge Two Sorted Linked Lists

This post talks about, merging two sorted linked lists into one sorted linked list. The implementation doesn't use any extra space(except head node overhead). It's implemented below in Java, but same approach can be applied in any programming language.

Merge method takes two sorted linked lists as arguments and returns the head of the final merged linked list.

First Linked List       1 -->6 -->13 -->49 -->114 -->null
Second Linked List   5 -->9 -->23 -->null
Merged Linked List  1 -->5 -->6 -->9 -->13 -->23 -->49 -->114 -->null

The merge method uses a new node i.e. merged to generate the merged list. It starts with the smallest node of either list and keeps on adding the next larger node (in while loop). Method will come out of the while loop if either of the lists is traveled fully. Then the remaining nodes of other list get appended to the end of merged list.

 package algo;  
   
 /**  
  * LinkedList implementation which merges two sorted linkedlists without using  
  * any extra space (except overhead of head)  
  *   
  * @author Siddheshwar  
  *   
  */  
 public class MergeLinkedList<E extends Comparable<E>> {  
      Node<E> head;  
   
      /**  
       * merges two sorted linked lists and returns node of the merged list  
       *   
       */  
      public Node<E> merge(Node<E> n1, Node<E> n2) {  
           Node<E> merged = null; // pointer for merged list  
           Node<E> resp = null; // head of merged list  
   
           if (n1 == null)  
                return n2;  
           if (n2 == null)  
                return n1;  
   
           int cmp = 0;  
           while (n1 != null && n2 != null) {  
                cmp = n1.compareTo(n2);  
                if (merged == null) {  
                     if (cmp < 0) {  
                          merged = n1;  
                          n1 = n1.next;  
                     } else {  
                          merged = n2;  
                          n2 = n2.next;  
                     }  
                     resp = merged; // points to head of merged list  
                } else {  
                     if (cmp < 0) {  
                          merged.next = n1;  
                          n1 = n1.next;  
                          merged = merged.next;  
                     } else {  
                          merged.next = n2;  
                          n2 = n2.next;  
                          merged = merged.next;  
                     }  
                }  
           }  
   
           // append the remaining nodes of the either list  
           if (n1 == null)  
                merged.next = n2;  
           else  
                merged.next = n1;  
   
           return resp;  
      }  
   
      /**  
       * Node implementation which forms linked list  
       *   
       */  
      private static class Node<E extends Comparable<E>> implements  
                Comparable<Node<E>> {  
           E data;  
           Node<E> next;  
   
           public Node(E data, Node<E> next) {  
                super();  
                this.data = data;  
                this.next = next;  
           }  
   
           @Override  
           public String toString() {  
                return "Node [data=" + data + "]";  
           }  
   
           @Override  
           public int compareTo(Node<E> node) {  
                return this.data.compareTo(node.data);  
           }  
      }  
   
      public void addNodeLast(E d) {  
           if (head == null) {  
                head = new Node<E>(d, null);  
                return;  
           }  
           Node<E> h = head;  
           while (h.next != null)  
                h = h.next;  
           h.next = new Node<E>(d, null);  
      }  
   
      public void print() {  
           Node<E> h = head;  
           while (h != null) {  
                System.out.print(h.data + " -->");  
                h = h.next;  
           }  
           System.out.println("null");  
      }  
   
      public void print(Node<E> head) {  
           Node<E> h = head;  
           while (h != null) {  
                System.out.print(h.data + " -->");  
                h = h.next;  
           }  
           System.out.println("null");  
      }  
   
      /**  
       * Main method for testing  
       */  
      public static void main(String[] args) {  
           /**  
            * First linked list  
            */  
           MergeLinkedList<Integer> l1 = new MergeLinkedList<>();  
           l1.addNodeLast(1);  
           l1.addNodeLast(6);  
           l1.addNodeLast(13);  
           l1.addNodeLast(49);  
           l1.addNodeLast(114);  
           System.out.print("First Linked List :");  
           l1.print(l1.head);  
   
           /**  
            * Second linked list  
            */  
           MergeLinkedList<Integer> l2 = new MergeLinkedList<>();  
           l2.addNodeLast(5);  
           l2.addNodeLast(9);  
           l2.addNodeLast(23);  
           System.out.print("Second Linked List :");  
           l2.print(l2.head);  
   
           /**  
            * Final, merged linked list  
            */  
           MergeLinkedList<Integer> mergedList = new MergeLinkedList<>();  
           mergedList.head = mergedList.merge(l1.head, l2.head);  
           System.out.print("Merged Linked List :");  
           mergedList.print(mergedList.head);  
      }  
 }  
   

I have implemented it in Java using Generics so that you can store any type of object in the node. One of the tricky aspects is the implementation of the Comparable interface. 
Note that compareTo(..) method in the Node class basically compares the data stored in the node. And it assumes that the data is comparable. This will be perfectly fine as long as you are using inbuilt classes like String, Integer as they implement Comparable. But if you need to compare your own custom object (say Student, Animal), make sure that the class implements the Comparable interface.


Tuesday, January 14, 2014

Detect Loop in a Linked List

Existence of loop/cycles in a linked list means that last node points to one of the existing nodes of the list instead of pointing to null. So normal approach of traversing the list until you find null will NOT work here. This is one of the most interesting and tricky problems of Linked List. In below sample; next pointer of Node 5, points to Node 3.

                                              1 -> 2 -> 3 -> 4 -> 5 -> 3


This is solved by the famous Tortoise and Hare Algorithm; also known as Floyd algorithm. I wanted to write this article on same, but dropped plan after finding few nicely written posts. So, in this post, I will be explaining an alternative and much easier solution to detect the cycle in a linked list.


Detect Using Map

Tortoise and Hare algorithm uses two pointers (slow and fast); these pointers traverse the list in such a way that fast runs twice as fast as the slower pointer. So, if both these pointers meet at some node; then it means there is a cycle/loop. This approach basically checks if a node points to an already traversed node (5 points to 3 in above example). 

An alternative approach is quite trivial compared to the normal approach but; it has some space overhead. Loop can be identified by storing nodes in a Map. And before putting the node; check if the node already exists. If the node already exists in the map then it means that Linked List has a loop.

Below method detects the loop. I have not given full source code of the linked list. You can get it from my earlier post here.


 public boolean loopDetector(Node<E> first) {  
           Node<E> t = first;  
           Map<Node<E>, Node<E>> map = new IdentityHashMap<Node<E>, Node<E>>();  
           while (t != null) {  
                if (map.containsKey(t)) {  
                     System.out.println(" duplicate Node is --" + t  
                               + " having value :" + t.data);  
   
                     return true;  
                } else {  
                     map.put(t, t);  
                }  
                t = t.next;  
           }  
           return false;  
      }  

To test it, make sure that you create a linked list with a loop. To create a loop you need to refactor add method to take next reference as well. So in case of the cycle next reference will point to an existing node instead of pointing to null.

obj.add(item, previousNode);

Note here that, I have used, IdentityHashMap [Java Doc] implementation of Java. Instead of object equality, IdentityHashMap uses reference equality. It considers two keys k1 and k2 equal if and only if (k1==k2). So this map fits aptly in our case to check if the node is already added.

Friday, January 3, 2014

Find middle node of a LinkedList

Finding the middle node of a linked list by traversing the list twice is trivial. But what makes this problem interesting is; If you have to do this in a single pass/traversal. 

Here, I will be using Java to solve this problem. Java provides a built-in API LinkedList, so using inbuilt iterator and size method of this API, the middle element can be easily found. But that would defy the whole intention behind this problem. Better do it more crude way! 

In Linked List post, I have created a custom single linked list. I am reusing the same class here, and have added a new method/s to find the middle node.

Find Middle Node

Approach to find the middle node is: keep two references, one pointing to middle and other pointing to end of the list. Keep on traversing the list and make sure that middle reference always points to the middle node at any point of traversal. Done!!!

package algo;  
 /**  
  * Generic single linked list implementation with generics  
  *   
  * @author Siddheshwar  
  *   
  */  
 public class SingleLinkedList<E> {  
      Node<E> start; // points to the head or first node  
      /**  
       * Node class  
       */  
      private static class Node<E> {  
           E data;  
           Node<E> next;  
           public Node(E data, Node<E> next) {  
                this.data = data;  
                this.next = next;  
           }  
           public E getData() {  
                return data;  
           }  
           public Node<E> getNext() {  
                return next;  
           }  
           public void setNext(Node<E> next) {  
                this.next = next;  
           }  
      }  
      public void add(E d) {
           if (start == null) {  
                start = new Node<E>(d, null);  
           } else {  
                Node<E> tmp = start;  
                while (tmp.getNext() != null) {  
                     tmp = tmp.getNext();  
                }  
                tmp.setNext(new Node<E>(d, null));   // add at the end of list  
           }  
      }  
      public void print() {  
           Node<E> current = start;  
           System.out.print(" values in link-list are :");  
           while (current != null) {  
                System.out.print(current.getData() + "--> ");  
                current = current.getNext();  
           }  
           System.out.println("null");  
      }  
      /**  
       * Finds middle object/node of linked list  
       * Approach : increment middle node alternate time 
       * (i.e. when count is odd)  
       */  
      public Node<E> findMiddleNode(Node<E> start) {  
           if (start == null)  
                return null;  
           Node<Integer> end = (Node<Integer>) start;  
           Node<Integer> middle = (Node<Integer>) start;  
           int count = 0;  
           while (end != null) {  
                end = end.getNext();  
                // move middle pointer alternate times  
                if (count % 2 == 1) {  
                     middle = middle.getNext();  
                }  
                count++;  
           }  
           return (Node<E>) middle;  
      }  
      /**  
       * Find middle node - Alternate approach 
       *   
       */  
      public Node<E> middleNode(Node<E> start) {  
           if (start == null)  
                return null;  
           Node<Integer> end = (Node<Integer>) start;  
           Node<Integer> middle = (Node<Integer>) start;  
           while (end != null) {  
                end = end.getNext();  
                if (end != null) {  
                     end = end.getNext();  
                     middle = middle.getNext();  
                }  
           }  
           return (Node<E>) middle;  
      }  
      public static void main(String[] args) {  
           SingleLinkedList<Integer> sll = new SingleLinkedList<>();  
           sll.add(1);  
           sll.add(2);  
           sll.add(3);  
           sll.add(4);  
           sll.add(5);  
           sll.add(6);  
           sll.add(7);  
           sll.print();  
           Node<Integer> middle = sll.middleNode(sll.start);  
           System.out.println("Middle value --:" + middle.getData());  
           middle = sll.findMiddleNode(sll.start);  
           System.out.println("Middle value --:" + middle.getData());  
      }  
 } 

Output:
 values in link-list are :1--> 2--> 3--> 4--> 5--> 6--> 7--> null
Middle value --:4
Middle value --:4

Note that there are two methods to find the middle node; both are more or less same, though.


Complexity:
End reference traverses the list fully once (i.e. O(n) ) and middle reference traverses only till the middle of the list (i.e. n/2 nodes / O(n)). Summing up those two still makes its complexity as O(n).

You can use this approach to solve similar problems:
  • Find the nth node from the last.
  • Remove the middle node of the list. 
  • Pairwise swapping of nodes (1->2->3->4 becomes 2->1->4->3)
  • Split a linked list in 2 ( or 3) equal  or close to equal linked list
  • Delete the repeated elements from a linked list.
  • Append last n nodes of the list to the beginning. 

Wednesday, April 17, 2013

Implementing Single Linked List in Java

Before I start, let me caution you that this post is not about LinkedList [Java Doc] API of Java. LinkedList API of Java is a specialized implementation of doubly linked list. This post talks in general about linked data structures (i.e. linked list) and implementation of single linked list in Java.


Definition

Linked data structures are composed of distinct chunks of memory; and these chunks are bounded/linked through pointers. These memory chunks are referred as nodes. As nodes are not stored in contiguous memory so adding or removing individual nodes is quite easier (unlike an array). But one drawback is that random access to node is not possible. 
typedef struct node {
         item_type item;  //data stored in node
         struct list *next;  //points to successor 
}node;
In C language; *p denotes the item that is pointed to by pointer p, and &x denotes the address (i.e. pointer) of a particular variable x. A special null value is used to denote the termination of the list. 


C pointers are similar to Java references; as both of them point to something.

Let's cover them in detail

C pointers:
    int var = 20; 
    int *ip;   //pointer to an integer
    ip = &var;  //store address of var in pointer ip

Java references:
     Integer x = new Integer(20);  //x is reference to Integer

Usually, Java references are implemented as pointers in C; but specification doesn't say it explicitly. Java reference should be just an abstraction on C pointers (i.e. references in Java will be implemented using C pointers). I am not going to stress if both are same or not; it's debatable!

Implementation

Below is custom single linked list implementation in Java. I have just provided add and print method.

package algo;  
   
 /**  
  * Generic single linked list implementation with generics  
  *   
  * @author Siddheshwar   
  */  
 public class SingleLinkedList<E> {  
      Node<E> start; // points to the head or first node  
   
      /**  
       * Node class    
       */  
      private class Node<E> {  
           E data;  
           Node<E> next;  
   
           public Node(E data, Node<E> next) {  
                this.data = data;  
                this.next = next;  
           }  
   
           public E getData() {  
                return data;  
           }  
   
           public Node<E> getNext() {  
                return next;  
           }  
   
           public void setNext(Node<E> next) {  
                this.next = next;  
           }  
      }  
   
      public void add(E d) { // add at the end of list  
           if (start == null) {  
                start = new Node<E>(d, null);  
           } else {  
                Node<E> tmp = start;  
                while (tmp.next != null) {  
                     tmp = tmp.next;  
                }  
                tmp.setNext(new Node<E>(d, null));  
           }  
      }  
   
      public void print() {  
           Node<E> current = start;  
           System.out.print(" values in link-list are :");  
           while (current != null) {  
                System.out.print(current.getData() + "--> ");  
                current = current.getNext();  
           }  
           System.out.println("null");  
      }  
   
      public static void main(String[] args) {  
           SingleLinkedList<String> sll = new SingleLinkedList<>();  
           sll.add("abc");  
           sll.add("def");  
           sll.print();  
      }  
 } 

Output : 
values in link-list are :abc--> def--> null

Complexity of common operations 
  1.  Insert/Update/delete at end of list: O(n) . Need to traverse whole list.  
  2.  Insert at the beginning/head of the list : O(1)
  3.  Find the size of list : O(n). But it can be achieved in O(1) if you keep track of the count in a separate attribute (increment its value on each addition and decrement on each deletion).
References from Java
  1. LinkedList  [Java Doc] : Doubly linked list implementation of the List and Deque interfaces.
  2. LinkedHashMap [Java Doc] : Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. Linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map.
  3. LinkedHashSet [Java Doc] : Hash table and linked list implementation of the Set interface, with predictable iteration order.