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 ("\n 1. 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 ("\n 2. 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 ("\n 3. 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 ("\n 4. 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 ("\n 5. 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 ("\n 6. 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 ("\n All 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