sorting_race/services/sorters/
shell.rs1use crate::models::traits::{Sorter, StepResult, Telemetry, Markers};
4use std::any::Any;
5
6#[derive(Debug)]
8pub struct ShellSort {
9 data: Vec<i32>,
10 gap: usize,
11 current_pos: usize,
12 insertion_pos: usize,
13 comparisons: u64,
14 moves: u64,
15 complete: bool,
16 in_insertion: bool,
17}
18
19impl ShellSort {
20 pub fn new() -> Self {
22 Self {
23 data: Vec::new(),
24 gap: 0,
25 current_pos: 0,
26 insertion_pos: 0,
27 comparisons: 0,
28 moves: 0,
29 complete: false,
30 in_insertion: false,
31 }
32 }
33
34 fn generate_initial_gap(n: usize) -> usize {
36 let mut gap = 1;
37 while gap < n / 3 {
38 gap = gap * 3 + 1;
39 }
40 gap
41 }
42
43 fn next_gap(current_gap: usize) -> usize {
44 (current_gap - 1) / 3
45 }
46}
47
48impl Default for ShellSort {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl Sorter for ShellSort {
55 fn step(&mut self, budget: usize) -> StepResult {
56 if self.complete || self.data.len() <= 1 {
57 return StepResult {
58 comparisons_used: 0,
59 moves_made: 0,
60 continued: false,
61 };
62 }
63
64 let initial_comparisons = self.comparisons;
65 let initial_moves = self.moves;
66 let mut remaining_budget = budget;
67
68 while remaining_budget > 0 && !self.complete {
69 if self.gap == 0 {
70 self.complete = true;
71 break;
72 }
73
74 if !self.in_insertion {
75 if self.current_pos >= self.data.len() {
77 self.gap = Self::next_gap(self.gap);
79 self.current_pos = self.gap;
80 continue;
81 }
82
83 self.insertion_pos = self.current_pos;
84 self.in_insertion = true;
85 }
86
87 if self.in_insertion {
88 if self.insertion_pos >= self.gap {
89 remaining_budget -= 1;
91 self.comparisons += 1;
92
93 if self.data[self.insertion_pos] < self.data[self.insertion_pos - self.gap] {
94 self.data.swap(self.insertion_pos, self.insertion_pos - self.gap);
96 self.moves += 1;
97 self.insertion_pos -= self.gap;
98 } else {
99 self.in_insertion = false;
101 self.current_pos += 1;
102 }
103 } else {
104 self.in_insertion = false;
106 self.current_pos += 1;
107 }
108 }
109 }
110
111 StepResult {
112 comparisons_used: (self.comparisons - initial_comparisons) as usize,
113 moves_made: (self.moves - initial_moves) as usize,
114 continued: !self.complete,
115 }
116 }
117
118 fn is_complete(&self) -> bool {
119 self.complete
120 }
121
122 fn get_telemetry(&self) -> Telemetry {
123 let mut markers = Markers::default();
124
125 if !self.complete {
126 markers.gap = Some(self.gap);
127
128 if self.in_insertion {
129 markers.cursors.push(self.insertion_pos);
130 if self.insertion_pos >= self.gap {
131 markers.cursors.push(self.insertion_pos - self.gap);
132 }
133 } else if self.current_pos < self.data.len() {
134 markers.cursors.push(self.current_pos);
135 }
136 }
137
138 Telemetry {
139 total_comparisons: self.comparisons,
140 total_moves: self.moves,
141 memory_current: self.get_memory_usage(),
142 memory_peak: self.get_memory_usage(),
143 highlights: markers.cursors.clone(),
144 markers,
145 status_text: if self.complete {
146 "Completed".to_string()
147 } else if self.in_insertion {
148 format!("Gap {}, inserting at position {}", self.gap, self.insertion_pos)
149 } else {
150 format!("Gap {}, processing position {}", self.gap, self.current_pos)
151 },
152 progress_hint: if self.data.len() <= 1 {
153 1.0
154 } else {
155 let initial_gap = Self::generate_initial_gap(self.data.len()) as f32;
157 let current_gap = self.gap as f32;
158 if initial_gap == 0.0 {
159 1.0
160 } else {
161 let progress = 1.0 - (current_gap / initial_gap);
162 if progress.is_finite() { progress.min(1.0).max(0.0) } else { 0.0 }
163 }
164 },
165 }
166 }
167
168 fn reset(&mut self, data: Vec<i32>) {
169 self.data = data;
170 self.gap = Self::generate_initial_gap(self.data.len());
171 self.current_pos = self.gap;
172 self.insertion_pos = 0;
173 self.comparisons = 0;
174 self.moves = 0;
175 self.complete = self.data.len() <= 1;
176 self.in_insertion = false;
177 }
178
179 fn name(&self) -> &str {
180 "Shell Sort"
181 }
182
183 fn get_array(&self) -> &[i32] {
184 &self.data
185 }
186
187 fn get_memory_usage(&self) -> usize {
188 self.data.len() * std::mem::size_of::<i32>()
190 }
191
192 fn as_any(&self) -> &dyn Any {
193 self
194 }
195
196 fn as_any_mut(&mut self) -> &mut dyn Any {
197 self
198 }
199}