Hacks

Analyze the Big O complexity on Sorts.

  • Establish analytics including:time to sort, number of comparisons and number of swaps.- Average the results for each each Sort, run each at least 12 times and 5000 elements. You should throw out High and Low when doing analysis.
  • Make your final/judgement on best sort: Number of Comparisons, Number of Swaps, Big O complexity, and Total Time.
public class SortAnalysis {
    // generate array of 5000 integers
    public static int[] generateArray() {
        int[] arr = new int[5000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 10000);
        }
        return arr;
    }
    
    public static float[] main(String[] args) {

        System.out.println("-------------------------------");

        // create an array with 5000 elements
        int[] arr1 = generateArray();
        int[] arr2 = new int[5000];
        int[] arr3 = new int[5000];
        int[] arr4 = new int[5000];
        System.arraycopy(arr1, 0, arr2, 0, 500);
        System.arraycopy(arr1, 0, arr3, 0, 500);
        System.arraycopy(arr1, 0, arr4, 0, 500);

        float[] times = new float[4];
        String str = "";

        // sort the array
        long start = System.nanoTime();
        bubbleSort(arr1);
        long end = System.nanoTime();
        // print the time it took
        str += ((end - start) + "ns | ");
        times [0] = (end - start);

        start = System.nanoTime();
        mergeSort(arr2);
        end = System.nanoTime();
        // print the time it took
        str += ((end - start) + "ns | ");
        times [1] = (end - start);

        start = System.nanoTime();
        selectionSort(arr3);
        end = System.nanoTime();
        // print the time it took
        str += ((end - start) + "ns | ");
        times [2] = (end - start);

        start = System.nanoTime();
        insertionSort(arr4);
        end = System.nanoTime();
        // print the time it took
        str += ((end - start) + "ns");
        times [3] = (end - start);
        System.out.println(str);

        return times;
    }

    public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    // instertionsort from before
    public static void insertionSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int current = arr[i];
            int j = i - 1;
            while (j >= 0 && current < arr[j]) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = current;
        }
    }

    // selectionsort from before
    public static void selectionSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

    // mergesort from previous lesson
    public static void mergeSort(int[] arr) {
        if (arr.length > 1) {
            int[] left = leftHalf(arr);
            int[] right = rightHalf(arr);

            mergeSort(left);
            mergeSort(right);

            merge(arr, left, right);
        }
    }

    // lefthalf function for mergesort
    public static int[] leftHalf(int[] arr) {
        int size1 = arr.length / 2;
        int[] left = new int[size1];
        for (int i = 0; i < size1; i++) {
            left[i] = arr[i];
        }
        return left;
    }

    // righthalf function for mergesotr
    public static int[] rightHalf(int[] arr) {
        int size1 = arr.length / 2;
        int size2 = arr.length - size1;
        int[] right = new int[size2];
        for (int i = 0; i < size2; i++) {
            right[i] = arr[i + size1];
        }
        return right;
    }

    public static int[] merge(int[] result, int[] left, int[] right) {
        int i1 = 0;
        int i2 = 0;

        for (int i = 0; i < result.length; i++) {
            if (i2 >= right.length || (i1 < left.length && left[i1] <= right[i2])) {
                result[i] = left[i1];
                i1++;
            } else {
                result[i] = right[i2];
                i2++;
            }
        }
        return result;
    }
}

System.out.println("Bubble | Merge | Selection | Insertion");
float[] means = new float[4];


for (int i = 0; i < 12; i++) {
    float[] a = SortAnalysis.main(null);
    
    for (int j = 0; j < 4; j++) {
        means[j] += a[j];
    }
}

for (int i = 0; i < 4; i++) {
    means[i] /= 12;
    means[i] = Math.round(means[i] * 1000) / 1000;
}

