Monday, May 7, 2012

A good looking tree program

This is the a full code for creating a Tree Data Structure in Java. This class will be able to create modify and display a tree.

package com.test.ds;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;

public class TreeAppLL {

 private TreeNodeLL root;

 public TreeAppLL(TreeNodeLL root) {
  this.root = root;
 }
 
 public TreeNodeLL getRoot(){
  return this.root;
 }

 /**
  * Find the code. We are assuming we have a inorder tree
  * 
  * @param key
  * @return
  */
 public TreeNodeLL find(int key) {
  TreeNodeLL current = root;
  while (current.key != key) {
   if (key > current.key) {
    current = current.leftChild;
   } else {
    current = current.rightChild;
   }
   if (current == null) {
    return null;
   }
  }
  return current;
 }

 public void insert(int key, int data) {
  TreeNodeLL node = new TreeNodeLL(key, data);
  if (root == null) {
   root = node;
  }
  /*
   * So we have to insert after some node.
   */
  else {
   TreeNodeLL current = root;
   TreeNodeLL parent;
   while (true) {
    parent = current;
    if (key < current.key) {
     current = current.leftChild;
     if (current == null) {
      parent.leftChild = node;
      return;
     }
    } else {
     current = current.rightChild;
     if (current == null) {
      parent.rightChild = node;
      return;
     }
    }
   }
  }
 }

 public void traversal() throws IOException {
  do {
   System.out.println("Enter the choice");
   System.out.println("1. In Order");
   System.out.println("2. Post Order");
   System.out.println("3. Pre Order");
   System.out.println("Press 'e' to Exit ");
   System.out.print("Choice: ");
   String str = getInput();
   if (str.equalsIgnoreCase("e")) {
    break;
   }
   switch (Integer.parseInt(str)) {
   case 1:
    System.out.println("In order traversal is: ");
    inOrder(root);
    System.out.println("");
    break;
   case 2:
    System.out.println("Post order traversal is: ");
    postOrder(root);
    System.out.println("");
    break;
   case 3:
    System.out.println("Pre order traversal is: ");
    preOrder(root);
    System.out.println("");
    break;
   default:
    inOrder(root);
    System.out.println("");
    break;
   }
  } while (true);
 }

 private void inOrder(TreeNodeLL current) {
  if (current != null) {
   inOrder(current.leftChild);
   System.out.print(" " + current.key + " ");
   inOrder(current.rightChild);
  }
 }

 private void postOrder(TreeNodeLL current) {
  if (current != null) {
   postOrder(current.leftChild);
   postOrder(current.rightChild);
   System.out.print(" " + current.key + " ");
  }
 }

 private void preOrder(TreeNodeLL current) {
  if (current != null) {
   System.out.print(" " + current.key + " ");
   preOrder(current.leftChild);
   preOrder(current.rightChild);
  }
 }

 public boolean delete(int key) {
  TreeNodeLL current = root;
  TreeNodeLL parent = root;
  boolean isChildLeft = false;
  while (current.key != key) {
   parent = current;
   if (key < current.key) {
    isChildLeft = true;
    current = current.leftChild;
   } else {
    isChildLeft = false;
    current = current.rightChild;
   }
   if (current == null) {
    return false;
   }
  }

  /**
   * Case 1. Where the both the child nodes are null
   */
  if (current.leftChild == null && current.rightChild == null) {
   if (isChildLeft) {
    parent.leftChild = null;
   } else {
    parent.rightChild = null;
   }
  }
  /**
   * Case 2: where node to be deleted has one child
   * 
   */
  if (current.leftChild == null) {
   if (current == root) {
    root = current.rightChild;
   }
   if (isChildLeft) {
    parent.leftChild = current.rightChild;
   } else {
    parent.rightChild = current.rightChild;
   }
  } else if (current.rightChild == null) {
   if (current == root) {
    root = current.leftChild;
   }
   if (isChildLeft) {
    parent.leftChild = current.leftChild;
   } else {
    parent.rightChild = current.leftChild;
   }
  }

  /**
   * Case 3: When node to be deleted has both the children
   */
  else {
   TreeNodeLL successor = successor(current);
   if (current == root) {
    root = successor;
   } else if (isChildLeft) {
    parent.leftChild = successor;
   } else {
    parent.rightChild = successor;
   }
   successor.leftChild = current.leftChild;
  }
  return true;
 }

