Implement merge sort that counts inversions

This commit is contained in:
Felix Martin 2020-11-16 21:12:09 -05:00
parent 60dfe69601
commit d845ce64a4
2 changed files with 71 additions and 48 deletions

View File

@ -1,57 +1,32 @@
use std::clone::Clone; mod merge_sort;
use std::cmp::PartialOrd; use crate::merge_sort::merge_sort_inversions;
use std::marker::Copy; use std::fs::File;
use std::io;
use std::io::{BufRead, BufReader, Error, ErrorKind};
use std::vec::Vec; use std::vec::Vec;
fn merge<T: Clone + PartialOrd + Copy>(a: Vec<T>, b: Vec<T>) -> Vec<T> { fn read_to_vector(path: &str) -> Result<Vec<i64>, io::Error> {
let mut r = vec![]; let file = File::open(path)?;
let mut i = 0; let br = BufReader::new(file);
let mut j = 0; let mut v = Vec::new();
for line in br.lines() {
while i < a.len() && j < b.len() { let line = line?;
if a[i] < b[j] { let n = line
r.push(a[i]); .trim()
i += 1; .parse()
} else { .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
r.push(b[j]); v.push(n);
j += 1;
}
} }
Ok(v)
while i < a.len() {
r.push(a[i]);
i += 1;
}
while j < b.len() {
r.push(b[j]);
j += 1;
}
return r;
} }
fn merge_sort<T: Clone + PartialOrd + Copy>(v: Vec<T>) -> Vec<T> { fn c1a2() {
if v.len() <= 1 { let vec = read_to_vector("data/week_2_assignment_2.txt").unwrap();
return v; let (_sorted, inversions) = merge_sort_inversions(vec);
} // println!("{:?}", sorted.len());
let i = v.len() / 2; println!("course 1 assignment 2: {:?}", inversions);
let a = merge_sort((&v[..i]).to_vec());
let b = merge_sort((&v[i..]).to_vec());
let r = merge(a, b);
return r;
}
fn mult_bin(a: i64, b: i64) -> i64 {
return a * b;
} }
fn main() { fn main() {
println!("Hello, world!"); c1a2();
let l = vec![4, 2, 1, 3];
let l = merge_sort(l);
println!("{:?}", l);
let r = mult_bin(42, 21);
println!("{:?}", r);
} }

48
src/merge_sort.rs Normal file
View File

@ -0,0 +1,48 @@
use std::clone::Clone;
use std::cmp::PartialOrd;
fn merge_count_inversions<T: Clone + PartialOrd + Copy + std::fmt::Debug>(
a: Vec<T>,
b: Vec<T>,
) -> (Vec<T>, usize) {
let mut r = vec![];
let mut i = 0;
let mut j = 0;
let mut inversions = 0;
while i < a.len() && j < b.len() {
if a[i] < b[j] {
r.push(a[i]);
i += 1;
} else {
r.push(b[j]);
j += 1;
inversions += a.len() - i;
}
}
while i < a.len() {
r.push(a[i]);
i += 1;
}
while j < b.len() {
r.push(b[j]);
j += 1;
}
return (r, inversions);
}
pub fn merge_sort_inversions<T: Clone + PartialOrd + Copy + std::fmt::Debug>(
v: Vec<T>,
) -> (Vec<T>, usize) {
if v.len() <= 1 {
return (v, 0);
}
let i = v.len() / 2;
let (a, n) = merge_sort_inversions((&v[..i]).to_vec());
let (b, m) = merge_sort_inversions((&v[i..]).to_vec());
let (r, p) = merge_count_inversions(a, b);
return (r, n + m + p);
}