Basic Insertion Sort
Problem Statement
Write a Java program that implements the Insertion Sort algorithm to sort an array of integers in ascending order. The program should count the number of shifts performed (the number of times elements are moved to make space for insertion) and test the implementation with various input arrays, including unsorted, already sorted, reversed, and arrays with duplicate elements. Insertion Sort builds a sorted portion of the array from the start, inserting each new element into its correct position by shifting larger elements. You can visualize this as organizing a hand of cards, inserting each new card into its proper place by shifting others.
Input:
- An array of integers to be sorted. Output: The sorted array, the number of shifts performed, and a string representation of the input and sorted arrays for clarity. Constraints:
- The array length
nis between 0 and 10^5. - Array elements are integers in the range [-10^9, 10^9]. Example:
- Input: array = [64, 34, 25, 12, 22]
- Output:
- Input Array: [64, 34, 25, 12, 22]
- Sorted Array: [12, 22, 25, 34, 64]
- Shifts: 10
- Explanation: Insertion Sort inserts each element, shifting larger ones, resulting in 10 shifts.
- Input: array = [1, 2, 3]
- Output:
- Input Array: [1, 2, 3]
- Sorted Array: [1, 2, 3]
- Shifts: 0
- Explanation: Already sorted array requires no shifts.
Pseudocode
FUNCTION insertionSort(arr)
SET n to length of arr
CREATE shifts as integer, initialized to 0
FOR i from 1 to n-1
SET key to arr[i]
SET j to i - 1
WHILE j >= 0 AND arr[j] > key
SET arr[j + 1] to arr[j]
INCREMENT shifts
DECREMENT j
ENDWHILE
SET arr[j + 1] to key
ENDFOR
RETURN shifts
ENDFUNCTION
FUNCTION toString(arr)
CREATE result as new StringBuilder
APPEND "[" to result
FOR each element in arr
APPEND element to result
IF element is not last THEN
APPEND ", " to result
ENDIF
ENDFOR
APPEND "]" to result
RETURN result as string
ENDFUNCTION
FUNCTION main()
SET testCases to array of input arrays
FOR each testCase in testCases
PRINT test case details
CREATE copy of testCase array
SET shifts to insertionSort(copy)
PRINT input array, sorted array, and shifts
ENDFOR
ENDFUNCTION
Algorithm Steps
- Define
insertionSort: a. Initialize a countershiftsto 0. b. For each index i from 1 to n-1:- Store arr[i] as
key. - Shift elements arr[j] (j from i-1 down to 0) that are greater than
keyone position forward, incrementingshiftsfor each move. - Insert
keyat the correct position. c. Return the number of shifts.
- Store arr[i] as
- Define
toString: a. Convert the array to a string, e.g., "[64, 34, 25, 12, 22]". - In
main, test with: a. An unsorted array. b. An already sorted array. c. A reversed array. d. An array with duplicates. e. An empty array.
Java Implementation
import java.util.*;
public class BasicInsertionSort {
// Performs Insertion Sort and counts shifts
public int insertionSort(int[] arr) {
int n = arr.length;
int shifts = 0;
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
shifts++;
j--;
}
arr[j + 1] = key;
}
return shifts;
}
// Converts array to string
public String toString(int[] arr) {
StringBuilder result = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
result.append(arr[i]);
if (i < arr.length - 1) {
result.append(", ");
}
}
result.append("]");
return result.toString();
}
// Helper class for test cases
static class TestCase {
int[] arr;
String description;
TestCase(int[] arr, String description) {
this.arr = arr;
this.description = description;
}
}
// Main method to test Insertion Sort
public static void main(String[] args) {
BasicInsertionSort sorter = new BasicInsertionSort();
// Test cases
TestCase[] testCases = {
new TestCase(new int[]{64, 34, 25, 12, 22}, "Unsorted"),
new TestCase(new int[]{1, 2, 3, 4, 5}, "Sorted"),
new TestCase(new int[]{5, 4, 3, 2, 1}, "Reversed"),
new TestCase(new int[]{3, 1, 3, 2, 1}, "Duplicates"),
new TestCase(new int[]{}, "Empty")
};
// Run test cases
for (int i = 0; i < testCases.length; i++) {
System.out.println("Test case " + (i + 1) + ": " + testCases[i].description);
int[] arr = testCases[i].arr.clone(); // Copy to preserve original
System.out.println("Input Array: " + sorter.toString(arr));
int shifts = sorter.insertionSort(arr);
System.out.println("Sorted Array: " + sorter.toString(arr));
System.out.println("Shifts: " + shifts + "\n");
}
}
}
Output
Running the main method produces:
Test case 1: Unsorted
Input Array: [64, 34, 25, 12, 22]
Sorted Array: [12, 22, 25, 34, 64]
Shifts: 10
Test case 2: Sorted
Input Array: [1, 2, 3, 4, 5]
Sorted Array: [1, 2, 3, 4, 5]
Shifts: 0
Test case 3: Reversed
Input Array: [5, 4, 3, 2, 1]
Sorted Array: [1, 2, 3, 4, 5]
Shifts: 10
Test case 4: Duplicates
Input Array: [3, 1, 3, 2, 1]
Sorted Array: [1, 1, 2, 3, 3]
Shifts: 5
Test case 5: Empty
Input Array: []
Sorted Array: []
Shifts: 0
Explanation:
- Test case 1: Unsorted array requires 10 shifts to sort.
- Test case 2: Already sorted array requires 0 shifts.
- Test case 3: Reversed array requires 10 shifts (worst case).
- Test case 4: Array with duplicates requires 5 shifts.
- Test case 5: Empty array requires 0 shifts.
How It Works
- insertionSort:
- Iterates from index 1 to n-1, treating arr[0..i-1] as sorted.
- For each element (key), shifts larger elements in the sorted portion one position forward, counting each shift.
- Inserts the key in the correct position.
- toString: Formats array as a string for output.
- Example Trace (Test case 1):
- i=1: key=34, shift 64: [34, 64, 25, 12, 22] (1 shift).
- i=2: key=25, shift 64, 34: [25, 34, 64, 12, 22] (2 shifts).
- i=3: key=12, shift 64, 34, 25: [12, 25, 34, 64, 22] (3 shifts).
- i=4: key=22, shift 64, 34, 25: [12, 22, 25, 34, 64] (4 shifts).
- Total shifts: 10.
- Main Method: Tests unsorted, sorted, reversed, duplicates, and empty arrays.
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| insertionSort | O(n²) worst, O(n) best | O(1) |
| toString | O(n) | O(n) |
Note:
- n is the array length.
- Time complexity: O(n²) for insertionSort in worst/average cases (reversed or random); O(n) in best case (sorted); O(n) for toString.
- Space complexity: O(1) for insertionSort (in-place); O(n) for toString (string builder).
- Shifts depend on input order, with fewer shifts for nearly sorted arrays.
✅ Tip: Insertion Sort is efficient for small or nearly sorted arrays due to fewer shifts in the best case. Count shifts instead of swaps to accurately measure its work.
⚠ Warning: Ensure the array is copied before sorting to preserve the original for display. Handle empty arrays to avoid index issues in the sorting loop.