Showing posts with label Implementation. Show all posts
Showing posts with label Implementation. Show all posts

Saturday, February 13, 2016

LEONARDO SPOJ (Implementation) Solution - JAVA

Algorithm :-

1. Odd length cycles are OK.
2. The graph should have two even length cycles of the same length if even cycles exist. (There may be multiple even cycles).
3. Self loops are OK.

Point #2:

Consider an alphabet having only 6 letters i.e. ABCDEF. Now we have to apply the same permutation twice to get "CDEABF". The permutation we apply is "BCDAEF". Applying it twice (steps):-

|--->CDABEF
P
|--->BCDAEF
P
|----ABCDEF

Where P stands for the application of the permutation "BCDAEF". Now if we only consider the final alphabet string and the original one,

CDABEF

ABCDEF

Notice our even length cycle "BCDA" has split up into two even cycles of equal length. (CA and DB).

You can similarly figure out that odd length cycles remain odd length cycles and of course, self loops have no effect.

Self loops:

There are two self loops in the above example E-E and F-F.

Now just write code to check whether there are even number of even length cycles. If this is the case, the answer is yes, otherwise no.

Source (Java):

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;


public class LEONARDO { 
    
    public static void main(String[] args){
        int n = IO.nextInt();
        String REF = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        while(n-->0){
            String s = IO.nextString();
            
            int[] pos = new int[256];
          
            for(int i=0;i<s.length();++i){
                pos[s.charAt(i)] = i;
            }
            
            boolean m[] = new boolean[256]; 
            
            int cyclesReg[] = new int[26]; 
            for(int i=0;i<s.length();++i){
                char c = s.charAt(i); 
                boolean f = false;
                int length =0 ;
                while(!m[c]){  
                    f = true;
                    length++;
                    m[c] = true;
                    int p = pos[c];
                    c = REF.charAt(p);
                } 
                if(f){ 
                    cyclesReg[length]++;
                }
            }
             
            boolean f = true;
            for(int i=0;i<cyclesReg.length;++i){
                if(i%2==0 && cyclesReg[i]%2!=0){f =  false;break;}
            }
            if(f)IO.println("Yes");
            else IO.println("No");
        }
    }
    
    private static class IO {
        private static InputStream stream = System.in;
        private static byte[] buf = new byte[1024];
        private static int curChar, numChars; 

        private static int read() {
                if (numChars == -1)throw new InputMismatchException();
                if (curChar >= numChars) {
                        curChar = 0;
                        try {
                            numChars = stream.read(buf);
                        } catch (IOException e) {
                            throw new InputMismatchException();
                        }
                        if (numChars <= 0)return -1;
                }
                return buf[curChar++];
        }

        public static int nextInt() {
                int c = read();
                while (isSpaceChar(c))
                        c = read();
                int sgn = 1;
                if (c == '-') {
                    sgn = -1;
                    c = read();
                }
                int res = 0;
                do {
                    if (c < '0' || c > '9') throw new InputMismatchException();
                    res *= 10;
                    res += c - '0';
                    c = read();
                } while (!isSpaceChar(c));
                return res * sgn;
        }

        public static char nextChar() {
                int c = read();
                while (isSpaceChar(c)) c = read();
                return (char) c;
        }
        
        private static String nextString(){
            int c = read();
            while(isSpaceChar(c))c=read();
            StringBuilder sb = new StringBuilder();
            do{
                sb.append((char)c);
            }while(!isSpaceChar((c=read())));
            return sb.toString();
        }

        private static boolean isSpaceChar(int c) {
                return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
        
        private static void println(Object... a){
            for(Object o:a)System.out.print(o);
            System.out.println();
        }
    }
}

Saturday, October 18, 2014

Bottom Up Merge Sort Java Implementation

Bottom up merge sort sorts the array without using recursion. It is 10% slower than the top down (recursive) mergesort. The idea is to start sorting the array elements from the start in groups of 2, 4, 8, 16, and so on (powers of two). So that the effect is the same as the recursive algorithm.
Here is a trace for sorting numbers 13,12, ..., 1
 

Source:

import java.util.Arrays;

public class BottomUpMergeSort {

    public static void merge(int[] orig, int[] aux, int start, int mid, int end) {
        int i, j, z = start; 
        
        if(orig[mid] <= orig[mid+1])return; 
        
        for(i=start, j = mid+1; i!=mid+1 || j!=end+1;){
            if(i==mid+1)               while(j!=end+1){ aux[z++] = orig[j++]; }
            else if(j==end+1)          while(i!=mid+1){ aux[z++] = orig[i++]; }
            else if(orig[i]<=orig[j])  aux[z++] = orig[i++];
            else                       aux[z++] = orig[j++];
        }    
        System.out.println(Arrays.toString(orig));
        System.out.println("start = "+start+" mid = "+mid+" end = "+end);
        System.out.println(Arrays.toString(aux)+"\n");
        System.arraycopy(aux, start, orig, start, end-start+1);
    }

