package com.hithomelabs.princeton1.module6; import com.hithomelabs.princeton1.module5.ComparableSort; import com.hithomelabs.princeton1.module5.MeasurableHelper; import com.hithomelabs.princeton1.module5.MeasurableSort; import com.hithomelabs.princeton1.module5.SortingMetaData; import java.util.Arrays; import java.util.Comparator; public class Merge implements MeasurableSort, MeasurableHelper { @Override public void sort(E[] arr) { coreSortLogic(arr, null, null); } private void coreSortLogic(E[] arr, Comparator cmp, SortingMetaData metaData) { int N = arr.length; // * * aux is a helper array required for merge E[] aux = Arrays.copyOf(arr, N); mergesort(arr, aux, 0, N - 1, cmp, metaData); } private void mergesort(E[] arr, E[] aux, int lo, int hi, Comparator cmp, SortingMetaData metaData) { if (hi <= lo) return; int mid = lo + (hi - lo) / 2; mergesort(arr, aux, lo, mid, cmp, metaData); mergesort(arr, aux, mid + 1, hi, cmp, metaData); merge(arr, aux, lo, mid, hi, cmp, metaData); } private void merge(E[] arr, E[] aux, int lo, int mid, int hi, Comparator cmp, SortingMetaData metaData) { // * * creating backup of original array for (int i = lo; i <= hi; i++) aux[i] = arr[i]; int i = lo; int j = mid + 1; for (int k = lo; k <= hi; k++) { // * If i has already reached mid, no need to compare we insert at pointer k if (i > mid) { arr[k] = aux[j++]; if (metaData != null) metaData.incrementCompares(); } else if (j > hi) { arr[k] = aux[i++]; if (metaData != null) metaData.incrementCompares(); } else if (MeasurableHelper.less( aux[i], aux[j], cmp, metaData)) { arr[k] = aux[i++]; } else arr[k] = aux[j++]; } } @Override public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { if (metaData != null) metaData.startTime(); coreSortLogic(arr, cmp, metaData); if (metaData != null) metaData.endTime(); } @Override public void sort(E[] arr, Comparator cmp) { coreSortLogic(arr, cmp, null); } }