 /**
  * return the inorder Successor of sent node
  * 
  * @param delNode
  * @return
  */
 public TreeNodeLL successor(TreeNodeLL delNode) {
  TreeNodeLL current = delNode.rightChild;
  TreeNodeLL sussessorParent = delNode;
  TreeNodeLL sussessor = delNode;
  while (current != null) {
   sussessorParent = sussessor;
   sussessor = current;
   current = current.leftChild;
  }
  if (sussessor != delNode.rightChild) {
   sussessorParent.leftChild = sussessor.rightChild;
   sussessor.rightChild = delNode.rightChild;
  }
  return sussessor;
 }

 public void displayTree() {
  Stack globalStack = new Stack();
  globalStack.push(root);
  int nBlank = 32;
  boolean isRowBlank = false;
  System.out
    .println("-------------------------------------------------------------");
  while (isRowBlank == false) {
   Stack localStack = new Stack();
   isRowBlank = true;

   for (int i = 0; i < nBlank; i++) {
    System.out.print(" ");
   }

   while (globalStack.isEmpty() == false) {
    TreeNodeLL temp = globalStack.pop();
    if (temp != null) {
     System.out.print(temp.key + "," + temp.leftSum+ "," + temp.rightSum);
     localStack.push(temp.leftChild);
     localStack.push(temp.rightChild);

     if (temp.leftChild != null || temp.rightChild != null) {
      isRowBlank = false;
     }
    } else {
     System.out.print("--");
     localStack.push(null);
     localStack.push(null);
    }
    for (int j = 0; j < nBlank * 2 - 2; j++) {
     System.out.print(" ");
    }
   }

   System.out.println("");
   nBlank = nBlank / 2;
   while (localStack.isEmpty() == false) {
    globalStack.push(localStack.pop());
   }
  }
  System.out.println("---------------------------------------------");
 }

 public static void main(String[] args) throws IOException {
  String str;
  TreeAppLL tree = new TreeAppLL(null);
  do {
   System.out.print("Enter the Tree Node, Enter 'Y' to exit: ");
   str = getInput();
   if (str.equalsIgnoreCase("y")) {
    break;
   }
   tree.insert(Integer.parseInt(str), Integer.parseInt(str));
   System.out.println("");
  } while (true);
//  tree.traversal();
  tree.displayTree();
 }

 public static String getInput() throws IOException {
  InputStreamReader inputStream = new InputStreamReader(System.in);
  BufferedReader reader = new BufferedReader(inputStream);
  String str = reader.readLine();
  return str;
 }
}



This requires a custom tree Node class which i created.


package com.test.ds;

public class TreeNodeLL {

 int key;
 int data;
 int leftSum;
 int rightSum;
 TreeNodeLL leftChild;
 TreeNodeLL rightChild;

 public TreeNodeLL(int key, int data) {
  this.key = key;
  this.data = data;
  this.leftChild = null;
  this.rightChild = null;
 }

}

I have also created a collection of common Tree problems which one should look at solving before moving  on with the topic.


package com.test.ds;


public class SumOfRootProb {