    public static void sort(int[] orig, int[] aux, int start, int end) {
        int N = orig.length;
        for (int sz = 1; sz < N; sz *= 2) {
            for (int lo = 0; lo < N - sz; lo += sz + sz) {
                merge(orig, aux, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N-1));
            }
        }
    }

    public static void main(String[] args) {
        int array[] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
        int aux[] = new int[array.length];
        sort(array, aux, 0, array.length - 1);
    }
}

lo < N - sz 
takes care to see that the mid value falls before end. 

lo < N - sz
lo + sz < N
lo + sz - 1 < N - 1
mid < N - 1

Math.min() takes care to see that end does not extend beyond the last index.

Output:

[11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
start = 0 mid = 0 end = 1
[10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[10, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1]
start = 2 mid = 2 end = 3
[10, 11, 8, 9, 0, 0, 0, 0, 0, 0, 0]
[10, 11, 8, 9, 7, 6, 5, 4, 3, 2, 1]
start = 4 mid = 4 end = 5
[10, 11, 8, 9, 6, 7, 0, 0, 0, 0, 0]
[10, 11, 8, 9, 6, 7, 5, 4, 3, 2, 1]
start = 6 mid = 6 end = 7
[10, 11, 8, 9, 6, 7, 4, 5, 0, 0, 0]
[10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1]
start = 8 mid = 8 end = 9
[10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0]
[10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 1]
start = 0 mid = 1 end = 3
[8, 9, 10, 11, 6, 7, 4, 5, 2, 3, 0]
[8, 9, 10, 11, 6, 7, 4, 5, 2, 3, 1]
start = 4 mid = 5 end = 7
[8, 9, 10, 11, 4, 5, 6, 7, 2, 3, 0]
[8, 9, 10, 11, 4, 5, 6, 7, 2, 3, 1]
start = 8 mid = 9 end = 10
[8, 9, 10, 11, 4, 5, 6, 7, 1, 2, 3]
[8, 9, 10, 11, 4, 5, 6, 7, 1, 2, 3]
start = 0 mid = 3 end = 7
[4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3]
[4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3]
start = 0 mid = 7 end = 10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Fisher–Yates shuffle Java Implementation

The Fisher–Yates shuffle (named after Ronald Fisher and Frank Yates), also known as the Knuth shuffle (after Donald Knuth), is an algorithm for generating a random permutation of a finite set—in plain terms, for randomly shuffling the set.

Algorithm:
1. Iterate from Index 0 to N,
2. For index i between 0 to N, select a random number between 0 and i (inclusive) and swap the numbers at the two positions.
3. After index N has been processed, the array is shuffled.

Source: 

import java.util.Arrays;
import java.util.Random; 

public class KnuthShuffle {
    
    public static <T> void swap(T[] array, int i, int j){
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    
    public static <T> T[] shuffle(T[] array){
        Random rand = new Random();
        
        for(int i = 0;i<array.length; ++i){
            swap(array, rand.nextInt(i+1), i); 
            //System.out.println(Arrays.toString(array));
        } 
        return array;
    }
    public static void main(String[] args){
        Integer[] array = new Integer[]{1, 2, 3, 4, 5, 6, 7};
        System.out.println(Arrays.toString(shuffle(array)));
    }
}
 
Output:
[5, 6, 1, 7, 2, 3, 4]

Circular Queue (Fixed Size) Java Implementation

This program implements Circular Queue of Fixed Size.

1. In the beginning, front and end are equal to 0.
2. When we add an item, we increment end to the index next to the index at which we have inserted the new item.
3. Queue is empty if [ front == end ] (Note that end gets incremented to the next index after each insertion, so end is pointing to the index next to the index of the last inserted item)
4. Queue is full if  [ previousIndex(front) == end ]

Source:

import java.util.Scanner;
 
public class CircularQueue {
    private int queue[] = new int[5];
    private int front = 0, end = 0;
     
    private int getNextIndex(int index){
        return (index+1==queue.length)?0:index+1;
    }
    
    private int getPreviousIndex(int index){
        return (index-1==-1)?queue.length-1:index-1;
    }
    
    public boolean isFull(){   
          return getPreviousIndex(front)==end; //End points to (index+1) where index is the last inserted item's index
    }
    
    public boolean isEmpty(){ 
        return front == end; //End points to (index+1) where index is the last inserted item's index
    }
    
    public void enqueue(int add){
        if(isFull()){ System.out.println("Error: Queue is full!"); return;}
        queue[end] = add; 
        end = getNextIndex(end); 
    }
    
    public void dequeue(){
        if(isEmpty()){ System.out.println("Error: Queue is empty!   "); return; }
        front = getNextIndex(front);
    }
    
    public void printQueue(){
        System.out.print("\nPrinting Queue: ");
        if(isEmpty()) {System.out.println("Queue is empty!"); return;}  
        for(int i = front; ; i = getNextIndex(i)){ 
            System.out.print(queue[i]+" ");
            if(i==end-1)break;
        }
        System.out.println();
    }
    
    public void consoleUI(){
        Scanner scan = new Scanner(System.in);
        int choice = 0;
        int item = 0;
        while(true){
           System.out.println("1. Insert\n2. Remove\n3. Is Empty?\n4. Is Full?\n5. Print Queue Contents");
           choice = scan.nextInt();
           
           switch(choice){
               case 1:
                   item = scan.nextInt();
                   while(item!=-999){
                       enqueue(item);
                       item = scan.nextInt();
                   }
                   break;
               case 2:  dequeue(); printQueue(); break;
               case 3:  System.out.println(isEmpty()); break;
               case 4:  System.out.println(isFull()); break;
               case 5:  printQueue(); break;
           }
        }
    }
    
    public static void main(String[] args){
        CircularQueue cq = new CircularQueue();
        cq.consoleUI();
    }
}
 
Sample Run:

1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
1
1 2 3 4
5
Error: Queue is full!
-999
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
2
Printing Queue: 2 3 4
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
2
Printing Queue: 3 4
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
1
5 6
7
Error: Queue is full!
-999
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
5
Printing Queue: 3 4 5 6
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
3
false
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
4
true
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
2
Printing Queue: 4 5 6
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
2
Printing Queue: 5 6
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
2
Printing Queue: 6
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
5
Printing Queue: 6
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
3
false
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
4
false
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
1
7
8
9
10
Error: Queue is full!
-999
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
5
Printing Queue: 6 7 8 9
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
3
false
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents
4
true
1. Insert
2. Remove
3. Is Empty?
4. Is Full?
5. Print Queue Contents

Red Black Tree Java Implementation

This program implements Red Black Tree in Java.

Red Black Tree Visualizer (Helps a lot) : http://www.cs.usfca.edu/~galles/visualization/RedBlack.html

[Note: The delete operation used in this source finds the min element in the right child of the node to be deleted (the node having two children) but the link above uses the min element from the left subtree in that case. So delete operations will be different. Both are correct.]
 
There are 5 basic properties a red-black tree must statisfy:

1. Every node is either red or black.
2. The root is black.
3. Every leaf (nil) is black.
4. If a node is red, then both its children are black.
5. For each node, all simple paths from the node to descendant leaves contain the
same number of black nodes.

Here is a random Red Black Tree so you can visualize the structure of a Red Black Tree:



The leaf nodes have both left and right references set to node nil. The root has it's parent node set to node nil as well.

Source:

import java.util.Scanner;

public class RedBlackTree {

    private final int RED = 0;
    private final int BLACK = 1;

    private class Node {

        int key = -1, color = BLACK;
        Node left = nil, right = nil, parent = nil;

        Node(int key) {
            this.key = key;
        } 
    }

    private final Node nil = new Node(-1); 
    private Node root = nil;

    public void printTree(Node node) {
        if (node == nil) {
            return;
        }
        printTree(node.left);
        System.out.print(((node.color==RED)?"Color: Red ":"Color: Black ")+"Key: "+node.key+" Parent: "+node.parent.key+"\n");
        printTree(node.right);
    }

    private Node findNode(Node findNode, Node node) {
        if (root == nil) {
            return null;
        }

        if (findNode.key < node.key) {
            if (node.left != nil) {
                return findNode(findNode, node.left);
            }
        } else if (findNode.key > node.key) {
            if (node.right != nil) {
                return findNode(findNode, node.right);
            }
        } else if (findNode.key == node.key) {
            return node;
        }
        return null;
    }

    private void insert(Node node) {
        Node temp = root;
        if (root == nil) {
            root = node;
            node.color = BLACK;
            node.parent = nil;
        } else {
            node.color = RED;
            while (true) {
                if (node.key < temp.key) {
                    if (temp.left == nil) {
                        temp.left = node;
                        node.parent = temp;
                        break;
                    } else {
                        temp = temp.left;
                    }
                } else if (node.key >= temp.key) {
                    if (temp.right == nil) {
                        temp.right = node;
                        node.parent = temp;
                        break;
                    } else {
                        temp = temp.right;
                    }
                }
            }
            fixTree(node);
        }
    }

    //Takes as argument the newly inserted node
    private void fixTree(Node node) {
        while (node.parent.color == RED) {
            Node uncle = nil;
            if (node.parent == node.parent.parent.left) {
                uncle = node.parent.parent.right;

                if (uncle != nil && uncle.color == RED) {
                    node.parent.color = BLACK;
                    uncle.color = BLACK;
                    node.parent.parent.color = RED;
                    node = node.parent.parent;
                    continue;
                } 
                if (node == node.parent.right) {
                    //Double rotation needed
                    node = node.parent;
                    rotateLeft(node);
                } 
                node.parent.color = BLACK;
                node.parent.parent.color = RED;
                //if the "else if" code hasn't executed, this
                //is a case where we only need a single rotation 
                rotateRight(node.parent.parent);
            } else {
                uncle = node.parent.parent.left;
                 if (uncle != nil && uncle.color == RED) {
                    node.parent.color = BLACK;
                    uncle.color = BLACK;
                    node.parent.parent.color = RED;
                    node = node.parent.parent;
                    continue;
                }
                if (node == node.parent.left) {
                    //Double rotation needed
                    node = node.parent;
                    rotateRight(node);
                }
                node.parent.color = BLACK;
                node.parent.parent.color = RED;
                //if the "else if" code hasn't executed, this
                //is a case where we only need a single rotation
                rotateLeft(node.parent.parent);
            }
        }
        root.color = BLACK;
    }

    void rotateLeft(Node node) {
        if (node.parent != nil) {
            if (node == node.parent.left) {
                node.parent.left = node.right;
            } else {
                node.parent.right = node.right;
            }
            node.right.parent = node.parent;
            node.parent = node.right;
            if (node.right.left != nil) {
                node.right.left.parent = node;
            }
            node.right = node.right.left;
            node.parent.left = node;
        } else {//Need to rotate root
            Node right = root.right;
            root.right = right.left;
            right.left.parent = root;
            root.parent = right;
            right.left = root;
            right.parent = nil;
            root = right;
        }
    }

    void rotateRight(Node node) {
        if (node.parent != nil) {
            if (node == node.parent.left) {
                node.parent.left = node.left;
            } else {
                node.parent.right = node.left;
            }

            node.left.parent = node.parent;
            node.parent = node.left;
            if (node.left.right != nil) {
                node.left.right.parent = node;
            }
            node.left = node.left.right;
            node.parent.right = node;
        } else {//Need to rotate root
            Node left = root.left;
            root.left = root.left.right;
            left.right.parent = root;
            root.parent = left;
            left.right = root;
            left.parent = nil;
            root = left;
        }
    }

    //Deletes whole tree
    void deleteTree(){
        root = nil;
    }
    
    //Deletion Code .
    
    //This operation doesn't care about the new Node's connections
    //with previous node's left and right. The caller has to take care
    //of that.
    void transplant(Node target, Node with){ 
          if(target.parent == nil){
              root = with;
          }else if(target == target.parent.left){
              target.parent.left = with;
          }else
              target.parent.right = with;
          with.parent = target.parent;
    }
    
    boolean delete(Node z){
        if((z = findNode(z, root))==null)return false;
        Node x;
        Node y = z; // temporary reference y
        int y_original_color = y.color;
        
        if(z.left == nil){
            x = z.right;  
            transplant(z, z.right);  
        }else if(z.right == nil){
            x = z.left;
            transplant(z, z.left); 
        }else{
            y = treeMinimum(z.right);
            y_original_color = y.color;
            x = y.right;
            if(y.parent == z)
                x.parent = y;
            else{
                transplant(y, y.right);
                y.right = z.right;
                y.right.parent = y;
            }
            transplant(z, y);
            y.left = z.left;
            y.left.parent = y;
            y.color = z.color; 
        }
        if(y_original_color==BLACK)
            deleteFixup(x);  
        return true;
    }
    
    void deleteFixup(Node x){
        while(x!=root && x.color == BLACK){ 
            if(x == x.parent.left){
                Node w = x.parent.right;
                if(w.color == RED){
                    w.color = BLACK;
                    x.parent.color = RED;
                    rotateLeft(x.parent);
                    w = x.parent.right;
                }
                if(w.left.color == BLACK && w.right.color == BLACK){
                    w.color = RED;
                    x = x.parent;
                    continue;
                }
                else if(w.right.color == BLACK){
                    w.left.color = BLACK;
                    w.color = RED;
                    rotateRight(w);
                    w = x.parent.right;
                }
                if(w.right.color == RED){
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.right.color = BLACK;
                    rotateLeft(x.parent);
                    x = root;
                }
            }else{
                Node w = x.parent.left;
                if(w.color == RED){
                    w.color = BLACK;
                    x.parent.color = RED;
                    rotateRight(x.parent);
                    w = x.parent.left;
                }
                if(w.right.color == BLACK && w.left.color == BLACK){
                    w.color = RED;
                    x = x.parent;
                    continue;
                }
                else if(w.left.color == BLACK){
                    w.right.color = BLACK;
                    w.color = RED;
                    rotateLeft(w);
                    w = x.parent.left;
                }
                if(w.left.color == RED){
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.left.color = BLACK;
                    rotateRight(x.parent);
                    x = root;
                }
            }
        }
        x.color = BLACK; 
    }
    
    Node treeMinimum(Node subTreeRoot){
        while(subTreeRoot.left!=nil){
            subTreeRoot = subTreeRoot.left;
        }
        return subTreeRoot;
    }
    
    public void consoleUI() {
        Scanner scan = new Scanner(System.in);
        while (true) {
            System.out.println("\n1.- Add items\n"
                    + "2.- Delete items\n"
                    + "3.- Check items\n"
                    + "4.- Print tree\n"
                    + "5.- Delete tree\n");
            int choice = scan.nextInt();

            int item;
            Node node;
            switch (choice) {
                case 1:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item);
                        insert(node);
                        item = scan.nextInt();
                    }
                    printTree(root);
                    break;
                case 2:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item);
                        System.out.print("\nDeleting item " + item);
                        if (delete(node)) {
                            System.out.print(": deleted!");
                        } else {
                            System.out.print(": does not exist!");
                        }
                        item = scan.nextInt();
                    }
                    System.out.println();
                    printTree(root);
                    break;
                case 3:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item);
                        System.out.println((findNode(node, root) != null) ? "found" : "not found");
                        item = scan.nextInt();
                    }
                    break;
                case 4:
                    printTree(root);
                    break;
                case 5:
                    deleteTree();
                    System.out.println("Tree deleted!");
                    break;
            }
        }
    }
    public static void main(String[] args) {
        RedBlackTree rbt = new RedBlackTree();
        rbt.consoleUI();
    }
}
 
