diff --git a/src/main/java/algorithms/HeapSort.java b/src/main/java/algorithms/HeapSort.java new file mode 100644 index 0000000..80df5a9 --- /dev/null +++ b/src/main/java/algorithms/HeapSort.java @@ -0,0 +1,82 @@ +package algorithms; + +import ui.Utils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +public class HeapSort extends AlgorithmSort { + private int comparisonCount = 0; + private int swapCount = 0; + + public HeapSort(ArrayList array) { + super(array); + } + + @Override + public void sort() { + int n = array.size(); + Set sortedIndices = new HashSet<>(); + int SLEEP_DURATION = 40; + + // Build the max heap + for (int i = n / 2 - 1; i >= 0; i--) { + heapify(n, i, sortedIndices, SLEEP_DURATION); + } + + // Extract elements one by one from the heap + for (int i = n - 1; i > 0; i--) { + // Swap current root to end + Utils.swapHighlighted(array, 0, i, sortedIndices, SLEEP_DURATION * 2); + swapCount++; + sortedIndices.add(i); // Mark as sorted + heapify(i, 0, sortedIndices, SLEEP_DURATION); // Heapify the reduced heap + } + // Mark the last element as sorted + sortedIndices.add(0); + + Utils.displayVerticalArray(array, -1, -1, sortedIndices); + + clearScreen(); + printStatistics(); + } + + private void heapify(int n, int i, Set sortedIndices, int sleepDuration) { + int largest = i; + int left = 2 * i + 1; + int right = 2 * i + 2; + + if (left < n && array.get(left) > array.get(largest)) { + largest = left; + comparisonCount++; + } + + if (right < n && array.get(right) > array.get(largest)) { + largest = right; + comparisonCount++; + } + + if (largest != i) { + Utils.swapHighlighted(array, i, largest, sortedIndices, sleepDuration); // Swap and highlight + swapCount++; + heapify(n, largest, sortedIndices, sleepDuration); // Recursively heapify the affected subtree + } + } + + private void printStatistics() { + System.out.println("\n========= Heap Sort Statistics: ========="); + System.out.printf("+--------------------+--------------------+%n"); + System.out.printf("| Metric | Value |%n"); + System.out.printf("+--------------------+--------------------+%n"); + System.out.printf("| Array Size | %-18d |%n", array.size()); + System.out.printf("| Total Comparisons | %-18d |%n", comparisonCount); + System.out.printf("| Total Swaps/Shifts | %-18d |%n", swapCount); + System.out.printf("+--------------------+--------------------+%n"); + } + + public static void clearScreen() { + System.out.print("\033[H\033[2J"); + System.out.flush(); + } +} diff --git a/src/main/java/algorithms/InsertionSort.java b/src/main/java/algorithms/InsertionSort.java index 642c35d..788700c 100644 --- a/src/main/java/algorithms/InsertionSort.java +++ b/src/main/java/algorithms/InsertionSort.java @@ -6,76 +6,87 @@ import java.util.HashSet; import java.util.Set; -public class InsertionSort extends SortingAlgorithm { + +public class InsertionSort extends AlgorithmSort { + private int comparisonCount = 0; + private int swapCount = 0; public InsertionSort(ArrayList array) { super(array); + } @Override public void sort() { - int SLEEP_DURATION = 2; - Set sortedIndices = new HashSet<>(); - if (array.isEmpty()) { System.out.println("Array is empty, nothing to sort."); return; } + Set sortedIndices = new HashSet<>(); int n = array.size(); + for (int i = 1; i < n; i++) { + int sleepDuration = 10 + (i * 2); // Dynamic delay for shifts and comparisons + int highlightSortedElementDelay = 10 + (i * 5); // Delay specifically for highlighting sorted elements + + int key = array.get(i); int j = i - 1; - // Highlight the initial key element before shifting - highlightInsertion(array, i, -1, -1, sortedIndices, SLEEP_DURATION); - // Shift elements to the right and highlight each shift + // Highlight the key element: = YELLOW = + highlightElement(array, i, "\033[33m", sortedIndices, sleepDuration); + + // Shift elements in sorted portion to make space for key: = RED = while (j >= 0 && array.get(j) > key) { + comparisonCount++; array.set(j + 1, array.get(j)); - highlightInsertion(array, i, j, j + 1, sortedIndices, SLEEP_DURATION); - j = j - 1; + highlightElement(array, j + 1, "\033[31m", sortedIndices, sleepDuration); + j--; } - // Place the key in the correct position + // Show target position in: = BLUE = before insertion + highlightElement(array, j + 1, "\033[34m", sortedIndices, sleepDuration * 2); array.set(j + 1, key); - highlightInsertion(array, -1, j + 1, j + 1, sortedIndices, SLEEP_DURATION); + swapCount++; - // Mark the element as sorted - sortedIndices.add(i); + // Delay and mark as sorted in: = GREEN = + try { + Thread.sleep(highlightSortedElementDelay); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + sortedIndices.add(j + 1); + Utils.displayVerticalArray(array, -1, -1, sortedIndices); } - // Mark all elements as sorted for the final display + highlightEverything(sortedIndices); Utils.displayVerticalArray(array, -1, -1, sortedIndices); + printStatistics(); } - static void highlightInsertion(ArrayList arrayList, int keyIndex, int shiftIndex, int targetIndex, Set sortedIndices, int sleepDuration) { - final String RESET = "\033[0m"; - final String YELLOW = "\033[33m"; // Key element - final String RED = "\033[31m"; // Shifted elements - final String BLUE = "\033[34m"; // Target position - final String GREEN = "\033[32m"; // Sorted elements + private static void highlightElement(ArrayList array, int index, String color, Set sortedIndices, int sleepDuration) { + final String RESET = "\033[0m"; + final String GREEN = "\033[32m"; + final String SQUARE = "◼"; StringBuilder output = new StringBuilder(); - int maxHeight = Utils.findMax(arrayList); + int maxHeight = Utils.findMax(array); for (int row = maxHeight; row > 0; row--) { - output.append("\033[2K"); // Clear the whole line - - for (int col = 0; col < arrayList.size(); col++) { - int element = arrayList.get(col); - + output.append("\033[2K"); + for (int col = 0; col < array.size(); col++) { + int element = array.get(col); if (element >= row) { - if (sortedIndices.contains(col)) { - output.append(GREEN).append("#").append(RESET); - } else if (col == keyIndex) { - output.append(YELLOW).append("#").append(RESET); - } else if (col == shiftIndex) { - output.append(RED).append("#").append(RESET); - } else if (col == targetIndex) { - output.append(BLUE).append("#").append(RESET); - } else { - output.append("#"); + if (col == index) { + output.append(color).append(SQUARE).append(RESET); // Highlight element in specified color + } //else if (sortedIndices.contains(col)) { + //output.append(GREEN).append(SQUARE).append(RESET); + // } + else { + output.append(SQUARE); } } else { output.append(" "); @@ -88,10 +99,28 @@ static void highlightInsertion(ArrayList arrayList, int keyIndex, int s System.out.print("\033[" + maxHeight + "F"); try { - Thread.sleep(100); + Thread.sleep(sleepDuration); } catch (InterruptedException e) { throw new RuntimeException(e); } } + private void highlightEverything(Set sortedIndices){ + for (int i = 0; i < array.size(); i++) { + sortedIndices.add(i); + } + } + + private void printStatistics() { + System.out.println("\n===== Insertion Sort Statistics: ====="); + System.out.printf("+--------------------+--------------------+%n"); + System.out.printf("| Metric | Value |%n"); + System.out.printf("+--------------------+--------------------+%n"); + System.out.printf("| Array Size | %-18d |%n", array.size()); + System.out.printf("| Total Comparisons | %-18d |%n", comparisonCount); + System.out.printf("| Total Swaps/Shifts | %-18d |%n", swapCount); + System.out.printf("+--------------------+--------------------+%n"); + } } + +