 public static void main(String[] args) {
  TreeNodeLL item = new TreeNodeLL(5, 10);
  TreeAppLL tree = new TreeAppLL(item);
  tree.insert(3, 20);
  tree.insert(7, 10);
  tree.insert(6, 10);
  tree.insert(2, 10);
  tree.insert(4, 10);
  tree.insert(9, 10);
  
  tree.displayTree();
  
  SumOfRootProb obj = new SumOfRootProb();
  obj.sum(tree.getRoot());
  
  tree.displayTree();
  
  System.out.println(obj.maxDepth(tree.getRoot()));
  
  System.out.println(obj.hasSumValue(tree.getRoot(), 18));
  
  obj.recPathPrint(tree.getRoot());
  

  TreeNodeLL item2 = new TreeNodeLL(5, 10);
  TreeAppLL tree2 = new TreeAppLL(item2);
  tree2.insert(3, 20);
  tree2.insert(7, 10);
  tree2.insert(6, 10);
  tree2.insert(2, 10);
  tree2.insert(4, 10);
  
  
  int result = obj.sameTree(tree.getRoot(), tree2.getRoot());
  if (result == 0) {
   System.out.println("Both with same structure");
  }
  else{
   System.out.println("Tum ho jhoote jhoote jhoote");
  }
  tree2.displayTree();
  tree.displayTree();
 }

 public int sum(TreeNodeLL node){
  if (node == null) {
   return 0;
  }
  else{
   node.leftSum = sum(node.leftChild);
   node.rightSum = sum(node.rightChild);
   return node.key + node.leftSum + node.rightSum;
  }
 }
 
 public int maxDepth(TreeNodeLL root) {
  int lDepth = 0, rDepth = 0;
  if(root == null){
   return 0;
  }
  lDepth = maxDepth(root.leftChild);
  rDepth = maxDepth(root.rightChild);
  if(lDepth > rDepth){
   return lDepth + 1;
  } else{
   return rDepth + 1;
  }
 }
 
 public boolean hasSumValue(TreeNodeLL node, int sum){
  if(node == null){
   return (sum == 0);
  }
  else{
   int subSum = sum - node.key;
   return (hasSumValue(node.leftChild, subSum)||hasSumValue(node.rightChild, subSum));
  }
  
 }
 public void recPathPrint(TreeNodeLL root){
  int[] path = new int[10];
  printPath(root, path, 0);
 }
 
 public void printPath(TreeNodeLL node, int[] path, int pathLen){
  if(node == null){
   return;
  }
  else{
   path[pathLen] = node.key;
   pathLen++;
   if(node.leftChild == null && node.rightChild == null){
    System.out.print("Path ");
    for(int i = 0; i< pathLen; i++){
     System.out.print(path[i] + " ");
    }
    System.out.println("");
   } else{
    printPath(node.leftChild, path, pathLen);
    printPath(node.rightChild, path, pathLen);
   }
  }
 }
 
 public void mirror(TreeNodeLL node){
  if(node == null){
   return;
  }
  else{
   TreeNodeLL temp;
   mirror(node.leftChild);
   mirror(node.rightChild);
   temp = node.leftChild;
   node.leftChild = node.rightChild;
   node.rightChild = temp;
  }
 }
 
 public void doubleTree(TreeNodeLL node){
  if(node == null){
   return;
  } else{
   doubleTree(node.leftChild);
   doubleTree(node.rightChild);
   TreeNodeLL newItem = new TreeNodeLL(node.key, node.data);
   newItem.leftChild = node.leftChild;
   node.leftChild = newItem;
  }
 }
 
 public int sameTree(TreeNodeLL root1, TreeNodeLL root2){
  if(root1 == null && root2 == null){
   return 0;
  } else if(root1 != null && root2 != null){
   int lResult = sameTree(root1.leftChild, root2.leftChild);
   int rResult = sameTree(root1.rightChild, root2.rightChild);
   if(lResult == 0 && rResult == 0){
    return 0;
   } else{
    return -1;
   }
   
  } else{
   return -1;
  }
 }
 
 public void longestPath(TreeNodeLL node, int[] path, int length, int maxLength){
  if(node == null){
   return;
  }
  else{
   path[length] = node.data;
   length++;
   if(node.leftChild == null && node.rightChild == null){
    if(maxLength < length){
     maxLength = length;
    }
   }
   else{
    longestPath(node.leftChild, path, length, maxLength);
    longestPath(node.rightChild, path, length, maxLength);
   }
  }
 }
} 

References:



Data Structures in Java by Robert Lafore

Euler's Problem 18