Output Sample [-999 is the (end of input) indicator]:
1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree
1
22 33 4 5 6 7 8 55 3 2 1 6 4 -999
Color: Red Key: 1 Parent: 2
Color: Black Key: 2 Parent: 3
Color: Black Key: 3 Parent: 5
Color: Black Key: 4 Parent: 3
Color: Red Key: 4 Parent: 4
Color: Black Key: 5 Parent: -1
Color: Black Key: 6 Parent: 7
Color: Red Key: 6 Parent: 6
Color: Red Key: 7 Parent: 22
Color: Black Key: 8 Parent: 7
Color: Black Key: 22 Parent: 5
Color: Black Key: 33 Parent: 22
Color: Red Key: 55 Parent: 33
1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree
2
33 22 5 4 7 6 55 8 2 3 6 1 4 -999
Deleting item 33: deleted!
Deleting item 22: deleted!
Deleting item 5: deleted!
Deleting item 4: deleted!
Deleting item 7: deleted!
Deleting item 6: deleted!
Deleting item 55: deleted!
Deleting item 8: deleted!
Deleting item 2: deleted!
Deleting item 3: deleted!
Deleting item 6: deleted!
Deleting item 1: deleted!
Deleting item 4: deleted!
1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree
4
1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

Sunday, September 28, 2014

