Skip to content

Commit 4c3cddc

Browse files
committed
misc.rs -> order.rs, with mergesort
1 parent b7b756b commit 4c3cddc

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@ Rather than try to persuade you with words, this repository aims to show by exam
4545

4646
- [Basic graph representations](src/graph/mod.rs): adjacency lists, disjoint set union
4747
- [Elementary graph algorithms](src/graph/util.rs): minimum spanning tree, Euler path, Dijkstra's algorithm, DFS iteration
48-
- [Network flows](src/graph/flow.rs): Dinic's blocking flow, Hopcroft-Karp bipartite matching, min cost max flow
4948
- [Connected components](src/graph/connectivity.rs): 2-edge-, 2-vertex- and strongly connected components, bridges, articulation points, topological sort, 2-SAT
50-
- [Associative range query](src/range_query): known colloquially as *segtrees*, as well as Mo's query square root decomposition
49+
- [Network flows](src/graph/flow.rs): Dinic's blocking flow, Hopcroft-Karp bipartite matching, min cost max flow
5150
- [Number theory](src/math/mod.rs): canonical solution to Bezout's identity, Miller's primality test
52-
- [Arithmetic](src/math/num.rs): rational and complex numbers, linear algebra, safe modular arithmetic
5351
- [FFT](src/math/fft.rs): fast Fourier transform, number theoretic transform, convolution
52+
- [Arithmetic](src/math/num.rs): rational and complex numbers, linear algebra, safe modular arithmetic
53+
- [Ordering algorithms](src/order.rs): binary search, mergesort, coordinate compression, amortized convex hull trick
54+
- [Associative range query](src/range_query): static and dynamic ARQ trees (a.k.a. segtrees), Mo's query square root decomposition
5455
- [Scanner](src/scanner.rs): utility for reading input data ergonomically
5556
- [String processing](src/string_proc.rs): Knuth-Morris-Pratt and Aho-Corasick string matching, suffix array, Manacher's linear-time palindrome search
56-
- [Miscellaneous algorithms](src/misc.rs): slice binary search, coordinate compression, convex hull trick with sqrt decomposition
57+

src/graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! All methods will panic if given an out-of-bounds element index.
66
pub mod connectivity;
77
pub mod flow;
8-
mod util;
8+
pub mod util;
99

1010
/// Represents a union of disjoint sets. Each set's elements are arranged in a
1111
/// tree, whose root is the set's representative.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Algorithms Cookbook in Rust.
22
pub mod graph;
33
pub mod math;
4-
pub mod misc;
4+
pub mod order;
55
pub mod range_query;
66
pub mod scanner;
77
pub mod string_proc;

src/misc.rs renamed to src/order.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@ pub fn asserting_cmp<T: PartialOrd>(a: &T, b: &T) -> std::cmp::Ordering {
55
a.partial_cmp(b).expect("Comparing incomparable elements")
66
}
77

8-
/// Assuming slice is totally ordered and sorted, returns the minimum i for which
8+
/// Assuming slice is sorted and totally ordered, returns the minimum i for which
99
/// slice[i] >= key, or slice.len() if no such i exists
1010
pub fn slice_lower_bound<T: PartialOrd>(slice: &[T], key: &T) -> usize {
1111
slice
1212
.binary_search_by(|x| asserting_cmp(x, key).then(std::cmp::Ordering::Greater))
1313
.unwrap_err()
1414
}
1515

16-
/// Assuming slice is totally ordered and sorted, returns the minimum i for which
16+
/// Assuming slice is sorted and totally ordered, returns the minimum i for which
1717
/// slice[i] > key, or slice.len() if no such i exists
1818
pub fn slice_upper_bound<T: PartialOrd>(slice: &[T], key: &T) -> usize {
1919
slice
2020
.binary_search_by(|x| asserting_cmp(x, key).then(std::cmp::Ordering::Less))
2121
.unwrap_err()
2222
}
2323

24-
/// Merge two sorted collections into one
24+
/// Merge two sorted and totally ordered collections into one
2525
pub fn merge_sorted<T: PartialOrd>(
2626
i1: impl IntoIterator<Item = T>,
2727
i2: impl IntoIterator<Item = T>,
@@ -35,6 +35,16 @@ pub fn merge_sorted<T: PartialOrd>(
3535
merged
3636
}
3737

38+
/// A stable sort
39+
pub fn merge_sort<T: Ord>(mut v: Vec<T>) -> Vec<T> {
40+
if v.len() < 2 {
41+
v
42+
} else {
43+
let v2 = v.split_off(v.len() / 2);
44+
merge_sorted(merge_sort(v), merge_sort(v2))
45+
}
46+
}
47+
3848
/// A simple data structure for coordinate compression
3949
pub struct SparseIndex {
4050
coords: Vec<i64>,
@@ -58,9 +68,9 @@ impl SparseIndex {
5868
/// Represents a maximum (upper envelope) of a collection of linear functions of a variable,
5969
/// evaluated using the convex hull trick with square root decomposition.
6070
pub struct PiecewiseLinearFn {
71+
recent_lines: Vec<(f64, f64)>,
6172
sorted_lines: Vec<(f64, f64)>,
6273
intersections: Vec<f64>,
63-
recent_lines: Vec<(f64, f64)>,
6474
merge_threshold: usize,
6575
}
6676

@@ -70,9 +80,9 @@ impl PiecewiseLinearFn {
7080
/// any threshold less than N (e.g., 0) yields O(N + Q log N) time complexity.
7181
pub fn with_merge_threshold(merge_threshold: usize) -> Self {
7282
Self {
83+
recent_lines: vec![],
7384
sorted_lines: vec![],
7485
intersections: vec![],
75-
recent_lines: vec![],
7686
merge_threshold,
7787
}
7888
}
@@ -155,6 +165,15 @@ mod test {
155165
assert_eq!(merge_sorted(vals1, vals2), vals_merged);
156166
}
157167

168+
#[test]
169+
fn test_merge_sort() {
170+
let unsorted = vec![8, -5, 1, 4, -3, 4];
171+
let sorted = vec![-5, -3, 1, 4, 4, 8];
172+
173+
assert_eq!(merge_sort(unsorted), sorted);
174+
assert_eq!(merge_sort(sorted.clone()), sorted);
175+
}
176+
158177
#[test]
159178
fn test_coord_compress() {
160179
let mut coords = vec![16, 99, 45, 18];

0 commit comments

Comments
 (0)