package com.hithomelabs.princeton1.module7;

import com.hithomelabs.princeton1.module5.AbstractCustomSorts;


public class Quick<E> extends AbstractCustomSorts<E> {
    @Override
    public void sort(E[] arr) {
        randomShuffle(arr);
        partition(arr, 0, arr.length-1);
    }

    private void randomShuffle(E[] arr){
        int array_len = arr.length;
        for(int i=0; i< array_len; i++){
            int random_index = (int)(Math.random()*array_len);
            exch(arr, i, random_index);
        }
    }

    private void partition(E[] arr, int low, int high){
        if(low >= high)
            return;
        int mid = sort(arr, low, high);
        partition(arr, low, mid-1);
        partition(arr, mid + 1, high);
    }

    private int sort(E[] arr, int low, int high){
        int i = low+1;
        int j = high;
        while (true){
            // Find the i index greater than 1st element
            while (i<=high && !less((Comparable<E>) arr[low], arr[i]))
                i++;
            // Find the j index less than 1st element
            while (less((Comparable<E>) arr[low], arr[j]) && j > low)
                j--;
            // Break if indexes are crossed
            if(j < i)
                break;
            // Swap index values of i & j
            if(less((Comparable<E>) arr[j], arr[i]))
                exch(arr, i, j);
        }
        // Swap 1st element to it's correct position
        exch(arr, low, j);
        return j;
    }
}