AVL Tree - Height Balancing Binary Search Tree (BST) Implementation [Java]

This program implements AVL tree (written in Java). AVL trees are binary search trees which automatically balance their heights after insertion of elements or removal of existing elements.

A post on BSTs :

http://coderbots.blogspot.in/2014/09/binary-search-tree-operations-find.html

Source:

import java.util.Scanner;

public class AVL {

    Node root;

    class Node {

        Node father, left, right;
        int height = 0;
        int key;

        public Node(int key, Node left, Node right, Node father) {
            this.key = key;
            this.left = left;
            this.right = right;
            this.father = father;
        }

        public String toString() {
            return "key = " + key + " height = " + height;
        }
    }

    public void insert(Node toInsert, Node node) {
        if (root == null) {
            root = toInsert;
            return;
        }

        if (toInsert.key < node.key) {
            if (node.left != null) {
                insert(toInsert, node.left);
                return;
            } else {
                toInsert.father = node;
                node.left = toInsert;
            }
        } else if (toInsert.key >= node.key) {
            if (node.right != null) {
                insert(toInsert, node.right);
                return;
            } else {
                toInsert.father = node;
                node.right = toInsert;
            }
        }
        updateHeights(toInsert);
        balance(toInsert);
    }

    public Node findNode(Node findNode, Node node) {
        if (root == null) {
            return null;
        }

        if (findNode.key < node.key) {
            if (node.left != null) {
                return findNode(findNode, node.left);
            }
        } else if (findNode.key > node.key) {
            if (node.right != null) {
                return findNode(findNode, node.right);
            }
        } else if (findNode.key == node.key) {
            return node;
        }
        return null;
    }