System.out.println("-------------------------------");
System.out.println("Average: " + means[0] + "ns | " + means[1] + "ns | " + means[2] + "ns | " + means[3] + "ns");
Bubble | Merge | Selection | Insertion
-------------------------------
22766366ns | 1678701ns | 6293168ns | 711223ns
-------------------------------
15671696ns | 1275861ns | 9018750ns | 1731988ns
-------------------------------
15910436ns | 1457726ns | 5538702ns | 995820ns
-------------------------------
15863990ns | 1662630ns | 5643207ns | 595193ns
-------------------------------
16892075ns | 1481931ns | 6411689ns | 799843ns
-------------------------------
14669169ns | 2937441ns | 11171519ns | 759446ns
-------------------------------
16550877ns | 1888868ns | 5976734ns | 671598ns
-------------------------------
16588768ns | 1175102ns | 5413783ns | 683402ns
-------------------------------
15727435ns | 731586ns | 5742831ns | 682431ns
-------------------------------
15799026ns | 328186ns | 6109086ns | 601344ns
-------------------------------
17061466ns | 406177ns | 8231558ns | 1065207ns
-------------------------------
16785958ns | 343330ns | 5636475ns | 744870ns
-------------------------------
Average: 2147483.0ns | 1280628.0ns | 2147483.0ns | 836863.0ns
  • Bubble complexity: O(n^2) - but best case scenario is O(n) only if the list is already sorted
  • Merge complexity: O(n log n)
  • Selection complexity: O(n^2) regardless of the order
  • Insertion complexity: O(n^2) - best case scenario is also O(n) if sorted

Build your own Hashmap. Make a HashMap to correspond to a Data Structure using a Collection.

  • Be sure to have 5000 records
  • Perform analysis on Binary Search vs HashMap Lookup, try using random to search and find 100 keys in 5000 records. Perform 12 times and throw out high and low.
import java.util.HashMap;
import java.lang.Integer;
import java.util.Scanner;

public class HashTester {
    public static void main(String[] args) {

        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        int[] arr = new int[500000];

        for (int i = 0; i < 500000; i++) {
            Integer value = (int) (Math.random() * 500000);
            map.put(value, value);
            arr[i] = value;
        }

        System.out.println("LookUp | BinarySearch");
        System.out.println("-------------------------------");

        double total_lut = 0;
        double total_bst = 0;

        // get num to search for from scanner
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter a number to search for: ");
        Integer num = sc.nextInt(); 

        for (int i = 0; i < 12; i++) {
            
            // check look up time for hash map
            String str = "|      ";
            long lut = (lookUp(map, num));
            total_lut += lut;
            str += (lut + "ns       |       ");
            
            // copy array, check binary search time
            int[] arra = new int[500000];
            System.arraycopy(arr, 0, arra, 0, arr.length);
            long bst = (binarySearchTime(arra, num));
            total_bst += bst;
            str += (bst + "ns      | ");

            System.out.println(str);
        }

        System.out.println("-------------------------------");
        System.out.println("Average: " + (total_lut / 12) + "ns | " + (total_bst / 12) + "ns");
    }

    public static long lookUp(HashMap<Integer, Integer> map, Integer value) {
        long start = System.nanoTime();
        map.containsKey(value);
        long end = System.nanoTime();
        return (end - start);
    }

    public static long binarySearchTime(int[] arr, Integer value) {
        long start = System.nanoTime();
        // binary search 
        int low = 0;
        int high = arr.length - 1;
        int mid = (low + high) / 2;
        while (low <= high) {
            if (arr[mid] < value) {
                low = mid + 1;
            } else if (arr[mid] == value) {
                break;
            } else {
                high = mid - 1;
            }
            mid = (low + high) / 2;
        }
        long end = System.nanoTime();
        return (end - start);
    }
}

HashTester.main(null);
LookUp | BinarySearch
-------------------------------
Enter a number to search for: 
|      16186ns       |       7407ns      | 
|      1051ns       |       4008ns      | 
|      1061ns       |       4231ns      | 
|      933ns       |       3848ns      | 
|      1046ns       |       4067ns      | 
|      621ns       |       3377ns      | 
|      641ns       |       3526ns      | 
|      612ns       |       4296ns      | 
|      1042ns       |       3338ns      | 
|      624ns       |       4066ns      | 
|      831ns       |       3949ns      | 
|      771ns       |       4909ns      | 
-------------------------------
Average: 2118.25ns | 4251.833333333333ns

Pros and Cons of Collection vs HashMap

Collections HashMaps
Pros Cons Pros Cons
Store and manipulate groups of objects Java doesn't integrate any methods to search or sort Map keys to values More memory usage than collections
Order of elements in a group, can reorder them too Inefficient at getting a specific value Retrieving a value from a key is very fast No order of elements, no sorting
Easy for simple uses like when you don't need key:value pairs Key:value mapping isn't a thing Built-in methods for search/sort such as containsKey() or getValue() Starts to get a bit weird / errors with duplicate keys