if you have heard of Euler's Problems then you might be aware of the Site Euler.net.

We have the input array

3
7 4
2 4 6
8 5 9 3

This problem deals with getting a path from top to bottom of contiguous elements which has the highest sum.

The trick is to see from the bottom up, in this example take the second last row and calculate the sum with one element being this and second being the element directly below and diagonally adjacent.

So, for element 2 in row 3  would be :
2 + 8 = 10
2+5 = 7

So, we can narrow down that we can choose the max number out of the two options which will give us more sum value.

Now, after calculating this sum replace the Sum value in this case 10 in position of 2.

Similarly, we will have this at the end of iteration for row = 2

3
7 4
10 13 15


Hence the solution is : 3 7 4 9
Sum : 23

Here is the Java code for the same


package com.test.practise;

public class MaxInMatrix {
 
 private int[][] input;
 private int[] output;
 
 public MaxInMatrix(int[][] input){
  this.input = input;
  this.output = new int[input.length];
 }
 
 
  public void getPath(){
  output[0] = input[0][0];
  int row = input.length -2;
  int j = 0;
  while(row >= 0){
   for(j=0; j<= row; j++){
    input[row][j] += Math.max(input[row+1][j], input[row+1][j+1]);
   }
   row--;
  }
  
  
  System.out.println(" ");
  System.out.print("Total Sum of the path is: " + input[0][0]);
 }
 
 
 public static void main(String[] args) {
  int[][] input = {{3},{7,4},{2,4,6},{8,5,9,3}};
  MaxInMatrix obj = new MaxInMatrix(input);
  obj.getPath();
 }

}


Refernces:
Euler's Project : http://projecteuler.net

Saturday, May 5, 2012

Making Oracle JAVA work on Ubuntu 12.04

With the suspension of support for more Ubuntu friendly format from Oracle we sometime face issues with installing Oracle Jdk 7 on ubuntu.
I have a 64 bit oracle JDK installed on my system from the following PPA
PPA: http://ppa.launchpad.net/webupd8team/java/ubuntu
you need to perform the following steps for installing the oracle JDK7 on your ubuntu 12.04 64 bit system
1. $> sudo add-apt-repository ppa:webupd8team/java
2. $> sudo apt-get update
3. $> sudo apt-get install oracle-java7-installer
After this you can check and select which java version you would like to use on the system
$>sudo update-alternatives --config java
Once this is done you probably would like to ensure that browser is using this java plugin, for that you need to carry out these options
create a "plugins" directory in the "~/.mozilla" path
$> mkdir ~/.mozilla/plugins 
Now you need to have a soft link to the actual file, which will be responsible for running the java on your browser(mozilla/chrome/chromium all use this plugins directory)   
$>ln -s /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libnpjp2.so ~/.mozilla/plugins
Once this is done you check the oracle link Test Page to see if the java is running fine on your system  
Now you would probably like to run eclipse on your system, for that these is a catch. I was facing issues when i was trying to open eclipse form my system and was getting this error
java.lang.UnsatisfiedLinkError: Could not load SWT library. Reasons: 
no swt-gtk-3740 in java.library.path
no swt-gtk in java.library.path
What this means is that the .swt folder at your home directory is missing few files which you need to manually copy. First you need to have following packages installed(generally they are installed if you have Gnome 3) 
$> sudo apt-get install libswt-gtk-3-jni libswt-gtk-3-java
Once you have installed these packages you can proceed to copy files which are needed
$> sudo cp /usr/lib/jni/libswt-*3740.so ~/.swt/lib/linux/x86_64
In case its a i386 install then the command will be 
$> sudo cp /usr/lib/jni/libswt-*3740.so ~/.swt/lib/linux/x86
You could also create the soft link to required files 
libswt-atk-gtk-3740.so -> /usr/lib/jni/libswt-atk-gtk-3740.so
libswt-cairo-gtk-3740.so -> /usr/lib/jni/libswt-cairo-gtk-3740.so
libswt-awt-gtk-3740.so -> /usr/lib/jni/libswt-awt-gtk-3740.so
libswt-gnome-gtk-3740.so -> /usr/lib/jni/libswt-gnome-gtk-3740.so
libswt-glx-gtk-3740.so -> /usr/lib/jni/libswt-glx-gtk-3740.so
libswt-gtk-3740.so -> /usr/lib/jni/libswt-gtk-3740.so
libswt-webkit-gtk-3740.so -> /usr/lib/jni/libswt-webkit-gtk-3740.so
libswt-pi-gtk-3740.so -> /usr/lib/jni/libswt-pi-gtk-3740.so
Once this is done you need to edit the eclipse.ini file to explicitly tell eclipse which VM to use. If you have installed eclipse using the Ubuntu Software Center you need to go to the following path to edit the file
$> sudo gedit /usr/lib/eclipse/eclipse.ini
You can specify the VM by adding these lines in the file
-vm
/usr/lib/jvm/java-7-oracle/bin