    public boolean deleteNode(Node deleteNode, Node node) {
        if (root == null) {
            return false;
        } else if (root.key == deleteNode.key) {
            if (root.left == null && root.right == null) {
                root = null;
            } else if (root.left == null) {
                root = root.right;
                root.father = null;
            } else if (root.right == null) {
                root = root.left;
                root.father = null;
            } else {
                Node min = root.right;
                //min element has no left or right child.
                if (min.left == null && min.right == null) {
                    root.key = min.key;
                    root.right = null;
                    updateHeights(root);
                    balance(root);
                    return true;
                }
                while (min.left != null) {
                    //Min element has left child.
                    min = min.left;
                }
                root.key = min.key;
                if (min.right != null) {
                    min.right.father = min.father;
                }
                //Min element has no left child but has right child.
                if (min.father != root) {
                    min.father.left = min.right; 
                } else {
                    min.father.right = min.right; 
                }
                updateHeights(min.father);
                balance(min.father);
            }
            return true;
        } else {
            Node locatedNode = findNode(deleteNode, root);
            if (locatedNode != null) {
                deleteHelper(locatedNode);
            } else {
                return false;
            }
        }
        return true;
    }

    private void deleteHelper(Node locatedNode) {
        boolean left = (locatedNode.father.left == locatedNode);
        if (locatedNode.right == null && locatedNode.left == null) {
            if (left) {
                locatedNode.father.left = null;
            } else {
                locatedNode.father.right = null;
            } 
        } else if (locatedNode.left != null && locatedNode.right == null) {
            locatedNode.left.father = locatedNode.father;
            if (left) {
                locatedNode.father.left = locatedNode.left;
            } else {
                locatedNode.father.right = locatedNode.left;
            }
        } else if (locatedNode.left == null && locatedNode.right != null) {
            locatedNode.right.father = locatedNode.father;
            if (left) {
                locatedNode.father.left = locatedNode.right;
            } else {
                locatedNode.father.right = locatedNode.right;
            }
        } else if (locatedNode.left != null && locatedNode.right != null) {
            Node min = locatedNode.right;
            //min element has no left or right child.
            if (min.left == null && min.right == null) {
                locatedNode.key = min.key;
                locatedNode.right = null;
                return;
            }
            while (min.left != null) {
                //Min element has left child.
                min = min.left;
            }
            locatedNode.key = min.key;
            if (min.right != null) {
                min.right.father = min.father;
            }
            //Min element has no left child but has right child.
            if (min.father != locatedNode) {
                min.father.left = min.right;
            } else {
                min.father.right = min.right;
            }
            updateHeights(min.father);
            balance(min.father); 
            return;
        }
        updateHeights(locatedNode.father);
        balance(locatedNode.father);
    }

