sorting_race/services/sorters/
merge.rs1use crate::models::traits::{Sorter, StepResult, Telemetry, Markers};
4use std::any::Any;
5
6#[derive(Debug, Clone)]
7struct MergeFrame {
8 left: usize,
9 mid: usize,
10 right: usize,
11 state: MergeState,
12 temp_left_idx: usize,
13 temp_right_idx: usize,
14 output_idx: usize,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18enum MergeState {
19 Split,
20 Merge,
21}
22
23#[derive(Debug)]
25pub struct MergeSort {
26 data: Vec<i32>,
27 temp_buffer: Vec<i32>,
28 stack: Vec<MergeFrame>,
29 comparisons: u64,
30 moves: u64,
31 complete: bool,
32 memory_usage: usize,
33}
34
35impl MergeSort {
36 pub fn new() -> Self {
38 Self {
39 data: Vec::new(),
40 temp_buffer: Vec::new(),
41 stack: Vec::new(),
42 comparisons: 0,
43 moves: 0,
44 complete: false,
45 memory_usage: 0,
46 }
47 }
48
49 fn merge(&mut self, frame: &mut MergeFrame, budget: &mut usize) -> bool {
50 let mid = frame.mid;
51 let right = frame.right;
52
53 if frame.temp_left_idx == frame.left {
55 for i in frame.left..=right {
56 self.temp_buffer[i] = self.data[i];
57 }
58 }
59
60 while *budget > 0 && frame.output_idx <= right {
61 if frame.temp_left_idx > mid {
62 self.data[frame.output_idx] = self.temp_buffer[frame.temp_right_idx];
64 self.moves += 1;
65 frame.temp_right_idx += 1;
66 } else if frame.temp_right_idx > right {
67 self.data[frame.output_idx] = self.temp_buffer[frame.temp_left_idx];
69 self.moves += 1;
70 frame.temp_left_idx += 1;
71 } else {
72 *budget -= 1;
74 self.comparisons += 1;
75
76 if self.temp_buffer[frame.temp_left_idx] <= self.temp_buffer[frame.temp_right_idx] {
77 self.data[frame.output_idx] = self.temp_buffer[frame.temp_left_idx];
78 frame.temp_left_idx += 1;
79 } else {
80 self.data[frame.output_idx] = self.temp_buffer[frame.temp_right_idx];
81 frame.temp_right_idx += 1;
82 }
83 self.moves += 1;
84 }
85
86 frame.output_idx += 1;
87 }
88
89 frame.output_idx > right }
91}
92
93impl Default for MergeSort {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl Sorter for MergeSort {
100 fn step(&mut self, budget: usize) -> StepResult {
101 if self.complete || self.data.len() <= 1 {
102 return StepResult {
103 comparisons_used: 0,
104 moves_made: 0,
105 continued: false,
106 };
107 }
108
109 let initial_comparisons = self.comparisons;
110 let initial_moves = self.moves;
111 let mut remaining_budget = budget;
112
113 while remaining_budget > 0 && !self.stack.is_empty() {
114 let mut frame = self.stack.pop().unwrap();
115
116 match frame.state {
117 MergeState::Split => {
118 if frame.left < frame.right {
119 let mid = (frame.left + frame.right) / 2;
120
121 self.stack.push(MergeFrame {
123 left: frame.left,
124 mid,
125 right: frame.right,
126 state: MergeState::Merge,
127 temp_left_idx: frame.left,
128 temp_right_idx: mid + 1,
129 output_idx: frame.left,
130 });
131
132 self.stack.push(MergeFrame {
134 left: mid + 1,
135 mid: mid + 1,
136 right: frame.right,
137 state: MergeState::Split,
138 temp_left_idx: 0,
139 temp_right_idx: 0,
140 output_idx: 0,
141 });
142
143 self.stack.push(MergeFrame {
145 left: frame.left,
146 mid: frame.left,
147 right: mid,
148 state: MergeState::Split,
149 temp_left_idx: 0,
150 temp_right_idx: 0,
151 output_idx: 0,
152 });
153 }
154 }
155 MergeState::Merge => {
156 let finished = self.merge(&mut frame, &mut remaining_budget);
157
158 if !finished {
159 self.stack.push(frame);
161 break;
162 }
163 }
164 }
165 }
166
167 if self.stack.is_empty() {
168 self.complete = true;
169 }
170
171 StepResult {
172 comparisons_used: (self.comparisons - initial_comparisons) as usize,
173 moves_made: (self.moves - initial_moves) as usize,
174 continued: !self.complete,
175 }
176 }
177
178 fn is_complete(&self) -> bool {
179 self.complete
180 }
181
182 fn get_telemetry(&self) -> Telemetry {
183 let mut markers = Markers::default();
184
185 if let Some(frame) = self.stack.last()
186 && frame.state == MergeState::Merge {
187 markers.merge_runs.push((frame.left, frame.right));
188
189 if frame.temp_left_idx <= frame.mid {
191 markers.cursors.push(frame.temp_left_idx);
192 }
193 if frame.temp_right_idx <= frame.right {
194 markers.cursors.push(frame.temp_right_idx);
195 }
196 if frame.output_idx <= frame.right {
197 markers.cursors.push(frame.output_idx);
198 }
199 }
200
201 Telemetry {
202 total_comparisons: self.comparisons,
203 total_moves: self.moves,
204 memory_current: self.memory_usage,
205 memory_peak: self.memory_usage, highlights: markers.cursors.clone(),
207 markers,
208 status_text: if self.complete {
209 "Completed".to_string()
210 } else if let Some(frame) = self.stack.last() {
211 match frame.state {
212 MergeState::Split => format!("Splitting range [{}, {}]", frame.left, frame.right),
213 MergeState::Merge => format!("Merging range [{}, {}]", frame.left, frame.right),
214 }
215 } else {
216 "Processing".to_string()
217 },
218 progress_hint: if self.data.len() <= 1 {
219 1.0
220 } else {
221 let progress = 1.0 - (self.stack.len() as f32 / (self.data.len() as f32).log2().max(1.0));
222 if progress.is_finite() { progress.min(1.0).max(0.0) } else { 0.0 }
223 },
224 }
225 }
226
227 fn reset(&mut self, data: Vec<i32>) {
228 self.data = data;
229 self.temp_buffer = vec![0; self.data.len()];
230 self.stack.clear();
231 self.comparisons = 0;
232 self.moves = 0;
233 self.complete = self.data.len() <= 1;
234
235 self.memory_usage = self.temp_buffer.len() * std::mem::size_of::<i32>();
237
238 if !self.complete {
239 self.stack.push(MergeFrame {
240 left: 0,
241 mid: 0,
242 right: self.data.len() - 1,
243 state: MergeState::Split,
244 temp_left_idx: 0,
245 temp_right_idx: 0,
246 output_idx: 0,
247 });
248
249 self.memory_usage += self.stack.capacity() * std::mem::size_of::<MergeFrame>();
250 }
251 }
252
253 fn name(&self) -> &str {
254 "Merge Sort"
255 }
256
257 fn get_array(&self) -> &[i32] {
258 &self.data
259 }
260
261 fn get_memory_usage(&self) -> usize {
262 self.data.len() * std::mem::size_of::<i32>() + self.memory_usage
264 }
265
266 fn as_any(&self) -> &dyn Any {
267 self
268 }
269
270 fn as_any_mut(&mut self) -> &mut dyn Any {
271 self
272 }
273}