Once all these steps are done you should be ready with starting your development in Java on Ubuntu  12.04 64bit.

Enjoy !

References :

askubuntu.com   : http://askubuntu.com/questions/125150/unsatisfied-link-error-and-missing-so-files-when-starting-eclipse
technonstop.com    : http://technonstop.com/install-java-plugin-ubuntu-linux 
Stackoverflow.com    : http://stackoverflow.com/questions/10165693/ubuntu-eclipse-cannot-load-swt-libraries-not-opening

Monday, April 9, 2012

Sum of Binary Tree Nodes

For the past few days i have been digging into the Trees Data Structure. Trees or graphs are one the most practically used Data Structure due to their better performance over Linked list and Arrays.

Let's go straight to the problem: We need to calculate the sum for all the parent nodes in the tree and only leaf nodes has the values.

Thanks to this post Post on stackoverflow, this issue is a problem of recursion. Remember for any issue where you need to travel each node in a tree can be solved by recursion. If you want to traverse a tree (In order, Preorder or Post Order) you will use recursion to do this.

Example Tree :


-------------------------------------------------------------
                                5,0,0                                                            
                3,0,0                              7,0,0                            
        2,0,0              4,0,0              6,0,0              9,0,0            
-------------------------------------------------------------

This is the Node class which i have printed


public class TreeNodeLL {

int key;
int data;
int leftSum;
int rightSum;
TreeNodeLL leftChild;
TreeNodeLL rightChild;

public TreeNodeLL(int key, int data) {
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}

}

So the leftSum = Sum of 'key' variable in the left Sub-tree.
similarly rightSum = Sum of 'key' variable in Right Sub-tree.




We have the method to calculate this



public int sum(TreeNodeLL node){
if (node == null) {
return 0;
}
else{
node.leftSum = sum(node.leftChild);
node.rightSum = sum(node.rightChild);
return node.key + node.leftSum + node.rightSum;
}
}

Output would be:


-------------------------------------------------------------
                                5,9,22                                                            
                3,2,4                              7,6,9                            
        2,0,0              4,0,0              6,0,0              9,0,0            
-----------------------------------------------------------



References:
Data Structures in Java by Robert Lafore
Stackoverflow.com

Wednesday, March 28, 2012

Recursion - Kanpsack Problem

Continuing my quest, playing with old computer science theories today i am writing about recursion and using it to solve similar issue as that of Knapsack problem. So, if you know about Recursion (like some flavor of it which i discussed in my last post) you would know its a very powerful tool which can be used to solve complex computer science problems.
In this approach we call same method from within a method with a base case which marks as its end, so we effectively call our self till we reach a base case and then we trace back till the starting. In java when a method call is placed in code it is loaded on to a stack in JVM which the run time environment will call, so if i call my self again and again i will end up having several stack entries of the same method and when the base case returns something it will unfold with last in last out rule.
As it may seem this is a powerful yet not that efficient tool as the repeated method calls can be expensive.

