Split the sorters in separated modules and added merge sort

master
Wynd 2025-05-31 16:44:44 +03:00
parent 5dbaef1dec
commit f9fc7068fc
4 changed files with 159 additions and 62 deletions

16
src/bubble.rs 100644
View File

@ -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();
}

View File

@ -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<f64>,
chart: Chart,
sorter: Sorter,
tx: Sender<Vec<f64>>,
rx: Receiver<Vec<f64>>,
enum SortMessage {
Data(Vec<f64>),
Done,
}
impl SortVisualizer {
fn new(id: usize, arr: Vec<f64>, sorter: Sorter) -> Self {
#[derive(Debug)]
struct SortVisualizer<'a> {
arr: Vec<f64>,
name: &'a str,
chart: Chart,
sorter: Sorter,
tx: Sender<SortMessage>,
rx: Receiver<SortMessage>,
}
impl<'a> SortVisualizer<'a> {
fn new(id: usize, name: &'a str, arr: Vec<f64>, 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);
}
}
}
}

62
src/merge.rs 100644
View File

@ -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<SortMessage>, og_arr: &mut [f64], arr: &[f64]) -> Vec<f64> {
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<SortMessage>, og_arr: &mut [f64], left: &[f64], right: &[f64]) -> Vec<f64> {
let mut i = 0;
let mut j = 0;
let mut merged: Vec<f64> = 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
}

39
src/quick.rs 100644
View File

@ -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
}