    public void deleteTree() {
        root = null;
    }

    public void printTree(Node node) {
        if (node == null) {
            return;
        }
        printTree(node.left);
        System.out.print(node + "\n");
        printTree(node.right);
    }

    public void consoleUI() {
        Scanner scan = new Scanner(System.in);
        while (true) {
            System.out.println("\n1.- Add items\n"
                    + "2.- Delete items\n"
                    + "3.- Check items\n"
                    + "4.- Print tree\n"
                    + "5.- Delete tree\n");
            int choice = scan.nextInt();

            int item;
            Node node;
            switch (choice) {
                case 1:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        insert(node, root);
                        item = scan.nextInt();
                    }
                    printTree(root);
                    break;
                case 2:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        System.out.print("\nDeleting item " + item);
                        if (deleteNode(node, root)) {
                            System.out.print(": deleted!");
                        } else {
                            System.out.print(": does not exist!");
                        }
                        item = scan.nextInt();
                    }
                    System.out.println();
                    printTree(root);
                    break;
                case 3:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        System.out.println((findNode(node, root) != null) ? "found" : "not found");
                        item = scan.nextInt();
                    }
                    break;
                case 4:
                    printTree(root);
                    break;
                case 5:
                    deleteTree();
                    System.out.println("Tree deleted!");
                    break;
            }
        }
    }
    
    /*AVL Specific Code*/
    private void updateHeights(Node node) {
        if (node == null) {
            return;
        }
        int left = -1, right = -1;
        if (node.left != null) {
            left = node.left.height;
        }
        if (node.right != null) {
            right = node.right.height;
        }
        node.height = Integer.max(left, right) + 1;
        updateHeights(node.father);
    }

    private int checkBalance(Node node){
        int subleft = -1, subright = -1;
        if(node.right!=null)subright = node.right.height;
        if(node.left!=null)subleft = node.left.height;
        int balance = subleft-subright;
        return balance;
    }
    
    private void balance(Node node) {
        int balance = checkBalance(node);
        if (balance < -1) {   
            if(checkBalance(node.right)==1) rotateRight(node.right);
            rotateLeft(node);
        } else if (balance > 1) { 
            if(checkBalance(node.left)==-1) rotateLeft(node.left);
            rotateRight(node);
        } 
        if(node.father!=null) balance(node.father); 
    } 

    void rotateLeft(Node node) {
        //Right heavy - Rotate left 
        System.out.println("Need to rotate node " + node + " left!");
        
        //In case it's a Left-Right rotation
        Node keepAlive = null;
        if(node.left!=null) {keepAlive = node.left; System.out.println("Need to keep alive "+keepAlive.key) ; }
        
        Node newNode = new Node(node.key, null, node.right.left, node);
        node.left = newNode;
        node.key = node.right.key;
        //Handling two special cases
        if (node.right.left != null) node.right.left.father = newNode;
        if (node.right.right != null) node.right.right.father = node; 
        
        node.right = node.right.right;
        if(keepAlive!=null){ node.left.left = keepAlive; keepAlive.father = node.left;}
        updateHeights(newNode);
    }

    void rotateRight(Node node) {
        //Left heavy - Rotate right
        System.out.println("Need to rotate node " + node + " right!");
        
        //In case it's a Right-Left rotation
        Node keepAlive = null;
        if(node.right!= null){ keepAlive = node.right; System.out.println("Need to keep alive "+keepAlive.key);}
        
        Node newNode = new Node(node.key, node.left.right, null, node);
        node.right = newNode;
        node.key = node.left.key;
        //Handle two special cases
        if (node.left.right != null) node.left.right.father = newNode;
        if (node.left.left != null) node.left.left.father = node;
        
        node.left = node.left.left;
        if(keepAlive!=null){ node.right.right = keepAlive; keepAlive.father = node.right;}
        updateHeights(newNode);
    } 
    
    public static void main(String[] args) {
        AVL avl = new AVL();
        avl.consoleUI(); 
    }
}