So, let's take a sample problem which is similar to Knapsack Problem remember Knapsack problem is a NP-complete problem hence no optimal solution exists for it. Please note this exercise is to understand and practice  recursion not to get the optimal solution to Knapsack Problem.

Problem
We have a array of descending numbers and we need to pick a set whose total is equal to the target.

E.g. array = 11, 8, 7, 6 ,5
Target Total = 20

We will create a program that can calculate the first set of numbers from this to get the result.


public class KnapsackProblem {
 
 private Stackx output;
 private int[] input;
 private int size;
 private int target;
 
 public KnapsackProblem(int target){
  this.input = new int[10];
  this.size = 0;
  this.output = new Stackx(10);
  this.target = target;
 }
 
 public void insert(int item) {
  input[size++] = item;
 }
 
 public void recKnapsack() {
  boolean flag = false;
  for (int i = 0; i < size; i++) {
   if (input[i] == target) {
    System.out.println("got it !");
   } else if (input[i] > target) {
    continue;
   } else if (input[i] < target) {
    boolean result = knapsackNew(target, i);
    if (result) {
     output.display();
     flag = true;
     break;
    } else{
     while(!output.isEmpty()){
      output.pop();
     }
    }
   }
  }
  if (flag) {
   System.out.println("  Success !!");
  } else {
   System.out.println("Cant find any conbination to get the target: " + target);
  }
  
 }

 public boolean knapsackNew(int target, int i) {
  if (i == size) {
   return false;
  }
  if (input[i] < target) {
   output.push(input[i]);
   return knapsackNew(target - input[i], ++i);
  } else if (input[i] > target) {
   return knapsackNew(target, ++i);
  } else if (input[i] == target) {
   output.push(input[i]);
   return true;
  }
  
  return false;
 }
 
 public static void main(String[] args) {
  KnapsackProblem obj = new KnapsackProblem(20);
  
  obj.insert(11);
  obj.insert(8);
  obj.insert(7);
  obj.insert(6);
  obj.insert(5);
  
  obj.recKnapsack();
 }
}
 

References :
Data Structures and Algorithms by Robert Lafore

Monday, March 26, 2012

Shell Sort - Let the shelling begin

So, many of us already know about insertion sort which is a nice sorting algorithm for sorting but lacks in performance, with complexity of O(n2), but gives a good performance when it comes to almost sorted list.

Using this property of fast processing in case of almost sorted list, Shell sort can achieve much better results then insertion sort. Shell sort does this by doing a "incremental sort" of the array. By that i mean it first divides the array into parts and sorts the elements relative to each other.

E.g. Array = 5 2 4 1 6 3 7

Lets take a interval of 4 and consider every 4rd element in this array

so we will compare 5, 1 and 7 and will sort these element relative to each other.

new Array = 1 2 4 5 6 3 7

In the next iteration we will consider a smaller number, finally we will reach to a point where we will have a interval of 1 and will be a simple insertion sort but by that time must of the element would be in there positions or very near to there final positions making this a fast iteration.

So we start with a big "Shell" and imagine these are the only elements in the array and sort then move on to making them smaller and smaller till we have a shell size of 1. As you may have noticed key is the division rule or the series(called a "Gap Sequence"or "Interval Sequence") we will use to decide on the shell sizes. Remember we need to have a series which ends with 1 so that we can run the insertion sort in the end. One of these series is provided by Kunth,

h = 3*h + 1

now in word of Kunfu Panda "enough talk, let's code"


 
 /**
 * This method will sort the array 
 * using Kunth's formula to calculate 
 * the bucket.
 */
public void shellSort() {
 int inner;
 int outer;
 int h = 1;
 /**
  * Calculate the bucket size to the max
  * then we move down till we reach around 1
  */
 while(h <= (nElemt/3)){
  h = h*3 + 1;
 }
 while(h > 0){
  for(outer = h; outer < nElemt; outer++){
   int temp = array[outer];
   inner = outer;
   while(inner > h-1 && 
                                    array[inner - h] >= temp){
    array[inner] = array[inner - h];
    inner -= h;
   }
   array[inner] = temp;
  }
  h = (h-1) / 3; //get the value of bucket back
 }
}

