private void merge(T[] arr, int low, int mid, int high){
        Object[] helper = new Object[(high - low) + 1];
        int i = 0;
        int l = low;
        int r = mid + 1;
        
        //Put the smallest element into helper array until all
        //elements from both (or either) are used.
        while(l <= mid && r <= high){
            if(arr[l].compareTo(arr[r]) < 0){
                helper[i] = arr[l]; 
                i++; l++;
            }
            else{
                helper[i] = arr[r]; 
                i++; r++;
            }
        }
        
        //If one array ran out of elements before the other, add the rest from 
        //the other. 
        if(l > mid){
            while(r <= high){
                helper[i] = arr[r]; 
                i++; r++;
            } 
        }
        if(r > high){
            while(l <= mid){
                helper[i] = arr[l]; 
                i++; l++;
            }
        }
        
        //Put the sorted elements from helper back into array.
        for(int arrInd = low, helpInd = 0; helpInd < helper.length; arrInd++, helpInd++){
            arr[arrInd] = (T) helper[helpInd]; 
        }
    }