Skip to content

Commit 3443cf2

Browse files
Merge pull request #398 from Pasan11504/feature/shell-sort
Add ShellSort implementation in Java
2 parents c20bb06 + b206bfc commit 3443cf2

1 file changed

Lines changed: 173 additions & 0 deletions

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* Algorithm: Shell Sort
3+
* Description: Advanced insertion sort that uses gap sequences for improved performance
4+
* Time Complexity: O(n^3/2) worst case, O(n log n) average case (depends on gap sequence)
5+
* Space Complexity: O(1) - in-place sorting algorithm
6+
*
7+
* @author Pasan Sulakshana Rathnayake
8+
* @version 1.0
9+
* @since 2025-10-04
10+
*/
11+
12+
import java.util.*;
13+
14+
public class ShellSort {
15+
16+
/**
17+
* Sorts an array using shell sort algorithm with Knuth's gap sequence.
18+
*
19+
* @param arr the array to be sorted
20+
* @throws IllegalArgumentException if array is null
21+
*/
22+
public static void shellSort(int[] arr) {
23+
if (arr == null) {
24+
throw new IllegalArgumentException("Array cannot be null");
25+
}
26+
27+
if (arr.length <= 1) {
28+
return; // Already sorted
29+
}
30+
31+
int n = arr.length;
32+
33+
// Start with Knuth's gap sequence: h = 3h + 1
34+
// This gives us gaps like: 1, 4, 13, 40, 121, 364, ...
35+
int gap = 1;
36+
while (gap < n / 3) {
37+
gap = 3 * gap + 1;
38+
}
39+
40+
// Perform shell sort with decreasing gaps
41+
while (gap >= 1) {
42+
// Perform insertion sort for elements at gap distance
43+
for (int i = gap; i < n; i++) {
44+
int temp = arr[i];
45+
int j;
46+
47+
// Shift elements that are greater than temp
48+
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
49+
arr[j] = arr[j - gap];
50+
}
51+
52+
// Place temp in its correct position
53+
arr[j] = temp;
54+
}
55+
56+
// Reduce gap for next iteration
57+
gap = gap / 3;
58+
}
59+
}
60+
61+
/**
62+
* Alternative shell sort implementation using Shell's original gap sequence.
63+
* This version uses gaps: n/2, n/4, n/8, ..., 1
64+
*
65+
* @param arr the array to be sorted
66+
* @throws IllegalArgumentException if array is null
67+
*/
68+
public static void shellSortOriginal(int[] arr) {
69+
if (arr == null) {
70+
throw new IllegalArgumentException("Array cannot be null");
71+
}
72+
73+
if (arr.length <= 1) {
74+
return;
75+
}
76+
77+
int n = arr.length;
78+
79+
// Start with gap = n/2 and reduce by half each time
80+
for (int gap = n / 2; gap > 0; gap /= 2) {
81+
// Perform insertion sort for elements at gap distance
82+
for (int i = gap; i < n; i++) {
83+
int temp = arr[i];
84+
int j;
85+
86+
// Shift elements that are greater than temp
87+
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
88+
arr[j] = arr[j - gap];
89+
}
90+
91+
// Place temp in its correct position
92+
arr[j] = temp;
93+
}
94+
}
95+
}
96+
97+
98+
99+
/**
100+
* Test the shell sort implementation.
101+
*/
102+
public static void main(String[] args) {
103+
System.out.println("SHELL SORT ALGORITHM TESTING");
104+
System.out.println("=============================");
105+
106+
// Test case 1: Regular array
107+
int[] test1 = {64, 34, 25, 12, 22, 11, 90, 88, 76, 50, 42};
108+
System.out.println("\n1. Regular array test:");
109+
System.out.println("Original: " + Arrays.toString(test1));
110+
shellSort(test1.clone());
111+
System.out.println("Sorted: " + Arrays.toString(test1));
112+
shellSort(test1);
113+
System.out.println("Verified: " + Arrays.toString(test1));
114+
115+
// Test case 2: Already sorted
116+
int[] test2 = {1, 2, 3, 4, 5, 6, 7, 8};
117+
System.out.println("\n2. Already sorted array:");
118+
System.out.println("Original: " + Arrays.toString(test2));
119+
shellSort(test2);
120+
System.out.println("Sorted: " + Arrays.toString(test2));
121+
122+
// Test case 3: Reverse sorted
123+
int[] test3 = {9, 8, 7, 6, 5, 4, 3, 2, 1};
124+
System.out.println("\n3. Reverse sorted array:");
125+
System.out.println("Original: " + Arrays.toString(test3));
126+
shellSort(test3);
127+
System.out.println("Sorted: " + Arrays.toString(test3));
128+
129+
// Test case 4: Array with duplicates
130+
int[] test4 = {5, 2, 8, 2, 9, 1, 5, 5, 2};
131+
System.out.println("\n4. Array with duplicates:");
132+
System.out.println("Original: " + Arrays.toString(test4));
133+
shellSort(test4);
134+
System.out.println("Sorted: " + Arrays.toString(test4));
135+
136+
// Test case 5: Single element
137+
int[] test5 = {42};
138+
shellSort(test5);
139+
assert test5[0] == 42;
140+
141+
// Test case 6: Empty array
142+
int[] test6 = {};
143+
shellSort(test6);
144+
assert test6.length == 0;
145+
146+
// Test case 7: Two elements
147+
int[] test7 = {9, 3};
148+
System.out.println("\n5. Two elements:");
149+
System.out.println("Original: " + Arrays.toString(test7));
150+
shellSort(test7);
151+
System.out.println("Sorted: " + Arrays.toString(test7));
152+
153+
// Test case 8: Compare gap sequences
154+
int[] testOriginal = {64, 34, 25, 12, 22, 11, 90, 88, 76, 50, 42};
155+
int[] testKnuth = testOriginal.clone();
156+
157+
System.out.println("\n6. Comparing gap sequences:");
158+
System.out.println("Original array: " + Arrays.toString(testOriginal));
159+
160+
shellSortOriginal(testOriginal);
161+
System.out.println("Shell's gaps: " + Arrays.toString(testOriginal));
162+
163+
shellSort(testKnuth);
164+
System.out.println("Knuth's gaps: " + Arrays.toString(testKnuth));
165+
166+
System.out.println("\nAll test cases passed!");
167+
System.out.println("Shell Sort advantages:");
168+
System.out.println(" - Better than insertion sort for larger arrays");
169+
System.out.println(" - In-place sorting (O(1) space complexity)");
170+
System.out.println(" - Adaptive - performs well on partially sorted data");
171+
System.out.println(" - Gap sequence affects performance significantly");
172+
}
173+
}

0 commit comments

Comments
 (0)