Selection Sort for String Arrays
Problem Statement
Write a Java program that extends the Selection Sort implementation to sort an array of strings lexicographically in ascending order (based on Unicode values, case-sensitive). The program should count the number of swaps performed and test with string arrays containing strings of varying lengths (short, medium, long) and cases (mixed upper/lowercase, all lowercase), including edge cases like empty arrays and arrays with duplicate strings. Selection Sort will find the lexicographically smallest string in each pass and swap it with the first unsorted element. You can visualize this as organizing a list of words alphabetically, selecting the "smallest" word (e.g., "apple" before "Banana") to build the sorted list.
Input:
- An array of strings to be sorted lexicographically. Output: The sorted array, the number of swaps performed, and a string representation of the input and sorted arrays for clarity. Constraints:
- The array length
nis between 0 and 10^5. - Strings can be of any length and contain any valid Unicode characters. Example:
- Input: array = ["banana", "Apple", "cherry", "date"]
- Output:
- Input Array: [banana, Apple, cherry, date]
- Sorted Array: [Apple, banana, cherry, date]
- Swaps: 2
- Explanation: Selection Sort sorts lexicographically (case-sensitive, "Apple" < "banana"), requiring 2 swaps.
- Input: array = ["cat", "Cat", "CAT"]
- Output:
- Input Array: [cat, Cat, CAT]
- Sorted Array: [CAT, Cat, cat]
- Swaps: 2
- Explanation: Case-sensitive sorting places uppercase before lowercase, 2 swaps.
Pseudocode
FUNCTION selectionSort(arr)
SET n to length of arr
CREATE swaps as integer, initialized to 0
FOR i from 0 to n-1
SET minIdx to i
FOR j from i+1 to n-1
IF arr[j] < arr[minIdx] THEN
SET minIdx to j
ENDIF
ENDFOR
IF minIdx != i THEN
SET temp to arr[i]
SET arr[i] to arr[minIdx]
SET arr[minIdx] to temp
INCREMENT swaps
ENDIF
ENDFOR
RETURN swaps
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 string arrays
FOR each testCase in testCases
PRINT test case details
CREATE copy of testCase array
SET swaps to selectionSort(copy)
PRINT input array, sorted array, and swaps
ENDFOR
ENDFUNCTION
Algorithm Steps
- Define
selectionSort(generic): a. Accept an array ofComparable<T>type (useStringfor testing). b. Initialize a counterswapsto 0. c. For each index i from 0 to n-1:- Find the index
minIdxof the lexicographically smallest element in arr[i..n-1] usingcompareTo. - If
minIdx!= i, swap arr[i] with arr[minIdx] and incrementswaps. d. Return the number of swaps.
- Find the index
- Define
toString: a. Convert the array to a string, e.g., "[banana, Apple, cherry]". - In
main, test with: a. Mixed case strings (short, n=4). b. Mixed case strings with duplicates (n=5). c. Long strings (n=6). d. Empty array (n=0). e. Single-element array (n=1). f. All lowercase strings (n=7).
Java Implementation
import java.util.*;
public class SelectionSortStringArray {
// Performs Selection Sort for Comparable types and counts swaps
public <T extends Comparable<T>> int selectionSort(T[] arr) {
int n = arr.length;
int swaps = 0;
for (int i = 0; i < n; i++) {
int minIdx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j].compareTo(arr[minIdx]) < 0) {
minIdx = j;
}
}
if (minIdx != i) {
T temp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = temp;
swaps++;
}
}
return swaps;
}
// Converts array to string
public <T> String toString(T[] 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 {
String[] arr;
String description;
TestCase(String[] arr, String description) {
this.arr = arr;
this.description = description;
}
}
// Main method to test string Selection Sort
public static void main(String[] args) {
SelectionSortStringArray sorter = new SelectionSortStringArray();
// Test cases
TestCase[] testCases = {
new TestCase(new String[]{"banana", "Apple", "cherry", "date"}, "Mixed case (n=4)"),
new TestCase(new String[]{"cat", "Cat", "CAT", "cat", "Dog"}, "Mixed case with duplicates (n=5)"),
new TestCase(new String[]{"elephant", "giraffe", "hippopotamus", "rhinoceros", "zebra", "antelope"}, "Long strings (n=6)"),
new TestCase(new String[]{}, "Empty (n=0)"),
new TestCase(new String[]{"single"}, "Single element (n=1)"),
new TestCase(new String[]{"apple", "banana", "cherry", "date", "elderberry", "fig", "grape"}, "All lowercase (n=7)")
};
// Run test cases
for (int i = 0; i < testCases.length; i++) {
System.out.println("Test case " + (i + 1) + ": " + testCases[i].description);
String[] arr = testCases[i].arr.clone(); // Copy to preserve original
System.out.println("Input Array: " + sorter.toString(arr));
int swaps = sorter.selectionSort(arr);
System.out.println("Sorted Array: " + sorter.toString(arr));
System.out.println("Swaps: " + swaps + "\n");
}
}
}
Output
Running the main method produces:
Test case 1: Mixed case (n=4)
Input Array: [banana, Apple, cherry, date]
Sorted Array: [Apple, banana, cherry, date]
Swaps: 2
Test case 2: Mixed case with duplicates (n=5)
Input Array: [cat, Cat, CAT, cat, Dog]
Sorted Array: [CAT, Cat, Dog, cat, cat]
Swaps: 4
Test case 3: Long strings (n=6)
Input Array: [elephant, giraffe, hippopotamus, rhinoceros, zebra, antelope]
Sorted Array: [antelope, elephant, giraffe, hippopotamus, rhinoceros, zebra]
Swaps: 5
Test case 4: Empty (n=0)
Input Array: []
Sorted Array: []
Swaps: 0
Test case 5: Single element (n=1)
Input Array: [single]
Sorted Array: [single]
Swaps: 0
Test case 6: All lowercase (n=7)
Input Array: [apple, banana, cherry, date, elderberry, fig, grape]
Sorted Array: [apple, banana, cherry, date, elderberry, fig, grape]
Swaps: 0
Explanation:
- Test case 1: Mixed case strings, 2 swaps ("Apple" before "banana" due to case).
- Test case 2: Mixed case with duplicates, 4 swaps (uppercase "CAT" first).
- Test case 3: Long strings, 5 swaps to sort lexicographically.
- Test case 4: Empty array, 0 swaps.
- Test case 5: Single element, 0 swaps.
- Test case 6: Already sorted lowercase strings, 0 swaps.
How It Works
- selectionSort:
- Uses generics with
Comparable<T>to handleStringarrays. - Finds the lexicographically smallest string in each pass using
compareTo. - Swaps if needed, counts swaps, and builds the sorted array.
- Uses generics with
- toString: Formats array as a string, handling
Stringelements. - Example Trace (Test case 1):
- Pass 1: Find min="Apple" at index 1, swap with "banana": [Apple, banana, cherry, date] (1 swap).
- Pass 2: Find min="banana", no swap: [Apple, banana, cherry, date].
- Pass 3: Find min="cherry", no swap: [Apple, banana, cherry, date].
- Pass 4: Find min="date", no swap. Total swaps: 2.
- Main Method: Tests mixed case, duplicates, long strings, empty, single element, and lowercase arrays.
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| selectionSort | O(n²) | O(1) |
| toString | O(n) | O(n) |
Note:
- n is the array length.
- Time complexity: O(n²) for selectionSort (n passes, up to n comparisons each); O(n) for toString. String comparisons depend on string length, but this is not included in standard analysis.
- Space complexity: O(1) for selectionSort (in-place); O(n) for toString (string builder).
- Selection Sort performs O(n²) comparisons, with swaps O(n) in the worst case.
✅ Tip: Use generics with
Comparableto extend Selection Sort to strings, leveragingcompareTofor lexicographical ordering. Test with mixed cases to understand case-sensitive sorting.
⚠ Warning: Java’s
compareTois case-sensitive (uppercase before lowercase). For case-insensitive sorting, usecompareToIgnoreCase. Handle empty arrays to avoid index errors.