References :
Data Structures and Algorithms in Java by Robert Lafore

Tuesday, March 13, 2012

Merge Sort explained

For past few days i have been going back to basics. these are the topics which got me started with coding in the first place. Although these are simple topics in Computer science but form the very basic of coding in any language.

Well lets start off with some back ground about the Merge Sort. This basically comes from the family of algorithms which is based on divide and conquer methodology(If you know your history almost all civilizations at some point of time had someone playing this game in the kingdom).

The intent is to divide a big problem(in this case a array ) into smaller problems so that they can be solved easily(by easily i mean in few lines of code). Imagine if you have a array of 10,000 objects and you want to sort it according to their values (in this case we will take a simple example of a integer generally these are complex objects but the principle remains the same). If we divide this array till it becomes a single element then we simply compare the element and get the result, that forms the basis of this algorithm. We will divide a array till we have two arrays having only one element and then we compare them and merge the arrays.

So, we have two steps
  1. Divide till we reach to a point where we have 1 element which can be compared.
  2. merge the elements.
For all the math interest groups, these are Mathematical Induction problems where you have a base case (in this case a array with elements which can be compared and merged in one go) and the repeating case.

Merging 
Lets look at Merging two sorted arrays first. We will be doing this when we divide the single array into two and then we will merge it.

Input array A = 11,33,55,77,99
Input array B = 22,44,66,88

For merging these 2 arrays we will choose each element and compare with each other and push in a new array. 

Iteration 1: compare 11 with 22
11 is smaller hence we push it in a new array C and increment the counter for A. 
then we compare next element in A with same element in B i.e. 33 with 22 now 22 is smaller hence we push 22 in C and increment the counter for B.

array C : 11,22

After all the iteration we will have one single array with sorted elements.

Recursion
Now let's look at recursion part of it. Our focus here is to divide the problem into smaller parts till we reach the base case.
e.g. Input Array = 55,33,44,11,22

we will take a lower pointer (0 position ) and upper pointer(4 position) and calculate the mid. Now we will call the same method with upper pointer as mid and same value of lower pointer.
We will keep on calculating till we have lowerPtr == UpperPtr then we have only one element.

Similarly we will call same method again with mid as lower pointer and same value for upper pointer.

The code will look like this.

public void recMergeSort(int[] workspace, int lowerBound, int upperBound) {
if (lowerBound == upperBound) {
return;
} else {
int mid = (lowerBound + upperBound)/2;
recMergeSort(workspace, lowerBound, mid);
recMergeSort(workspace, mid + 1, upperBound);
merge(workspace, lowerBound, mid + 1, upperBound);
}
}
We use workspace array to hold the merged output

the last line submits the array to get it merged, here we will divide the same array in two parts from lower to mid and from mid+1 to upper.

Here is the Java code for it.

public void merge(int[] workspace, int lowPtr, int highPtr,
int upperBound) {
int i = 0; // workspace index
int lowerBound = lowPtr;
int mid = highPtr - 1;
int n = upperBound - lowerBound + 1;  // number of items
while (lowPtr <= mid && highPtr <= upperBound) {
if (array[lowPtr] < array[highPtr]) {
workspace[i++] = array[lowPtr++];
} else {
workspace[i++] = array[highPtr++];
}
}
while(lowPtr <= mid){
workspace[i++] = array[lowPtr++];
}
while(highPtr <= upperBound){
workspace[i++] = array[highPtr++];
}

for (int j = 0; j < n; j++) {
array[lowerBound + j] = workspace[j]; // copy the merged array back
}
}
Since we keep on dividing the array into 2 parts, the final time complexity of this algorithm is O(n log n)
Please keep in mind the base of Log is 2 here.

For better time complexity we compromise on space here as we are using 2 arrays of the same size, so if you are programming on device which is limited on size you might want to consider more complex sorting algorithms but more on that later.


References :
Data Structures & Algorithms in Java by Robert Lafore