You can test building and modifying some random AVLs. Here's a link: AVL Example
I've tested it on the AVLs given in the link above. Output shown is on the trees shown in the link.

Output [Note: -999 is the end marker]:

1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

1
15 20 24 10 13 7 30 36 25 -999
Need to rotate node key = 15 height = 2 left!
Need to rotate node key = 10 height = 1 left!
Need to rotate node key = 15 height = 2 right!
Need to rotate node key = 20 height = 3 right!
Need to keep alive 24
Need to rotate node key = 24 height = 2 left!
Need to rotate node key = 30 height = 2 right!
Need to keep alive 36
Need to rotate node key = 20 height = 3 left!
Need to keep alive 15
key = 7 height = 0
key = 10 height = 1
key = 13 height = 3
key = 15 height = 0
key = 20 height = 1
key = 24 height = 2
key = 25 height = 0
key = 30 height = 1
key = 36 height = 0

1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

2
24 -999

Deleting item 24: deleted!
key = 7 height = 0
key = 10 height = 1
key = 13 height = 3
key = 15 height = 0
key = 20 height = 1
key = 25 height = 2
key = 30 height = 1
key = 36 height = 0

1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

2
20 -999

Deleting item 20: deleted!
key = 7 height = 0
key = 10 height = 1
key = 13 height = 3
key = 15 height = 0
key = 25 height = 2
key = 30 height = 1
key = 36 height = 0

1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

Saturday, September 27, 2014

Binary Search Tree Operations [Find, Insert, Delete, Print][Using Father Node Field][BST][Java Implementation]

Previous post on BST did not use Father field. This program uses Father field in Node.

Source:

import java.util.Scanner;

public class BSTFather {

    Node root;

    class Node {

        Node father, left, right;
        int key;

        public Node(int key, Node left, Node right, Node father) {
            this.key = key;
            this.left = left;
            this.right = right;
            this.father = father;
        }

        public String toString() {
            return Integer.toString(key);
        }
    }

    public void insert(Node toInsert, Node node) {
        if (root == null) {
            root = toInsert;
            return;
        }

        if (toInsert.key < node.key) {
            if (node.left != null) {
                insert(toInsert, node.left);
            } else { 
                toInsert.father = node;
                node.left = toInsert;
            }
        } else if (toInsert.key >= node.key) {
            if (node.right != null) {
                insert(toInsert, node.right);
            } else { 
                toInsert.father = node;
                node.right = toInsert;
            }
        }
    }

