From f9fc7068fc03366a0f53f69e2e680fac1a7e9218 Mon Sep 17 00:00:00 2001 From: Wynd Date: Sat, 31 May 2025 16:44:44 +0300 Subject: [PATCH] Split the sorters in separated modules and added merge sort --- src/bubble.rs | 16 ++++++++ src/main.rs | 104 ++++++++++++++++++++------------------------------ src/merge.rs | 62 ++++++++++++++++++++++++++++++ src/quick.rs | 39 +++++++++++++++++++ 4 files changed, 159 insertions(+), 62 deletions(-) create mode 100644 src/bubble.rs create mode 100644 src/merge.rs create mode 100644 src/quick.rs diff --git a/src/bubble.rs b/src/bubble.rs new file mode 100644 index 0000000..e97e41f --- /dev/null +++ b/src/bubble.rs @@ -0,0 +1,16 @@ +use crate::{SortMessage, SortVisualizer}; + +pub fn sort(vis: &mut SortVisualizer) { + let n = vis.arr.len(); + + for i in 0..n { + for j in 0..n - i - 1 { + if vis.arr[j] > vis.arr[j + 1] { + vis.arr.swap(j, j + 1); + vis.tx.send(SortMessage::Data(vis.arr.clone())).unwrap(); + } + } + } + + vis.tx.send(SortMessage::Done).unwrap(); +} diff --git a/src/main.rs b/src/main.rs index c58dcbf..fa045e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,22 +13,32 @@ use fltk::{ use fltk_theme::{color_themes, ColorTheme}; use rand::Rng; -const SIZE: u32 = 50; +mod bubble; +mod merge; +mod quick; + +const SIZE: u32 = 100; const MAX_VALUE: f64 = 100.0; type Sorter = fn(&mut SortVisualizer); -#[derive(Debug)] -struct SortVisualizer { - arr: Vec, - chart: Chart, - sorter: Sorter, - tx: Sender>, - rx: Receiver>, +enum SortMessage { + Data(Vec), + Done, } -impl SortVisualizer { - fn new(id: usize, arr: Vec, sorter: Sorter) -> Self { +#[derive(Debug)] +struct SortVisualizer<'a> { + arr: Vec, + name: &'a str, + chart: Chart, + sorter: Sorter, + tx: Sender, + rx: Receiver, +} + +impl<'a> SortVisualizer<'a> { + fn new(id: usize, name: &'a str, arr: Vec, sorter: Sorter) -> Self { let (tx, rx) = mpsc::channel(); let y = 300 * (id) as i32; @@ -37,9 +47,11 @@ impl SortVisualizer { chart.set_size(500, 250); chart.set_frame(FrameType::FlatBox); chart.set_bounds(0.0, MAX_VALUE); + chart.set_label(name); Self { arr, + name, chart, sorter, tx, @@ -57,54 +69,10 @@ impl SortVisualizer { self.chart.add(*i, "", Color::Cyan); } } -} -fn quick_sort(vis: &mut SortVisualizer) { - let n = vis.arr.len(); - let low = 0; - let high = n - 1; - - quick_sorting(vis, low, high); -} - -fn quick_sorting(vis: &mut SortVisualizer, low: usize, high: usize) { - if low < high { - let pivot = partition(vis, low, high); - if pivot > 0 { - quick_sorting(vis, low, pivot - 1); - } - quick_sorting(vis, pivot + 1, high); - } -} - -fn partition(vis: &mut SortVisualizer, low: usize, high: usize) -> usize { - let pivot = high; - let mut i = low as isize - 1; - - for j in low..high { - if vis.arr[j] < vis.arr[pivot] { - i += 1; - vis.arr.swap(i as usize, j); - vis.tx.send(vis.arr.clone()).unwrap(); - } - } - - vis.arr.swap((i + 1) as usize, pivot); - vis.tx.send(vis.arr.clone()).unwrap(); - - (i + 1) as usize -} - -fn bubble_sort(vis: &mut SortVisualizer) { - let n = vis.arr.len(); - - for i in 0..n { - for j in 0..n - i - 1 { - if vis.arr[j] > vis.arr[j + 1] { - vis.arr.swap(j, j + 1); - vis.tx.send(vis.arr.clone()).unwrap(); - } - } + fn complete(&mut self, rank: u8) { + self.chart + .set_label(&format!("{} - Complete - Rank #{}", self.name, rank)); } } @@ -113,7 +81,11 @@ fn main() { .map(|_| rand::rng().random_range(1.0..MAX_VALUE)) .collect(); - let sorts = [quick_sort, bubble_sort]; + let sorts: [(&str, Sorter); 3] = [ + ("Quick Sort", quick::sort), + ("Bubble Sort", bubble::sort), + ("Merge Sort", merge::sort), + ]; let app = app::App::default().with_scheme(app::Scheme::Gtk); let theme = ColorTheme::new(&color_themes::fleet::DARK1); @@ -127,7 +99,7 @@ fn main() { let mut visualizers = vec![]; for (i, sort) in sorts.into_iter().enumerate() { - visualizers.push(SortVisualizer::new(i, arr.clone(), sort)); + visualizers.push(SortVisualizer::new(i, sort.0, arr.clone(), sort.1)); } thread::scope(|scope| { @@ -141,11 +113,19 @@ fn main() { window.end(); window.show(); + let mut rank = 0; + app::add_idle3(move |_| { for sorter in &mut visualizers { - let arr = sorter.rx.try_recv(); - if let Ok(arr) = arr { - sorter.draw(arr); + let data = sorter.rx.try_recv(); + if let Ok(data) = data { + match data { + SortMessage::Data(arr) => sorter.draw(arr), + SortMessage::Done => { + rank += 1; + sorter.complete(rank); + } + } } } diff --git a/src/merge.rs b/src/merge.rs new file mode 100644 index 0000000..6896505 --- /dev/null +++ b/src/merge.rs @@ -0,0 +1,62 @@ +use std::sync::mpsc::Sender; + +use crate::{SortMessage, SortVisualizer}; + +pub fn sort(vis: &mut SortVisualizer) { + merge_sort(&vis.tx, &mut vis.arr.clone(), &vis.arr); + + vis.tx.send(SortMessage::Done).unwrap(); +} + +fn merge_sort(tx: &Sender, og_arr: &mut [f64], arr: &[f64]) -> Vec { + if arr.len() < 2 { + arr.to_vec() + } + else { + let n = arr.len() / 2; + + let left = merge_sort(tx, og_arr, &arr[0..n]); + let right = merge_sort(tx, og_arr, &arr[n..]); + + merge(tx, og_arr, &left, &right) + } +} + +fn merge(tx: &Sender, og_arr: &mut [f64], left: &[f64], right: &[f64]) -> Vec { + let mut i = 0; + let mut j = 0; + let mut merged: Vec = vec![]; + + while i < left.len() && j < right.len() { + if left[i] < right[j] { + merged.push(left[i]); + i += 1; + } + else { + merged.push(right[j]); + j += 1; + } + } + + if i < left.len() { + while i < left.len() { + merged.push(left[i]); + i += 1; + } + } + + if j < right.len() { + while j < right.len() { + merged.push(right[j]); + j += 1; + } + } + + for (i, val) in merged.iter().enumerate() { + og_arr[i] = *val; + + tx.send(SortMessage::Data(og_arr.to_vec().clone())).unwrap(); + } + + merged +} diff --git a/src/quick.rs b/src/quick.rs new file mode 100644 index 0000000..5436376 --- /dev/null +++ b/src/quick.rs @@ -0,0 +1,39 @@ +use crate::{SortMessage, SortVisualizer}; + +pub fn sort(vis: &mut SortVisualizer) { + let n = vis.arr.len(); + let low = 0; + let high = n - 1; + + quick_sort(vis, low, high); + + vis.tx.send(SortMessage::Done).unwrap(); +} + +fn quick_sort(vis: &mut SortVisualizer, low: usize, high: usize) { + if low < high { + let pivot = partition(vis, low, high); + if pivot > 0 { + quick_sort(vis, low, pivot - 1); + } + quick_sort(vis, pivot + 1, high); + } +} + +fn partition(vis: &mut SortVisualizer, low: usize, high: usize) -> usize { + let pivot = high; + let mut i = low as isize - 1; + + for j in low..high { + if vis.arr[j] < vis.arr[pivot] { + i += 1; + vis.arr.swap(i as usize, j); + vis.tx.send(SortMessage::Data(vis.arr.clone())).unwrap(); + } + } + + vis.arr.swap((i + 1) as usize, pivot); + vis.tx.send(SortMessage::Data(vis.arr.clone())).unwrap(); + + (i + 1) as usize +}