    public Node findNode(Node findNode, Node node) {
        if (root == null) {
            return null;
        }

        if (findNode.key < node.key) {
            if (node.left != null) {
                return findNode(findNode, node.left);
            } 
        } else if (findNode.key > node.key) {
            if (node.right != null) {
                return findNode(findNode, node.right);
            } 
        } else if (findNode.key == node.key) {
            return node;
        }
        return null;
    }

    public boolean deleteNode(Node deleteNode, Node node) {
        if (root == null) return false;
        else if (root.key == deleteNode.key) {
            if(root.left == null && root.right == null) root = null;
            else if (root.left == null) { root = root.right; root.father = null; }
            else if (root.right == null) { root = root.left; root.father = null; }
            else {
                Node min = root.right;
                //min element has no left or right child.
                if(min.left==null && min.right==null){
                    root.key = min.key;
                    root.right = null; 
                    return true;
                } 
                while(min.left!=null){
                    //Min element has left child.
                    min = min.left;
                }
                root.key = min.key; 
                if(min.right!=null) min.right.father = min.father;
                //Min element has no left child but has right child.
                if(min.father!=root) min.father.left = min.right;
                else{ min.father.right = min.right;} 
            }
            return true;
        }
        else { 
            Node locatedNode = findNode(deleteNode, root); 
            if(locatedNode!=null) deleteHelper(locatedNode);
            else return false;
        }
        return true;
    }

    private void deleteHelper(Node locatedNode) {
        boolean left = (locatedNode.father.left == locatedNode); 
        if(locatedNode.right == null && locatedNode.left == null){
            if(left) locatedNode.father.left = null;
            else locatedNode.father.right = null;
        }
        else if(locatedNode.left!=null && locatedNode.right == null){ 
            locatedNode.left.father = locatedNode.father;
            if(left) locatedNode.father.left = locatedNode.left;
            else locatedNode.father.right = locatedNode.left;
        }else if(locatedNode.left==null && locatedNode.right!=null){
            locatedNode.right.father = locatedNode.father;
            if(left) locatedNode.father.left = locatedNode.right;
            else locatedNode.father.right = locatedNode.right;
        }else if(locatedNode.left!=null && locatedNode.right!=null){ 
            Node min = locatedNode.right;
            //min element has no left or right child.
            if(min.left==null && min.right==null){
                locatedNode.key = min.key;
                locatedNode.right = null;
                return;
            } 
            while(min.left!=null){
                //Min element has left child.
                min = min.left;
            }
            locatedNode.key = min.key; 
            if(min.right!=null) min.right.father = min.father;
            //Min element has no left child but has right child.
            if(min.father!=locatedNode) min.father.left = min.right;
            else{ min.father.right = min.right;} 
            
        }
    }

    public void deleteTree(){
        root = null;
    }
    
    public void printTree(Node node) {
        if (node == null) {
            return;
        }
        printTree(node.left);
        System.out.print(node.key+" ");
        printTree(node.right);
    }

    public void consoleUI(){
        Scanner scan = new Scanner(System.in);  
        while (true) {
            System.out.println("\n1.- Add items\n"
                    + "2.- Delete items\n"
                    + "3.- Check items\n"
                    + "4.- Print tree\n"
                    + "5.- Delete tree\n");
            int choice = scan.nextInt();

            int item;
            Node node;
            switch (choice) {
                case 1:
                    item = scan.nextInt(); 
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        insert(node, root);
                        item = scan.nextInt(); 
                    }
                    printTree(root);
                    break;
                case 2:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        System.out.print("\nDeleting item "+item); 
                        if(deleteNode(node, root)){
                            System.out.print(": deleted!"); 
                        }else
                            System.out.print(": does not exist!"); 
                        item = scan.nextInt();
                    }
                    System.out.println();
                    printTree(root);
                    break;
                case 3:
                    item = scan.nextInt();
                    while (item != -999) {
                        node = new Node(item, null, null, null);
                        System.out.println((findNode(node, root)!=null)?"found":"not found");
                        item = scan.nextInt();
                    }
                    break;
                case 4:
                    printTree(root);
                    break;
                case 5:
                    deleteTree();
                    System.out.println("Tree deleted!");
                    break;
            }
        }
    }
    
    public static void main(String[] args) {
        BSTFather bst = new BSTFather();   
        bst.consoleUI();
        
    }
}

Output:

1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

1
1 2 77 5 4 99 7 4 6 -999
1 2 4 4 5 6 7 77 99 
1.- Add items
2.- Delete items
3.- Check items
4.- Print tree
5.- Delete tree

2
4 5 7 4 6 77 99 1 2 -999

Deleting item 4: deleted!
Deleting item 5: deleted!
Deleting item 7: deleted!
Deleting item 4: deleted!
Deleting item 6: deleted!
Deleting item 77: deleted!
Deleting item 99: deleted!
Deleting item 1: deleted!
Deleting item 2: deleted!

As expected!