├── res ├── strings │ ├── abra.txt │ ├── shellsST.txt │ ├── words3.txt │ └── shells.txt ├── common │ ├── tobe.txt │ └── tinyUF.txt ├── kmp_dfa.png ├── algs4_cover.png ├── graph │ ├── tinyCG.txt │ ├── tinyG.txt │ ├── jobsPC.txt │ ├── tinyDAG.txt │ ├── tinyEWDAG.txt │ ├── rates.txt │ ├── tinyEWD.txt │ ├── routes.txt │ ├── tinyEWDn.txt │ ├── tinyEWG.txt │ ├── tinyEWDnc.txt │ ├── tinyDG.txt │ └── jobs.txt └── trending-day-2021-08-21.png ├── src ├── other │ ├── mod.rs │ └── min_free.rs ├── search │ ├── mod.rs │ └── binary.rs ├── tree │ ├── mod.rs │ └── binary │ │ ├── builder │ │ ├── mod.rs │ │ ├── level.rs │ │ └── tournament.rs │ │ ├── mod.rs │ │ ├── tree.rs │ │ └── avl.rs ├── math │ ├── mod.rs │ ├── mysqrt.rs │ └── sparse_vector.rs ├── ll │ ├── mod.rs │ ├── reverse.rs │ ├── kth2tail.rs │ ├── cycle.rs │ └── linked_list.rs ├── sort │ ├── mod.rs │ ├── quick.rs │ ├── floyd.rs │ ├── shell.rs │ ├── bubble.rs │ ├── tree_selection.rs │ ├── selection.rs │ └── insert.rs ├── graph │ ├── util │ │ ├── mod.rs │ │ ├── symbol_graph.rs │ │ ├── paths.rs │ │ └── parser.rs │ ├── directed │ │ ├── mod.rs │ │ ├── transitive_closure.rs │ │ ├── search.rs │ │ ├── scc.rs │ │ ├── digraph.rs │ │ ├── sort.rs │ │ └── order.rs │ ├── shortest │ │ ├── mod.rs │ │ ├── directed_edge.rs │ │ ├── ew_digraph.rs │ │ ├── arbitrage.rs │ │ ├── cpm.rs │ │ ├── acyclic_sp.rs │ │ └── dijkstra_sp.rs │ ├── undirected │ │ ├── dfs2.rs │ │ ├── dfs.rs │ │ ├── mod.rs │ │ ├── cc.rs │ │ ├── cycle.rs │ │ ├── bipartite.rs │ │ └── graph.rs │ ├── mst │ │ ├── edge.rs │ │ ├── mod.rs │ │ ├── ew_graph.rs │ │ ├── kruskal_mst.rs │ │ ├── lazy_prim_mst.rs │ │ └── prim_mst.rs │ └── mod.rs ├── strings │ ├── palindrome.rs │ ├── mod.rs │ ├── count.rs │ ├── brute_force.rs │ ├── kmp.rs │ ├── alphabet.rs │ ├── quick3.rs │ └── lsd.rs ├── common │ ├── mod.rs │ ├── binary_tree.rs │ ├── drop.rs │ ├── top_m.rs │ ├── stack.rs │ ├── util.rs │ ├── queue.rs │ └── max_heap.rs ├── lib.rs └── dp │ ├── mod.rs │ ├── coin.rs │ └── fib.rs ├── .gitignore ├── plotters-doc-data └── 0.png ├── cpp ├── fib.h └── fib.c ├── tests ├── test_rb_tree.rs ├── test_search.rs ├── test_math.rs ├── playground.rs ├── test_alphabet.rs ├── test_sparse_vec.rs ├── test_graph_mst.rs ├── test_dp.rs ├── test_common_heap.rs ├── test_sort.rs ├── test_linked_list.rs ├── test_bst_tree.rs ├── test_rb_tree2.rs └── test_common.rs ├── benches ├── math.rs ├── common.rs ├── dp.rs └── strings.rs ├── Makefile ├── Cargo.toml ├── examples └── quadratic.rs ├── LICENSE ├── CheatSheet.md ├── todos.md └── README.md /res/strings/abra.txt: -------------------------------------------------------------------------------- 1 | ABRACADABRA! -------------------------------------------------------------------------------- /src/other/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod min_free; 2 | -------------------------------------------------------------------------------- /src/search/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod binary; 2 | -------------------------------------------------------------------------------- /src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod binary; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | res/graph/movies.txt -------------------------------------------------------------------------------- /res/common/tobe.txt: -------------------------------------------------------------------------------- 1 | to be or not to - be - - that - - - is 2 | -------------------------------------------------------------------------------- /src/math/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mysqrt; 2 | pub mod sparse_vector; 3 | -------------------------------------------------------------------------------- /res/strings/shellsST.txt: -------------------------------------------------------------------------------- 1 | she sells sea shells by the sea shore 2 | -------------------------------------------------------------------------------- /res/kmp_dfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douchuan/algorithm/HEAD/res/kmp_dfa.png -------------------------------------------------------------------------------- /res/algs4_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douchuan/algorithm/HEAD/res/algs4_cover.png -------------------------------------------------------------------------------- /plotters-doc-data/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douchuan/algorithm/HEAD/plotters-doc-data/0.png -------------------------------------------------------------------------------- /res/graph/tinyCG.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 8 3 | 0 5 4 | 2 4 5 | 2 3 6 | 1 2 7 | 0 1 8 | 3 4 9 | 3 5 10 | 0 2 -------------------------------------------------------------------------------- /src/tree/binary/builder/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod level; 2 | pub mod tournament; 3 | 4 | pub struct TreeBuilder; 5 | -------------------------------------------------------------------------------- /res/trending-day-2021-08-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douchuan/algorithm/HEAD/res/trending-day-2021-08-21.png -------------------------------------------------------------------------------- /res/common/tinyUF.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 4 3 3 | 3 8 4 | 6 5 5 | 9 4 6 | 2 1 7 | 8 9 8 | 5 0 9 | 7 2 10 | 6 1 11 | 1 0 12 | 6 7 13 | -------------------------------------------------------------------------------- /src/ll/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cycle; 2 | pub mod kth2tail; 3 | pub mod linked_list; 4 | pub mod reverse; 5 | 6 | pub use linked_list::{LinkedList, Node}; 7 | -------------------------------------------------------------------------------- /res/graph/tinyG.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 13 3 | 0 5 4 | 4 3 5 | 0 1 6 | 9 12 7 | 6 4 8 | 5 4 9 | 0 2 10 | 11 12 11 | 9 10 12 | 0 6 13 | 7 8 14 | 9 11 15 | 5 3 16 | -------------------------------------------------------------------------------- /cpp/fib.h: -------------------------------------------------------------------------------- 1 | #ifndef FIB_H 2 | #define FIB_H 3 | 4 | #include 5 | 6 | size_t fib_cache_result_c(size_t n); 7 | size_t fib_classic_iteration_for_c(size_t n); 8 | 9 | #endif -------------------------------------------------------------------------------- /src/sort/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bubble; 2 | pub mod floyd; 3 | pub mod insert; 4 | pub mod merge; 5 | pub mod quick; 6 | pub mod selection; 7 | pub mod shell; 8 | pub mod tree_selection; 9 | -------------------------------------------------------------------------------- /res/graph/jobsPC.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 41.0 3 1 7 9 3 | 51.0 1 2 4 | 50.0 0 5 | 36.0 0 6 | 38.0 0 7 | 45.0 0 8 | 21.0 2 3 8 9 | 32.0 2 3 8 10 | 32.0 1 2 11 | 29.0 2 4 6 12 | -------------------------------------------------------------------------------- /src/graph/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod parser; 2 | mod paths; 3 | mod symbol_graph; 4 | 5 | pub use paths::{BreadthFirstPaths, DepthFirstPaths, Paths}; 6 | pub use symbol_graph::SymbolGraph; 7 | -------------------------------------------------------------------------------- /res/strings/words3.txt: -------------------------------------------------------------------------------- 1 | bed bug dad yes zoo 2 | now for tip ilk dim 3 | tag jot sob nob sky 4 | hut men egg few jay 5 | owl joy rap gig wee 6 | was wad fee tap tar 7 | dug jam all bad yet 8 | -------------------------------------------------------------------------------- /res/graph/tinyDAG.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 15 3 | 2 3 4 | 0 6 5 | 0 1 6 | 2 0 7 | 11 12 8 | 9 12 9 | 9 10 10 | 9 11 11 | 3 5 12 | 8 7 13 | 5 4 14 | 0 5 15 | 6 4 16 | 6 9 17 | 7 6 18 | 19 | -------------------------------------------------------------------------------- /res/graph/tinyEWDAG.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 13 3 | 5 4 0.35 4 | 4 7 0.37 5 | 5 7 0.28 6 | 5 1 0.32 7 | 4 0 0.38 8 | 0 2 0.26 9 | 3 7 0.39 10 | 1 3 0.29 11 | 7 2 0.34 12 | 6 2 0.40 13 | 3 6 0.52 14 | 6 0 0.58 15 | 6 4 0.93 16 | -------------------------------------------------------------------------------- /res/graph/rates.txt: -------------------------------------------------------------------------------- 1 | 5 2 | USD 1 0.741 0.657 1.061 1.005 3 | EUR 1.349 1 0.888 1.433 1.366 4 | GBP 1.521 1.126 1 1.614 1.538 5 | CHF 0.942 0.698 0.619 1 0.953 6 | CAD 0.995 0.732 0.650 1.049 1 7 | 8 | -------------------------------------------------------------------------------- /res/graph/tinyEWD.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 15 3 | 4 5 0.35 4 | 5 4 0.35 5 | 4 7 0.37 6 | 5 7 0.28 7 | 7 5 0.28 8 | 5 1 0.32 9 | 0 4 0.38 10 | 0 2 0.26 11 | 7 3 0.39 12 | 1 3 0.29 13 | 2 7 0.34 14 | 6 2 0.40 15 | 3 6 0.52 16 | 6 0 0.58 17 | 6 4 0.93 18 | -------------------------------------------------------------------------------- /res/graph/routes.txt: -------------------------------------------------------------------------------- 1 | JFK MCO 2 | ORD DEN 3 | ORD HOU 4 | DFW PHX 5 | JFK ATL 6 | ORD DFW 7 | ORD PHX 8 | ATL HOU 9 | DEN PHX 10 | PHX LAX 11 | JFK ORD 12 | DEN LAS 13 | DFW HOU 14 | ORD ATL 15 | LAS LAX 16 | ATL MCO 17 | HOU MCO 18 | LAS PHX 19 | -------------------------------------------------------------------------------- /src/tree/binary/mod.rs: -------------------------------------------------------------------------------- 1 | pub use node::Node; 2 | pub use node::NodeQuery; 3 | pub use tree::Tree; 4 | 5 | pub mod avl; 6 | pub mod bst; 7 | pub mod builder; 8 | mod node; 9 | pub mod rb; 10 | pub mod rb2; 11 | pub mod traverse; 12 | mod tree; 13 | -------------------------------------------------------------------------------- /res/graph/tinyEWDn.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 15 3 | 4 5 0.35 4 | 5 4 0.35 5 | 4 7 0.37 6 | 5 7 0.28 7 | 7 5 0.28 8 | 5 1 0.32 9 | 0 4 0.38 10 | 0 2 0.26 11 | 7 3 0.39 12 | 1 3 0.29 13 | 2 7 0.34 14 | 6 2 -1.20 15 | 3 6 0.52 16 | 6 0 -1.40 17 | 6 4 -1.25 18 | -------------------------------------------------------------------------------- /res/graph/tinyEWG.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 16 3 | 4 5 0.35 4 | 4 7 0.37 5 | 5 7 0.28 6 | 0 7 0.16 7 | 1 5 0.32 8 | 0 4 0.38 9 | 2 3 0.17 10 | 1 7 0.19 11 | 0 2 0.26 12 | 1 2 0.36 13 | 1 3 0.29 14 | 2 7 0.34 15 | 6 2 0.40 16 | 3 6 0.52 17 | 6 0 0.58 18 | 6 4 0.93 19 | -------------------------------------------------------------------------------- /res/graph/tinyEWDnc.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 15 3 | 4 5 0.35 4 | 5 4 -0.66 5 | 4 7 0.37 6 | 5 7 0.28 7 | 7 5 0.28 8 | 5 1 0.32 9 | 0 4 0.38 10 | 0 2 0.26 11 | 7 3 0.39 12 | 1 3 0.29 13 | 2 7 0.34 14 | 6 2 0.40 15 | 3 6 0.52 16 | 6 0 0.58 17 | 6 4 0.93 18 | -------------------------------------------------------------------------------- /res/graph/tinyDG.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 22 3 | 4 2 4 | 2 3 5 | 3 2 6 | 6 0 7 | 0 1 8 | 2 0 9 | 11 12 10 | 12 9 11 | 9 10 12 | 9 11 13 | 7 9 14 | 10 12 15 | 11 4 16 | 4 3 17 | 3 5 18 | 6 8 19 | 8 6 20 | 5 4 21 | 0 5 22 | 6 4 23 | 6 9 24 | 7 6 25 | -------------------------------------------------------------------------------- /src/strings/palindrome.rs: -------------------------------------------------------------------------------- 1 | pub fn is_palindrome(word: &str) -> bool { 2 | let chars: Vec<_> = word.chars().collect(); 3 | do_check(&chars) 4 | } 5 | 6 | fn do_check(items: &[char]) -> bool { 7 | match items { 8 | [first, middle @ .., last] => first == last && do_check(middle), 9 | [] | [_] => true, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/common/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod binary_tree; 2 | pub mod drop; 3 | pub mod max_heap; 4 | mod priority_queue; 5 | mod queue; 6 | mod stack; 7 | mod top_m; 8 | mod uf; 9 | pub mod util; 10 | 11 | pub use priority_queue::{IndexPQ, PQ}; 12 | pub use queue::Queue; 13 | pub use stack::Stack; 14 | pub use top_m::TopM; 15 | pub use uf::{QuickFindUF, QuickUnionUF, WeightedQuickUnionUF, UF}; 16 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(iter_partition_in_place)] 2 | #![feature(stmt_expr_attributes)] 3 | #![feature(test)] 4 | extern crate test; 5 | 6 | #[macro_use] 7 | extern crate lazy_static; 8 | 9 | pub mod common; 10 | pub mod dp; 11 | pub mod graph; 12 | pub mod ll; 13 | pub mod math; 14 | pub mod other; 15 | pub mod search; 16 | pub mod sort; 17 | pub mod strings; 18 | pub mod tree; 19 | -------------------------------------------------------------------------------- /tests/test_rb_tree.rs: -------------------------------------------------------------------------------- 1 | use algo::tree::binary::Tree; 2 | 3 | #[test] 4 | fn rb_tree_height() { 5 | use algo::tree::binary::rb::RedBlackTree; 6 | let mut tree = Tree::default(); 7 | for v in 0..100 { 8 | tree.insert(v, v); 9 | } 10 | // 即使输入升序数列,rb tree仍然是平衡的 11 | // 证明:含有n个节点的红黑树,其高度不会超过 2 * lg(n + 1) 12 | assert!(tree.height() as f32 <= 2.0 * 100.0f32.log2()) 13 | } 14 | -------------------------------------------------------------------------------- /src/strings/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod alphabet; 2 | pub mod brute_force; 3 | mod count; 4 | mod kmp; 5 | pub mod lsd; 6 | pub mod msd; 7 | pub mod palindrome; 8 | pub mod quick3; 9 | mod tries; 10 | mod tst; 11 | 12 | pub use alphabet::Alphabet; 13 | pub use count::Count; 14 | pub use kmp::KMP; 15 | pub use lsd::LSD; 16 | pub use msd::MSD; 17 | pub use quick3::{Quick3String, Quick3Way}; 18 | pub use tries::TrieST; 19 | pub use tst::TST; 20 | -------------------------------------------------------------------------------- /res/strings/shells.txt: -------------------------------------------------------------------------------- 1 | she sells seashells by the sea shore 2 | the shells she sells are surely seashells 3 | she sells seashells by the sea shore 4 | the shells she sells are surely seashells 5 | she sells seashells by the sea shore 6 | the shells she sells are surely seashells 7 | she sells seashells by the sea shore 8 | the shells she sells are surely seashells 9 | she sells seashells by the sea shore 10 | the shells she sells are surely seashells -------------------------------------------------------------------------------- /src/sort/quick.rs: -------------------------------------------------------------------------------- 1 | //! 快速排序 2 | //! 3 | //! C. A. R. Hoare在1960年提出。 4 | //! 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分, 5 | //! 其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按 6 | //! 此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行, 7 | //! 以此达到整个数据变成有序序列 8 | 9 | pub fn sort(a: &mut [T]) 10 | where 11 | T: Ord, 12 | { 13 | let len = a.len(); 14 | if len > 0 { 15 | let (l, _, r) = a.select_nth_unstable(len / 2); 16 | sort(l); 17 | sort(r) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /res/graph/jobs.txt: -------------------------------------------------------------------------------- 1 | Algorithms/Theoretical CS/Databases/Scientific Computing 2 | Introduction to CS/Advanced Programming/Algorithms 3 | Advanced Programming/Scientific Computing 4 | Scientific Computing/Computational Biology 5 | Theoretical CS/Computational Biology/Artificial Intelligence 6 | Linear Algebra/Theoretical CS 7 | Calculus/Linear Algebra 8 | Artificial Intelligence/Neural Networks/Robotics/Machine Learning 9 | Machine Learning/Neural Networks 10 | -------------------------------------------------------------------------------- /tests/test_search.rs: -------------------------------------------------------------------------------- 1 | use algo::search; 2 | 3 | #[test] 4 | fn binary_search() { 5 | //empty array 6 | assert_eq!(search::binary::search(&[], 0), None); 7 | 8 | let xs = vec![1, 2, 3, 4, 5, 6, 7, 8]; 9 | for (v, p) in vec![ 10 | (1, Some(0)), 11 | (4, Some(3)), 12 | (8, Some(7)), 13 | (100, None), 14 | (-1, None), 15 | ] { 16 | assert_eq!(search::binary::search(&xs, v), p); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/common/binary_tree.rs: -------------------------------------------------------------------------------- 1 | //! Complete binary tree in array 2 | //! 3 | //! Initial sequence number begin with 0 4 | 5 | /// left child of i 6 | #[inline(always)] 7 | pub fn left(i: usize) -> usize { 8 | (i << 1) + 1 9 | } 10 | 11 | /// right child of i 12 | #[inline(always)] 13 | pub fn right(i: usize) -> usize { 14 | (i + 1) << 1 15 | } 16 | 17 | /// parent of i 18 | #[inline(always)] 19 | pub fn parent(i: usize) -> usize { 20 | ((i + 1) >> 1) - 1 21 | } 22 | -------------------------------------------------------------------------------- /benches/math.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | use algo::math; 5 | use test::Bencher; 6 | 7 | static X: f32 = 999999999.0f32; 8 | 9 | #[bench] 10 | fn sqrt_std(b: &mut Bencher) { 11 | b.iter(|| X.sqrt()); 12 | } 13 | 14 | #[bench] 15 | fn sqrt_binary_search(b: &mut Bencher) { 16 | b.iter(|| math::mysqrt::sqrt_binary_search(X)); 17 | } 18 | 19 | #[bench] 20 | fn sqrt_newton(b: &mut Bencher) { 21 | b.iter(|| math::mysqrt::sqrt_newton(X)); 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_math.rs: -------------------------------------------------------------------------------- 1 | use algo::math; 2 | 3 | #[test] 4 | fn sqrt() { 5 | // let epsilon = f64::EPSILON; 6 | let epsilon = 0.01; 7 | let valus: Vec = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; 8 | for v in valus { 9 | assert!((v.sqrt() - math::mysqrt::sqrt_binary_search(v)) <= epsilon); 10 | assert!((v.sqrt() - math::mysqrt::sqrt_newton(v)) <= epsilon); 11 | assert!((v.sqrt() - math::mysqrt::sqrt3(v)) <= epsilon); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/graph/directed/mod.rs: -------------------------------------------------------------------------------- 1 | //! DAG 2 | //! 3 | //! A directed acyclic graph (DAG) is a digraph with no directed cycles. 4 | 5 | mod cycle; 6 | mod digraph; 7 | mod order; 8 | mod scc; 9 | mod search; 10 | mod sort; 11 | mod transitive_closure; 12 | 13 | pub use digraph::Digraph; 14 | 15 | pub use cycle::{DirectedCycle, EdgeWeightedDirectedCycle}; 16 | pub use order::DepthFirstOrders; 17 | pub use scc::KosarajuSCC; 18 | pub use search::DirectedDFS; 19 | pub use sort::Topological; 20 | pub use transitive_closure::TransitiveClosure; 21 | -------------------------------------------------------------------------------- /src/dp/mod.rs: -------------------------------------------------------------------------------- 1 | //! dp: dynamic plan 2 | //! 3 | //! 解题思路: 4 | //! 求解动态规划的核心问题是穷举。因为要求最值,肯定要把所有可行的答案穷举出来,然后在其中找最值 5 | //! 6 | //! 1. 动态规划的穷举有点特别,因为这类问题存在「重叠子问题」,如果暴力穷举的话效率会极其低下, 7 | //! 所以需要「备忘录」或者「DP table」来优化穷举过程,避免不必要的计算 8 | //! 9 | //! 2. 动态规划问题一定会具备「最优子结构」,才能通过子问题的最值得到原问题的最值 10 | //! 11 | //! 3. 虽然动态规划的核心思想就是穷举求最值,但是问题可以千变万化,穷举所有可行解其实并不是一件 12 | //! 容易的事,只有列出正确的「状态转移方程」才能正确地穷举 13 | //! 14 | //! 以上提到的重叠子问题、最优子结构、状态转移方程就是动态规划三要素 15 | //! 16 | //! 但凡遇到需要递归的问题,最好都画出递归树,这对你分析算法的复杂度,寻找算法低效的原因都有巨大帮助 17 | 18 | pub mod coin; 19 | pub mod fib; 20 | -------------------------------------------------------------------------------- /src/search/binary.rs: -------------------------------------------------------------------------------- 1 | //! 二分查找 2 | 3 | use std::cmp::Ordering; 4 | 5 | pub fn search(arr: &[K], k: K) -> Option 6 | where 7 | K: Ord, 8 | { 9 | let mut left = 0; 10 | let mut right = arr.len(); 11 | 12 | while left < right { 13 | let mid = (left + right) >> 1; 14 | match arr[mid].cmp(&k) { 15 | Ordering::Less => left = mid + 1, 16 | Ordering::Equal => return Some(mid), 17 | Ordering::Greater => right = mid, 18 | } 19 | } 20 | 21 | None 22 | } 23 | -------------------------------------------------------------------------------- /src/ll/reverse.rs: -------------------------------------------------------------------------------- 1 | //! 反转链表 2 | //! 3 | //! 输入一个链表,反转链表后,输出新链表的表头。 4 | 5 | use crate::ll::Node; 6 | use std::ptr::NonNull; 7 | 8 | // 递归,先找到tail,然后从后向前修正指针 9 | pub(crate) unsafe fn do_reverse(node: Option>>) -> Option>> { 10 | node.and_then(|mut node| match node.as_mut().next.take() { 11 | None => Some(node), // new_head, origin tail 12 | Some(mut next) => { 13 | let new_head = do_reverse(Some(next)); 14 | next.as_mut().next = Some(node); 15 | new_head 16 | } 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/sort/floyd.rs: -------------------------------------------------------------------------------- 1 | //! 堆排序 2 | /// Robert. W. Floyd 给出了一个堆排序的高效实现。 3 | /// 思路是构建一个最大堆,接下来,将最大的元素和数组末尾的元素交换, 4 | /// 这样最大元素就存储到了排序后的正确位置。然后将堆的大小减一,执 5 | /// 行 Heapify 恢复堆的性质。我们重复这一过程,直到堆中仅剩下一个元素。 6 | /// 这一算法是原地排序的,无需使用额外的空间来存储结果 7 | /// 8 | /// 就地排序,小 -> 大 9 | use crate::common::max_heap; 10 | 11 | pub fn sort(a: &mut [T]) 12 | where 13 | T: Ord, 14 | { 15 | // 构建最大堆 16 | max_heap::build_heap(a); 17 | 18 | let mut i = a.len(); 19 | while i > 1 { 20 | i -= 1; 21 | a.swap(0, i); 22 | max_heap::heapify(&mut a[0..i], 0); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/strings/count.rs: -------------------------------------------------------------------------------- 1 | use crate::strings::Alphabet; 2 | 3 | /// computing the frequency of occurrence of each 4 | /// character over a given alphabet 5 | pub struct Count; 6 | 7 | impl Count { 8 | pub fn compute(alphabet: &Alphabet, s: &str) -> Vec { 9 | let mut count = vec![0; alphabet.radix()]; 10 | for c in s.chars() { 11 | if let Some(&i) = alphabet.to_index(c) { 12 | if i >= 0 { 13 | count[i as usize] += 1; 14 | } 15 | } 16 | } 17 | count 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cpp/fib.c: -------------------------------------------------------------------------------- 1 | #include "fib.h" 2 | 3 | int MEMO[100] = { 0 }; 4 | 5 | size_t fib_cache_result_c(size_t n) 6 | { 7 | if (0 == n) return 0; 8 | if (1 == n || 2 == n) return 1; 9 | if (0 != MEMO[n]) return MEMO[n]; 10 | MEMO[n] = fib_cache_result_c(n - 1) + fib_cache_result_c(n - 2); 11 | return MEMO[n]; 12 | } 13 | 14 | size_t fib_classic_iteration_for_c(size_t n) 15 | { 16 | if (0 == n) return 0; 17 | if (1 == n || 2 == n) return 1; 18 | size_t prev = 1, curr = 1; 19 | for (size_t i = 3; i <= n; i++) { 20 | size_t sum = prev + curr; 21 | prev = curr; 22 | curr = sum; 23 | } 24 | return curr; 25 | } 26 | -------------------------------------------------------------------------------- /src/sort/shell.rs: -------------------------------------------------------------------------------- 1 | //! 希尔排序 (Shell's Sort) 2 | //! 3 | //! 又称“缩小增量排序”(Diminishing Increment Sort), 4 | //! 是直接插入排序算法的一种更高效的改进版本。希尔排序是 5 | //! 非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。 6 | 7 | pub fn sort(a: &mut [T]) 8 | where 9 | T: Ord + Copy, 10 | { 11 | let len = a.len(); 12 | let mut gap = len; 13 | while gap > 1 { 14 | gap /= 2; 15 | 16 | for i in gap..len { 17 | let insert_v = a[i]; 18 | let mut j = i; 19 | while j >= gap && insert_v < a[j - gap] { 20 | a[j] = a[j - gap]; 21 | j -= gap; 22 | } 23 | a[j] = insert_v; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/playground.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn vec_random_access() { 3 | // Allocate vector big enough for 4 elements. 4 | let size = 4; 5 | let mut x: Vec = Vec::with_capacity(size); 6 | let x_ptr = x.as_mut_ptr(); 7 | 8 | unsafe { 9 | for v in 0..4 { 10 | *x_ptr.add(v) = v; 11 | } 12 | x.set_len(size); 13 | } 14 | assert_eq!(&*x, &[0, 1, 2, 3]); 15 | 16 | // 扩充 17 | x.reserve(4); 18 | let x_ptr = x.as_mut_ptr(); 19 | unsafe { 20 | for v in 4..8 { 21 | *x_ptr.add(v) = v; 22 | } 23 | x.set_len(8) 24 | } 25 | assert_eq!(&*x, &[0, 1, 2, 3, 4, 5, 6, 7]); 26 | } 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CARGO = RUST_BACKTRACE=1 rustup run nightly cargo 2 | TEST = $(CARGO) test 3 | BENCH = $(CARGO) bench 4 | BUILD = $(CARGO) build 5 | 6 | build: 7 | @$(BUILD) 8 | 9 | clippy: 10 | @$(CARGO) clippy 11 | 12 | test: 13 | #@$(TEST) -- --nocapture 14 | @$(TEST) $(ARGS) 15 | 16 | bench: 17 | @$(BENCH) 18 | 19 | eg_quadratic: 20 | @$(CARGO) run --example quadratic 21 | 22 | doc: 23 | @$(CARGO) doc --open 24 | 25 | stats: 26 | @echo "codes: " 27 | @cloc . --exclude-dir=target 28 | @echo 29 | @echo 30 | @echo "commits: " 31 | @git log --oneline | wc -l 32 | @echo "first commit: " 33 | @git rev-list --max-parents=0 HEAD | git --no-pager log --pretty=%cd --date=short --stdin 34 | @echo 35 | @echo 36 | @echo "disk:" 37 | @du -d 1 -h target -------------------------------------------------------------------------------- /src/sort/bubble.rs: -------------------------------------------------------------------------------- 1 | //! 冒泡排序(Bubble Sort) 2 | //! 3 | //! 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺 4 | //! 序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素 5 | //! 的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列 6 | //! 已经排序完成。 7 | //! 8 | //! 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的 9 | //! 顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会 10 | //! 上浮到顶端一样,故名“冒泡排序”。 11 | //! 12 | 13 | pub fn sort(a: &mut [T]) 14 | where 15 | T: Ord, 16 | { 17 | let len = a.len(); 18 | for i in 0..len.saturating_sub(1) { 19 | let mut swapped = false; 20 | 21 | for j in 0..(len - 1 - i) { 22 | if a[j] > a[j + 1] { 23 | a.swap(j, j + 1); 24 | swapped = true; 25 | } 26 | } 27 | 28 | if !swapped { 29 | break; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/sort/tree_selection.rs: -------------------------------------------------------------------------------- 1 | //! 算法新解, 刘新宇 2 | //! Version: 0.6180339887498949 3 | //! 8.4 本质改进 4 | //! 5 | //! 构建锦标赛树,复用比较结果,对Selection sort的性能做改进 6 | 7 | use crate::tree::binary::builder::tournament::{BuildTournamentTree, Minimal}; 8 | use crate::tree::binary::builder::TreeBuilder; 9 | use crate::tree::binary::Tree; 10 | 11 | /// 排序结果:大 -> 小 12 | /// 13 | /// 构建tree的时间复杂度 O(n) 14 | /// 每次pop的时间复杂度 O(log2(n)),所以弹出n个元素的的时间复杂度为 O(n * log2(n)) 15 | pub fn sort_desc(data: &[K]) -> Vec 16 | where 17 | K: Copy + std::cmp::Ord + Minimal, 18 | { 19 | let mut tree: Tree = TreeBuilder::build_tournament_tree(data); 20 | let mut r = Vec::with_capacity(data.len()); 21 | while let Some(v) = TreeBuilder::tournament_tree_pop(&mut tree) { 22 | r.push(v); 23 | } 24 | r 25 | } 26 | -------------------------------------------------------------------------------- /src/other/min_free.rs: -------------------------------------------------------------------------------- 1 | //! 最小可用ID 2 | //! 3 | //! 这道题目来自 Richard Bird 书中的第一章 [1]。 4 | //! 现代社会中,有很多服务依赖一种被称为ID的概念。 5 | //! 例如身份证就是一种ID,银行账户也是一种ID,电 6 | //! 话号码本质上也是一种ID。假设我们使用非负整数作 7 | //! 为某个系统的的ID,所有用户都由一个ID唯一确定。 8 | //! 任何时间,这个系统中有些ID处在使用中的状态,有些 9 | //! ID则可以用于分配给新用户。 10 | //! 现在的问题是,怎样才能找到最小的可分配ID呢? 11 | //! 12 | //! 例如下面的列表记录了当前正在被使用的ID: 13 | //! [18, 4, 8, 9, 16, 1, 14, 7, 19, 3, 0, 5, 2, 11, 6] 14 | //! 15 | //! [1] Richard Bird. “Pearls of functional algorithm design”. Cambridge University Press; 1 edition (November 1, 2010). ISBN-10: 0521513383 16 | 17 | //todo: improve me 18 | /// 时间复杂度 O(n^2) 19 | pub fn mfv1(a: &[usize]) -> usize { 20 | let mut v = 0; 21 | loop { 22 | if a.contains(&v) { 23 | v += 1; 24 | } else { 25 | return v; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "algorithm" 3 | version = "0.1.0" 4 | authors = ["Dou Chuan <1843657913@qq.com>"] 5 | edition = "2018" 6 | 7 | description = "This crate contains source code for the algorithms in the textbook Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne" 8 | repository = "https://github.com/douchuan/algorithm" 9 | readme = "README.md" 10 | categories = ["algorithms", "data-structures"] 11 | license = "MIT" 12 | 13 | [lib] 14 | name = "algo" 15 | path = "src/lib.rs" 16 | 17 | [features] 18 | instrument = [] 19 | 20 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 21 | 22 | [dependencies] 23 | lazy_static = "1.4.0" 24 | libc = "0.2" 25 | nom = "6.2.1" 26 | rand = "0.8.0" 27 | 28 | [dev-dependencies] 29 | approx = "0.5.0" 30 | plotters = "0.3.1" 31 | 32 | [build-dependencies] 33 | cc = "1.0" 34 | -------------------------------------------------------------------------------- /benches/common.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | use algo::common::{QuickUnionUF, WeightedQuickUnionUF, UF}; 5 | use std::str::FromStr; 6 | use test::Bencher; 7 | 8 | // const TINY_UF: &'static str = include_str!("../res/common/tinyUF.txt"); 9 | const MEDIUM_UF: &'static str = include_str!("../res/common/mediumUF.txt"); 10 | 11 | #[bench] 12 | fn weighted_quf(b: &mut Bencher) { 13 | b.iter(|| { 14 | let i = MEDIUM_UF; 15 | let _uf = WeightedQuickUnionUF::from_str(i).unwrap(); 16 | }); 17 | } 18 | 19 | #[bench] 20 | fn quf(b: &mut Bencher) { 21 | b.iter(|| { 22 | let i = MEDIUM_UF; 23 | let _uf = QuickUnionUF::from_str(i).unwrap(); 24 | }); 25 | } 26 | 27 | #[bench] 28 | fn uf(b: &mut Bencher) { 29 | b.iter(|| { 30 | let i = MEDIUM_UF; 31 | let _uf = UF::from_str(i).unwrap(); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /src/common/drop.rs: -------------------------------------------------------------------------------- 1 | //! Used by unit test to verify no memory leak. 2 | 3 | use std::sync::atomic::{AtomicUsize, Ordering}; 4 | 5 | // record how many Drop::drop called 6 | // tests run in concurrent, DROPS should be thread_local 7 | thread_local! { 8 | static DROPS: AtomicUsize = AtomicUsize::new(0); 9 | } 10 | 11 | pub struct Elem; 12 | // wrapper for DROPS 13 | pub struct Ctx; 14 | 15 | // drops counter +1 16 | impl Drop for Elem { 17 | fn drop(&mut self) { 18 | DROPS.with(|drops| drops.fetch_add(1, Ordering::SeqCst)); 19 | } 20 | } 21 | 22 | impl Ctx { 23 | /// count of Drop::drop called 24 | pub fn get(&self) -> usize { 25 | DROPS.with(|drops| drops.load(Ordering::SeqCst)) 26 | } 27 | } 28 | 29 | pub fn with(f: F) 30 | where 31 | F: FnOnce(Ctx), 32 | { 33 | DROPS.with(|drops| { 34 | // reset DROPS to 0 35 | drops.store(0, Ordering::SeqCst); 36 | f(Ctx) 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /src/common/top_m.rs: -------------------------------------------------------------------------------- 1 | use crate::common::PQ; 2 | 3 | /// Find the largest M integers. 4 | /// This implementation uses a MinPQ of size 5 | /// at most m + 1 to identify the M largest elements. 6 | pub struct TopM { 7 | pq: PQ, 8 | m: usize, 9 | } 10 | 11 | impl TopM { 12 | pub fn new(m: usize) -> Self { 13 | Self { 14 | pq: PQ::new_min_pq(m + 1), 15 | m, 16 | } 17 | } 18 | 19 | pub fn insert(&mut self, v: T) { 20 | self.pq.enqueue(v); 21 | // remove minimum if m+1 entries on the PQ 22 | if self.pq.len() > self.m { 23 | let _ = self.pq.dequeue(); 24 | } 25 | // top m entries are on the PQ 26 | } 27 | 28 | pub fn into_vec(mut self) -> Vec { 29 | let mut vec = Vec::with_capacity(self.m); 30 | while let Some(v) = self.pq.dequeue() { 31 | vec.push(v); 32 | } 33 | vec.reverse(); 34 | vec 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/quadratic.rs: -------------------------------------------------------------------------------- 1 | use plotters::prelude::*; 2 | fn main() -> Result<(), Box> { 3 | let root = BitMapBackend::new("plotters-doc-data/0.png", (640, 480)).into_drawing_area(); 4 | root.fill(&WHITE)?; 5 | let mut chart = ChartBuilder::on(&root) 6 | .caption("y=x^2", ("sans-serif", 50).into_font()) 7 | .margin(5) 8 | .x_label_area_size(30) 9 | .y_label_area_size(30) 10 | .build_cartesian_2d(-1f32..1f32, -0.1f32..1f32)?; 11 | 12 | chart.configure_mesh().draw()?; 13 | 14 | chart 15 | .draw_series(LineSeries::new( 16 | (-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)), 17 | &RED, 18 | ))? 19 | .label("y = x^2") 20 | .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); 21 | 22 | chart 23 | .configure_series_labels() 24 | .background_style(&WHITE.mix(0.8)) 25 | .border_style(&BLACK) 26 | .draw()?; 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /src/ll/kth2tail.rs: -------------------------------------------------------------------------------- 1 | //! 链表中倒数最后k个结点 2 | //! 3 | //! 输入一个链表,输出一个链表,该输出链表包含原链表中从倒数第k个结点至尾节点的全部节点。 4 | //! 如果该链表长度小于k,请返回一个长度为 0 的链表。 5 | 6 | use crate::ll::{LinkedList, Node}; 7 | use std::ptr::NonNull; 8 | 9 | pub fn find(l: &LinkedList, k: usize) -> Option>> { 10 | unsafe { do_find(l.head, k) } 11 | } 12 | 13 | /// 设链表的长度为 N。设置两个指针 P1 和 P2,先让 P1 移动 K 个节点, 14 | /// 则还有 N - K 个节点可以移动。此时让 P1 和 P2 同时移动,可以知道 15 | /// 当 P1 移动到链表结尾时,P2 移动到第 N - K 个节点处,该位置就是 16 | /// 倒数第 K 个节点。 17 | unsafe fn do_find(node: Option>>, mut k: usize) -> Option>> { 18 | let mut p1 = node; 19 | 20 | // p1 move k nodes 21 | while p1.is_some() && k > 0 { 22 | p1 = p1.unwrap().as_ref().next; 23 | k -= 1; 24 | } 25 | if k > 0 { 26 | return None; 27 | } 28 | 29 | // p2 移动到第 N - K 个节点处 30 | let mut p2 = node; 31 | while p1.is_some() { 32 | p1 = p1.unwrap().as_ref().next; 33 | p2 = p2.unwrap().as_ref().next; 34 | } 35 | 36 | p2 37 | } 38 | -------------------------------------------------------------------------------- /src/graph/directed/transitive_closure.rs: -------------------------------------------------------------------------------- 1 | //! Definition. 2 | //! The transitive closure of a digraph G is another digraph with 3 | //! the same set of vertices, but with an edge from v to w in the 4 | //! transitive closure if and only if w is reachable from v in G. 5 | //! 6 | //! By convention, every vertex is reachable from itself 7 | //! 8 | //! Compute transitive closure of a digraph and support 9 | //! reachability queries. 10 | 11 | use crate::graph::directed::DirectedDFS; 12 | use crate::graph::IGraph; 13 | 14 | pub struct TransitiveClosure { 15 | tc: Vec, // tc[v] = reachable from v 16 | } 17 | 18 | impl TransitiveClosure { 19 | /// Computes the transitive closure of the digraph 20 | pub fn new(graph: &dyn IGraph) -> Self { 21 | let mut tc = Vec::with_capacity(graph.V()); 22 | for v in 0..graph.V() { 23 | tc.push(DirectedDFS::new_single(graph, v)); 24 | } 25 | Self { tc } 26 | } 27 | 28 | /// Is there a directed path from vertex v to vertex w in the digraph? 29 | pub fn reachable(&self, v: usize, w: usize) -> bool { 30 | self.tc[v].marked(w) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 douchuan and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/math/mysqrt.rs: -------------------------------------------------------------------------------- 1 | pub fn sqrt_binary_search(x: f64) -> f64 { 2 | assert!(x >= 0.0); 3 | let mut low = 0.0; 4 | let mut up = x; 5 | let mut last = 0.0; 6 | loop { 7 | let mid = (low + up) / 2.0; 8 | if (mid - last).abs() <= f64::EPSILON { 9 | return mid; 10 | } 11 | 12 | if mid * mid > x { 13 | up = mid; 14 | } else { 15 | low = mid; 16 | } 17 | 18 | last = mid; 19 | } 20 | } 21 | 22 | pub fn sqrt_newton(x: f64) -> f64 { 23 | assert!(x >= 0.0); 24 | if x == 0.0 { 25 | return x; 26 | } 27 | if (x - 1.0).abs() <= f64::EPSILON { 28 | return 1.0; 29 | } 30 | let mut last = 0.0; 31 | let mut iter_v = x; 32 | loop { 33 | // iter_v = iter_v - (iter_v * iter_v - x) / (2.0 * iter_v); 34 | iter_v = (iter_v + x / iter_v) / 2.0; //由上式化简得来 35 | if (iter_v - last).abs() <= f64::EPSILON { 36 | return iter_v; 37 | } 38 | last = iter_v; 39 | } 40 | } 41 | 42 | // exp(log(x) * 0.5) 43 | pub fn sqrt3(x: f64) -> f64 { 44 | assert!(x >= 0.0); 45 | (x.ln() * 0.5f64).exp() 46 | } 47 | -------------------------------------------------------------------------------- /src/common/stack.rs: -------------------------------------------------------------------------------- 1 | //! A generic stack, implemented using a singly linked list. 2 | 3 | use crate::ll::linked_list::Iter; 4 | use crate::ll::LinkedList; 5 | 6 | pub struct Stack { 7 | ll: LinkedList, 8 | } 9 | 10 | impl Stack { 11 | /// Adds the item to this stack. 12 | pub fn push(&mut self, v: T) { 13 | self.ll.push_front(v); 14 | } 15 | 16 | /// Removes and returns the item most recently added to this stack. 17 | pub fn pop(&mut self) -> Option { 18 | self.ll.pop_front() 19 | } 20 | 21 | /// Returns (but does not remove) the item most recently added to this stack. 22 | pub fn peek(&self) -> Option<&T> { 23 | self.ll.first() 24 | } 25 | 26 | /// Returns an iterator to this stack that iterates through the items in LIFO order. 27 | pub fn iter(&self) -> Iter<'_, T> { 28 | self.ll.iter() 29 | } 30 | 31 | pub fn len(&self) -> usize { 32 | self.ll.len() 33 | } 34 | 35 | pub fn is_empty(&self) -> bool { 36 | self.ll.is_empty() 37 | } 38 | } 39 | 40 | impl Default for Stack { 41 | fn default() -> Self { 42 | let ll = LinkedList::default(); 43 | Self { ll } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/graph/directed/search.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::IGraph; 2 | 3 | pub struct DirectedDFS { 4 | marked: Vec, 5 | } 6 | 7 | impl DirectedDFS { 8 | /// find vertices in G that are reachable from s 9 | pub fn new_single(graph: &dyn IGraph, s: usize) -> Self { 10 | let mut dfs = Self { 11 | marked: vec![false; graph.V()], 12 | }; 13 | dfs.dfs(graph, s); 14 | dfs 15 | } 16 | 17 | /// find vertices in G that are reachable from sources 18 | pub fn new_multi(graph: &dyn IGraph, sources: &[usize]) -> Self { 19 | let mut dfs = Self { 20 | marked: vec![false; graph.V()], 21 | }; 22 | for &s in sources { 23 | if !dfs.marked[s] { 24 | dfs.dfs(graph, s); 25 | } 26 | } 27 | dfs 28 | } 29 | 30 | /// is v reachable? 31 | pub fn marked(&self, v: usize) -> bool { 32 | self.marked[v] 33 | } 34 | } 35 | 36 | impl DirectedDFS { 37 | fn dfs(&mut self, graph: &dyn IGraph, v: usize) { 38 | self.marked[v] = true; 39 | for &w in graph.adj(v) { 40 | if !self.marked[w] { 41 | self.dfs(graph, w); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/test_alphabet.rs: -------------------------------------------------------------------------------- 1 | use algo::strings::{alphabet, Alphabet, Count}; 2 | 3 | const ABRA: &'static str = include_str!("../res/strings/abra.txt"); 4 | const PI: &'static str = include_str!("../res/strings/pi.txt"); 5 | 6 | #[test] 7 | fn alphabet() { 8 | let s = "NowIsTheTimeForAllGoodMen"; 9 | let encoded = alphabet::BASE64.to_indices(s); 10 | let decoded = alphabet::BASE64.to_chars(&encoded); 11 | assert_eq!(s, decoded); 12 | 13 | let s = "AACGAACGGTTTACCCCG"; 14 | let encoded = alphabet::DNA.to_indices(s); 15 | let decoded = alphabet::DNA.to_chars(&encoded); 16 | assert_eq!(s, decoded); 17 | 18 | let s = "01234567890123456789"; 19 | let encoded = alphabet::DECIMAL.to_indices(s); 20 | let decoded = alphabet::DECIMAL.to_chars(&encoded); 21 | assert_eq!(s, decoded); 22 | } 23 | 24 | #[test] 25 | fn count() { 26 | use std::convert::TryFrom; 27 | 28 | let alphabet = Alphabet::try_from("ABCDR").unwrap(); 29 | let r = Count::compute(&alphabet, ABRA); 30 | assert_eq!(vec![5, 2, 1, 1, 2], r); 31 | 32 | let r = Count::compute(&alphabet::DECIMAL, PI); 33 | assert_eq!( 34 | vec![9999, 10137, 9908, 10026, 9971, 10026, 10028, 10025, 9978, 9902], 35 | r 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /src/sort/selection.rs: -------------------------------------------------------------------------------- 1 | //! 选择排序 2 | //! 3 | //! 从待排序的数据元素中选出最小(或最大)的一个元素, 4 | //! 然后放到已排序的序列的末尾,直到全部待排序的数据元素的个数为零。 5 | //! 6 | //! 选择排序是不稳定的排序方法 7 | 8 | pub fn sort(a: &mut [T]) 9 | where 10 | T: Ord, 11 | { 12 | let len = a.len(); 13 | for i in 0..len { 14 | let mut m = i; 15 | for j in (i + 1)..len { 16 | if a[m] > a[j] { 17 | m = j; 18 | } 19 | } 20 | 21 | a.swap(i, m); 22 | } 23 | } 24 | 25 | /// 鸡尾酒排序 (Cock-tail sort) 26 | /// 每次扫描可以同时查找最小值和最大值,将最小值放到开头, 27 | /// 最大值放到末尾 28 | pub fn sort_cocktail(a: &mut [T]) 29 | where 30 | T: Ord, 31 | { 32 | let n = a.len(); 33 | let semi_n = n / 2; 34 | // 注意右边界是semi_n 35 | // i在区间[0, semi_n)迭代的过程中, 36 | // max = n - 1 - i, 也逐渐向semi_n靠拢 37 | for i in 0..semi_n { 38 | let mut min = i; 39 | let mut max = n - 1 - i; 40 | if a[min] > a[max] { 41 | a.swap(min, max); 42 | } 43 | for j in (i + 1)..(n - 1 - i) { 44 | if a[min] > a[j] { 45 | min = j; 46 | } 47 | if a[max] < a[j] { 48 | max = j; 49 | } 50 | } 51 | 52 | a.swap(i, min); 53 | a.swap(n - 1 - i, max); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ll/cycle.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | //! 环形链表 3 | //! 4 | //! 给定一个链表,判断链表中是否有环。 5 | 6 | use crate::ll::{LinkedList, Node}; 7 | use std::ptr::NonNull; 8 | 9 | /// 使用双指针,一个指针每次移动一个节点,一个指针每次移动两个节点, 10 | /// 如果存在环,那么这两个指针一定会相遇。 11 | fn has_cycle(p: Option>>) -> bool { 12 | let mut fast = p; 13 | let mut slow = p; 14 | 15 | loop { 16 | unsafe { 17 | fast = fast.and_then(|v| v.as_ref().next.and_then(|next| next.as_ref().next)); 18 | slow = slow.and_then(|v| v.as_ref().next); 19 | } 20 | 21 | if fast.is_none() || fast == slow { 22 | break; 23 | } 24 | } 25 | 26 | fast.is_some() && fast == slow 27 | } 28 | 29 | #[test] 30 | fn t_has_cycle() { 31 | let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; 32 | let mut ll = LinkedList::default(); 33 | for v in data { 34 | ll.push_back(v); 35 | } 36 | 37 | //no cycle 38 | assert!(!has_cycle(ll.head)); 39 | 40 | //create cycle by hand 41 | let mut tail = ll.tail.unwrap(); 42 | unsafe { 43 | tail.as_mut().next = ll.head; 44 | } 45 | assert!(has_cycle(ll.head)); 46 | 47 | //eliminate cycle, otherwise LinkedList drop failed 48 | unsafe { 49 | tail.as_mut().next = None; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/graph/shortest/mod.rs: -------------------------------------------------------------------------------- 1 | mod acyclic_sp; 2 | mod arbitrage; 3 | mod bellman_ford_sp; 4 | mod cpm; 5 | mod dijkstra_sp; 6 | mod directed_edge; 7 | mod ew_digraph; 8 | 9 | pub use acyclic_sp::{AcyclicLP, AcyclicSP}; 10 | pub use arbitrage::Arbitrage; 11 | pub use bellman_ford_sp::BellmanFordSP; 12 | pub use cpm::CPM; 13 | pub use dijkstra_sp::{DijkstraAllPairsSP, DijkstraSP}; 14 | pub use directed_edge::DirectedEdge; 15 | pub use ew_digraph::EWDigraph; 16 | 17 | use crate::ll::linked_list::Iter; 18 | /// Edge weighted graph 19 | pub trait IEWDigraph { 20 | /// number of vertices 21 | #[allow(non_snake_case)] 22 | fn V(&self) -> usize; 23 | 24 | /// number of edges 25 | #[allow(non_snake_case)] 26 | fn E(&self) -> usize; 27 | 28 | /// Adds the directed edge e to this edge-weighted graph 29 | fn add_edge(&mut self, v: usize, w: usize, weight: f32); 30 | 31 | /// Returns the edges incident on vertex v 32 | fn adj(&self, v: usize) -> Iter<'_, DirectedEdge>; 33 | 34 | /// Returns all edges in this edge-weighted graph 35 | fn edges(&self) -> Vec; 36 | 37 | /// Returns the degree of vertex v 38 | fn out_degree(&self, v: usize) -> usize; 39 | 40 | /// Returns the number of directed edges incident to vertex 41 | fn in_degree(&self, v: usize) -> usize; 42 | } 43 | -------------------------------------------------------------------------------- /src/graph/shortest/directed_edge.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | #[derive(Default, Copy, Clone)] 4 | pub struct DirectedEdge { 5 | v: usize, 6 | w: usize, 7 | weight: f32, 8 | } 9 | 10 | impl DirectedEdge { 11 | pub fn new(v: usize, w: usize, weight: f32) -> Self { 12 | if weight.is_nan() { 13 | panic!("Weight is NaN"); 14 | } 15 | Self { v, w, weight } 16 | } 17 | 18 | pub fn weight(&self) -> f32 { 19 | self.weight 20 | } 21 | 22 | pub fn from(&self) -> usize { 23 | self.v 24 | } 25 | 26 | pub fn to(&self) -> usize { 27 | self.w 28 | } 29 | } 30 | 31 | impl PartialOrd for DirectedEdge { 32 | fn partial_cmp(&self, other: &Self) -> Option { 33 | self.weight.partial_cmp(&other.weight) 34 | } 35 | } 36 | 37 | impl PartialEq for DirectedEdge { 38 | fn eq(&self, other: &Self) -> bool { 39 | self.weight == other.weight 40 | } 41 | } 42 | 43 | impl Ord for DirectedEdge { 44 | fn cmp(&self, other: &Self) -> Ordering { 45 | self.weight.partial_cmp(&other.weight).unwrap() 46 | } 47 | } 48 | 49 | impl Eq for DirectedEdge {} 50 | 51 | impl ToString for DirectedEdge { 52 | fn to_string(&self) -> String { 53 | format!("{}->{} {:5.2}", self.v, self.w, self.weight) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/strings/brute_force.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | use crate::common; 3 | 4 | #[deprecated(note = "brute force search used by benchmark, use KMP in production")] 5 | pub fn search1(pat: &str, txt: &str) -> Option { 6 | let M = pat.len(); 7 | let N = txt.len(); 8 | for i in 0..=(N - M) { 9 | let mut j = 0; 10 | while j < M { 11 | let ic = common::util::byte_at(txt, i + j); 12 | let jc = common::util::byte_at(pat, j); 13 | if ic != jc { 14 | break; 15 | } 16 | j += 1; 17 | } 18 | if j == M { 19 | return Some(i); 20 | } 21 | } 22 | 23 | None 24 | } 25 | 26 | #[deprecated(note = "brute force search used by benchmark, use KMP in production")] 27 | pub fn search2(pat: &str, txt: &str) -> Option { 28 | let M = pat.len(); 29 | let N = txt.len(); 30 | let mut i = 0; 31 | let mut j = 0; 32 | while i < N && j < M { 33 | let ic = common::util::byte_at(txt, i); 34 | let jc = common::util::byte_at(pat, j); 35 | if ic == jc { 36 | j += 1; 37 | } else { 38 | i -= j; 39 | j = 0; 40 | } 41 | i += 1; 42 | } 43 | if j == M { 44 | Some(i - M) 45 | } else { 46 | None 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /benches/dp.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | use algo::dp; 5 | use test::Bencher; 6 | 7 | static MAKE_CHANGES_AMOUNT: i32 = 20; 8 | 9 | #[bench] 10 | fn make_changes_classic(b: &mut Bencher) { 11 | let coins = vec![1, 2, 5]; 12 | b.iter(|| dp::coin::make_change_classic(&coins, MAKE_CHANGES_AMOUNT)); 13 | } 14 | 15 | #[bench] 16 | fn make_changes_iter(b: &mut Bencher) { 17 | let coins = vec![1, 2, 5]; 18 | b.iter(|| dp::coin::make_change_iter(&coins, MAKE_CHANGES_AMOUNT)); 19 | } 20 | 21 | static BENCH_N: usize = 20; 22 | 23 | #[bench] 24 | fn fib_classic_recursive(b: &mut Bencher) { 25 | b.iter(|| dp::fib::fib_classic_recursive(BENCH_N)); 26 | } 27 | 28 | #[bench] 29 | fn fib_cache_result(b: &mut Bencher) { 30 | b.iter(|| dp::fib::fib_cache_result(BENCH_N)); 31 | } 32 | 33 | #[bench] 34 | fn fib_classic_iteration_loop(b: &mut Bencher) { 35 | b.iter(|| dp::fib::fib_classic_iteration_loop(BENCH_N)); 36 | } 37 | 38 | #[bench] 39 | fn fib_classic_iteration_for(b: &mut Bencher) { 40 | b.iter(|| dp::fib::fib_classic_iteration_for(BENCH_N)); 41 | } 42 | 43 | #[bench] 44 | fn fib_cache_result_c(b: &mut Bencher) { 45 | b.iter(|| unsafe { dp::fib::fib_cache_result_c(BENCH_N) }); 46 | } 47 | 48 | #[bench] 49 | fn fib_classic_iteration_for_c(b: &mut Bencher) { 50 | b.iter(|| unsafe { dp::fib::fib_classic_iteration_for_c(BENCH_N) }); 51 | } 52 | -------------------------------------------------------------------------------- /src/common/util.rs: -------------------------------------------------------------------------------- 1 | use rand; 2 | use rand::prelude::SliceRandom; 3 | 4 | pub fn shuffle(data: &mut [T]) { 5 | let mut rng = rand::thread_rng(); 6 | data.shuffle(&mut rng); 7 | } 8 | 9 | // n, item length 10 | // n = 1, vec!["a", "b", ... "z"] 11 | // n = 2, vec!["aa", "bb", ... "zz"] 12 | pub fn vec_alphabet(n: usize) -> Vec { 13 | debug_assert!(n > 0); 14 | "abcdefghijklmnopqrstuvwxyz" 15 | .chars() 16 | .map(|c| String::from(c).repeat(n)) 17 | .collect() 18 | } 19 | 20 | /// return d-th character of s, -1 if d = length of string 21 | #[inline(always)] 22 | pub fn byte_at_checked(s: &str, d: usize) -> i32 { 23 | if let Some(v) = s.as_bytes().get(d) { 24 | *v as i32 25 | } else { 26 | -1 27 | } 28 | } 29 | 30 | /// uncheck version of byte_at 31 | #[inline(always)] 32 | pub fn byte_at(s: &str, d: usize) -> usize { 33 | s.as_bytes()[d] as usize 34 | } 35 | 36 | #[test] 37 | fn t_vec_alphabet() { 38 | let vec = vec_alphabet(1); 39 | assert_eq!("a", vec[0]); 40 | 41 | let vec = vec_alphabet(10); 42 | assert_eq!("aaaaaaaaaa", vec[0]); 43 | } 44 | 45 | #[test] 46 | fn t_char_at() { 47 | assert_eq!(b'a' as i32, byte_at_checked("abc", 0)); 48 | assert_eq!(b'b' as i32, byte_at_checked("abc", 1)); 49 | assert_eq!(b'c' as i32, byte_at_checked("abc", 2)); 50 | assert_eq!(-1, byte_at_checked("abc", 3)); 51 | } 52 | -------------------------------------------------------------------------------- /src/tree/binary/tree.rs: -------------------------------------------------------------------------------- 1 | use crate::tree::binary::node::Node; 2 | use std::ptr::NonNull; 3 | 4 | pub struct Tree { 5 | pub root: Option>>, 6 | size: usize, 7 | } 8 | 9 | impl Tree { 10 | pub fn height(&self) -> usize { 11 | height(self.root) 12 | } 13 | 14 | pub fn size(&self) -> usize { 15 | self.size 16 | } 17 | 18 | pub fn set_size(&mut self, size: usize) { 19 | self.size = size; 20 | } 21 | 22 | pub fn is_empty(&self) -> bool { 23 | self.root.is_none() 24 | } 25 | } 26 | 27 | impl Default for Tree { 28 | fn default() -> Self { 29 | Tree { 30 | root: None, 31 | size: 0, 32 | } 33 | } 34 | } 35 | 36 | impl Drop for Tree { 37 | fn drop(&mut self) { 38 | fn visitor(p: Option>>) { 39 | if let Some(p) = p { 40 | let p = unsafe { Box::from_raw(p.as_ptr()) }; 41 | visitor(p.left); 42 | visitor(p.right); 43 | } 44 | } 45 | visitor(self.root); 46 | } 47 | } 48 | 49 | fn height(node: Option>>) -> usize { 50 | node.map_or(0, |node| unsafe { 51 | let lh = height(node.as_ref().left); 52 | let rh = height(node.as_ref().right); 53 | 1 + std::cmp::max(lh, rh) 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /src/graph/undirected/dfs2.rs: -------------------------------------------------------------------------------- 1 | //! The *NonRecursiveDFS* represents a data type for finding 2 | //! the vertices connected to a source vertex *s* in the undirected 3 | //! graph. 4 | //! 5 | //! This implementation uses a non recursive version of depth-first search 6 | //! with an explicit stack. 7 | 8 | use crate::common::Stack; 9 | use crate::graph::IGraph; 10 | 11 | pub struct NonRecursiveDFS { 12 | marked: Vec, 13 | } 14 | 15 | impl NonRecursiveDFS { 16 | pub fn new(graph: &dyn IGraph, s: usize) -> Self { 17 | let mut dfs = Self { 18 | marked: vec![false; graph.V()], 19 | }; 20 | dfs.mark(graph, s); 21 | dfs 22 | } 23 | 24 | pub fn marked(&self, v: usize) -> bool { 25 | self.marked[v] 26 | } 27 | } 28 | 29 | impl NonRecursiveDFS { 30 | fn mark(&mut self, graph: &dyn IGraph, s: usize) { 31 | let mut adj = Vec::with_capacity(graph.V()); 32 | for v in 0..graph.V() { 33 | adj.push(graph.adj(v)); 34 | } 35 | 36 | let mut stack = Stack::default(); 37 | stack.push(s); 38 | self.marked[s] = true; 39 | 40 | while let Some(&v) = stack.peek() { 41 | if let Some(&w) = adj[v].next() { 42 | if !self.marked[w] { 43 | self.marked[w] = true; 44 | stack.push(w); 45 | } 46 | } else { 47 | let _ = stack.pop(); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/graph/mst/edge.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | // Default, 用于MinPQ中的0号元素 4 | #[derive(Default, Copy, Clone)] 5 | pub struct Edge { 6 | v: usize, 7 | w: usize, 8 | weight: f32, 9 | } 10 | 11 | impl Edge { 12 | pub fn new(v: usize, w: usize, weight: f32) -> Self { 13 | if weight.is_nan() { 14 | panic!("Weight is NaN"); 15 | } 16 | Self { v, w, weight } 17 | } 18 | 19 | pub fn weight(&self) -> f32 { 20 | self.weight 21 | } 22 | 23 | pub fn either(&self) -> usize { 24 | self.v 25 | } 26 | 27 | pub fn other(&self, v: usize) -> usize { 28 | if self.v == v { 29 | self.w 30 | } else if self.w == v { 31 | self.v 32 | } else { 33 | panic!("illegal vertex") 34 | } 35 | } 36 | } 37 | 38 | impl PartialOrd for Edge { 39 | fn partial_cmp(&self, other: &Self) -> Option { 40 | self.weight.partial_cmp(&other.weight) 41 | } 42 | } 43 | 44 | impl PartialEq for Edge { 45 | fn eq(&self, other: &Self) -> bool { 46 | self.weight == other.weight 47 | } 48 | } 49 | 50 | // todo: eliminate, used by KruskalMST 51 | impl Ord for Edge { 52 | fn cmp(&self, other: &Self) -> Ordering { 53 | self.weight.partial_cmp(&other.weight).unwrap() 54 | } 55 | } 56 | 57 | impl Eq for Edge {} 58 | 59 | impl ToString for Edge { 60 | fn to_string(&self) -> String { 61 | format!("{}-{} {:.5}", self.v, self.w, self.weight) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/sort/insert.rs: -------------------------------------------------------------------------------- 1 | //! 插入排序 2 | //! 3 | //! 基本思想是将一个value插入到有序表中 4 | 5 | use std::cmp::Ordering; 6 | 7 | pub fn sort(a: &mut [T]) 8 | where 9 | T: Ord, 10 | { 11 | let len = a.len(); 12 | // i begins with `1` 13 | for i in 1..len { 14 | // insert a[i] into a[0..i-1] 15 | let mut j = i; 16 | while j > 0 && a[j] < a[j - 1] { 17 | a.swap(j, j - 1); 18 | j -= 1; 19 | } 20 | } 21 | } 22 | 23 | /// insertion sort a[lo..=hi], starting at d-th character 24 | /// lo & hi, is inclusive 25 | pub fn sort_dth(a: &mut [T], lo: usize, hi: usize, d: usize) 26 | where 27 | T: AsRef, 28 | { 29 | // i begin with `lo + 1` 30 | for i in lo + 1..=hi { 31 | let mut j = i; 32 | while j > lo && is_less(a[j].as_ref(), a[j - 1].as_ref(), d) { 33 | a.swap(j, j - 1); 34 | j -= 1; 35 | } 36 | } 37 | } 38 | 39 | /// is v less than w, starting at d-th character 40 | fn is_less(v: &str, w: &str, d: usize) -> bool { 41 | for (a, b) in v.bytes().zip(w.bytes()).skip(d) { 42 | match a.cmp(&b) { 43 | Ordering::Less => return true, 44 | Ordering::Equal => (), 45 | Ordering::Greater => return false, 46 | } 47 | } 48 | v.as_bytes().len() < w.as_bytes().len() 49 | } 50 | 51 | #[test] 52 | fn t_less() { 53 | assert!(is_less("aaa", "aaaa", 0)); // len less 54 | assert!(is_less("aaa", "aaaa", 1)); // len less 55 | assert!(is_less("aaa", "abaa", 1)); // 'a' < 'b' 56 | } 57 | -------------------------------------------------------------------------------- /src/graph/undirected/dfs.rs: -------------------------------------------------------------------------------- 1 | //! find vertices connected to a source vertex s 2 | //! 3 | //! We use the term 'source' (起点) to distinguish the 4 | //! vertex provided as argument to the constructor 5 | //! from the other vertices in the graph. 6 | //! 7 | //! depth-first search (DFS) 8 | //! 9 | //! To search a graph, invoke a *recursive* method that visits vertices. 10 | //! To visit a vertex: 11 | //! - Mark it as having been visited. 12 | //! - Visit (recursively) all the vertices that are adjacent to it and 13 | //! that have not yet been marked. 14 | 15 | use crate::graph::IGraph; 16 | 17 | pub struct DepthFirstSearch { 18 | marked: Vec, 19 | count: usize, 20 | } 21 | 22 | impl DepthFirstSearch { 23 | pub fn new(g: &dyn IGraph, s: usize) -> Self { 24 | let mut dfs = Self { 25 | marked: vec![false; g.V()], 26 | count: 0, 27 | }; 28 | dfs.dfs(g, s); 29 | dfs 30 | } 31 | 32 | /// is v connected to s? 33 | pub fn marked(&self, v: usize) -> bool { 34 | self.marked[v] 35 | } 36 | 37 | /// how many vertices are connected to s? 38 | /// 39 | /// if (search.count() != G.V()) 40 | /// Not connected 41 | pub fn count(&self) -> usize { 42 | self.count 43 | } 44 | } 45 | 46 | impl DepthFirstSearch { 47 | fn dfs(&mut self, g: &dyn IGraph, v: usize) { 48 | self.marked[v] = true; 49 | self.count += 1; 50 | for &w in g.adj(v) { 51 | if !self.marked[w] { 52 | self.dfs(g, w); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/graph/mod.rs: -------------------------------------------------------------------------------- 1 | //! 2 | //! ## 图的典型应用 3 | //! 4 | //! | 应用 | 节点 | 连接 | 5 | //! |-----------|--------------|-----------------| 6 | //! | 地图 | 十字路口 | 公路 | 7 | //! | 网络内容 | 网页 | 超链接 | 8 | //! | 电路 | 元器件 | 导线 | 9 | //! | 任务调度 | 任务 | 限制条件 | 10 | //! | 商业交易 | 客户 | 交易 | 11 | //! | 配对 | 学生 | 申请 | 12 | //! | 计算机网络 | 网站 | 物理连接 | 13 | //! | 软件 | 方法 | 调用关系 | 14 | //! | 社交网络 | 人 | 友谊关系 | 15 | 16 | pub mod directed; 17 | pub mod mst; // minimum spanning trees 18 | pub mod shortest; // shortest path 19 | pub mod undirected; 20 | pub mod util; 21 | 22 | pub use mst::IEWGraph; 23 | pub use shortest::IEWDigraph; 24 | pub use undirected::IGraph; 25 | 26 | macro_rules! impl_to_string { 27 | ($G: ty) => { 28 | impl ToString for $G { 29 | fn to_string(&self) -> String { 30 | let mut buf = Vec::new(); 31 | buf.push(format!("{} {}", self.V(), self.E())); 32 | for v in 0..self.V() { 33 | let adj = self 34 | .adj(v) 35 | .map(|v| v.to_string()) 36 | .collect::>() 37 | .join(" "); 38 | buf.push(format!("{}: {}", v, adj)); 39 | } 40 | buf.join("\n") 41 | } 42 | } 43 | }; 44 | } 45 | 46 | impl_to_string!(dyn IGraph); 47 | impl_to_string!(dyn IEWGraph); 48 | impl_to_string!(dyn IEWDigraph); 49 | -------------------------------------------------------------------------------- /src/graph/directed/scc.rs: -------------------------------------------------------------------------------- 1 | //! Strong connectivity in digraphs 2 | //! 3 | //! Definition. 4 | //! Two vertices v and w are strongly connected if they are mutually 5 | //! reachable: that is, if there is a directed path from v to w and 6 | //! a directed path from w to v. A digraph is strongly connected if 7 | //! all its vertices are strongly connected to one another. 8 | //! 9 | use crate::graph::directed::DepthFirstOrders; 10 | use crate::graph::IGraph; 11 | 12 | pub struct KosarajuSCC { 13 | marked: Vec, 14 | id: Vec, 15 | count: usize, 16 | } 17 | 18 | impl KosarajuSCC { 19 | pub fn new(graph: &dyn IGraph) -> Self { 20 | let mut scc = Self { 21 | marked: vec![false; graph.V()], 22 | id: vec![0; graph.V()], 23 | count: 0, 24 | }; 25 | let order = DepthFirstOrders::from(graph.reverse().as_ref()); 26 | for &s in order.rev_post() { 27 | if !scc.marked[s] { 28 | scc.dfs(graph, s); 29 | scc.count += 1; 30 | } 31 | } 32 | 33 | scc 34 | } 35 | 36 | pub fn strongly_connected(&self, v: usize, w: usize) -> bool { 37 | self.id[v] == self.id[w] 38 | } 39 | 40 | pub fn id(&self, v: usize) -> usize { 41 | self.id[v] 42 | } 43 | 44 | pub fn count(&self) -> usize { 45 | self.count 46 | } 47 | } 48 | 49 | impl KosarajuSCC { 50 | fn dfs(&mut self, graph: &dyn IGraph, v: usize) { 51 | self.marked[v] = true; 52 | self.id[v] = self.count; 53 | for &w in graph.adj(v) { 54 | if !self.marked[w] { 55 | self.dfs(graph, w); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/common/queue.rs: -------------------------------------------------------------------------------- 1 | //! The Queue represents a first-in-first-out (FIFO) 2 | //! queue of generic items. 3 | //! It supports the usual enqueue and dequeue 4 | //! operations, along with methods for peeking at the first item, 5 | //! testing if the queue is empty, and iterating through 6 | //! the items in FIFO order. 7 | //! This implementation uses a singly linked list. 8 | //! The enqueue, dequeue, peek, size, and is-empty 9 | //! operations all take constant time in the worst case. 10 | 11 | use crate::ll::linked_list::Iter; 12 | use crate::ll::LinkedList; 13 | 14 | pub struct Queue { 15 | ll: LinkedList, 16 | } 17 | 18 | impl Queue { 19 | /// Adds the item to this queue 20 | pub fn enqueue(&mut self, v: T) { 21 | self.ll.push_back(v); 22 | } 23 | 24 | /// Removes and returns the item on this queue that was least recently added 25 | pub fn dequeue(&mut self) -> Option { 26 | self.ll.pop_front() 27 | } 28 | 29 | /// Returns the item least recently added to this queue 30 | pub fn peek(&self) -> Option<&T> { 31 | self.ll.first() 32 | } 33 | 34 | /// Returns an iterator that iterates over the items in this queue in FIFO order 35 | pub fn iter(&self) -> Iter<'_, T> { 36 | self.ll.iter() 37 | } 38 | 39 | /// Returns the number of items in this queue 40 | pub fn len(&self) -> usize { 41 | self.ll.len() 42 | } 43 | 44 | /// Returns true if this queue is empty 45 | pub fn is_empty(&self) -> bool { 46 | self.ll.is_empty() 47 | } 48 | } 49 | 50 | impl Default for Queue { 51 | fn default() -> Self { 52 | let ll = LinkedList::default(); 53 | Self { ll } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_sparse_vec.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate approx; 3 | 4 | use algo::math::sparse_vector::SparseVector; 5 | 6 | #[test] 7 | fn dot() { 8 | let (a, b) = create(); 9 | assert_relative_eq!(a.dot(&b).unwrap(), 0.3); 10 | } 11 | 12 | #[test] 13 | fn magnitude() { 14 | let (a, _) = create(); 15 | assert_relative_eq!( 16 | a.magnitude(), 17 | (0.5_f64.powf(2.0) + 0.75_f64.powf(2.0)).sqrt() 18 | ); 19 | } 20 | 21 | #[test] 22 | fn scale() { 23 | let (a, _) = create(); 24 | let c = a.scale(2.0); 25 | let expect = vec![0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5]; 26 | for (i, &v) in expect.iter().enumerate() { 27 | assert_relative_eq!(v, c.get(i),); 28 | } 29 | } 30 | 31 | #[test] 32 | fn plus() { 33 | let (a, b) = create(); 34 | let c = a + b; 35 | let expect = vec![0.0, 0.0, 0.0, 1.1, 0.9, 0.0, 0.0, 0.0, 0.0, 0.75]; 36 | for (i, &v) in expect.iter().enumerate() { 37 | assert_relative_eq!(v, c.get(i),); 38 | } 39 | } 40 | 41 | #[test] 42 | fn sub() { 43 | let (a, b) = create(); 44 | let c = a - b; 45 | let expect = vec![0.0, 0.0, 0.0, -0.1, -0.9, 0.0, 0.0, 0.0, 0.0, 0.75]; 46 | for (i, &v) in expect.iter().enumerate() { 47 | assert_relative_eq!(v, c.get(i),); 48 | } 49 | } 50 | 51 | #[test] 52 | fn to_string() { 53 | let (a, _) = create(); 54 | assert_eq!(a.to_string(), "(3, 0.5)(9, 0.75)"); 55 | } 56 | 57 | fn create() -> (SparseVector, SparseVector) { 58 | let mut a = SparseVector::new(10); 59 | let mut b = SparseVector::new(10); 60 | a.put(3, 0.5); 61 | a.put(9, 0.75); 62 | a.put(6, 0.11); 63 | a.put(6, 0.0); 64 | b.put(3, 0.6); 65 | b.put(4, 0.9); 66 | 67 | (a, b) 68 | } 69 | -------------------------------------------------------------------------------- /CheatSheet.md: -------------------------------------------------------------------------------- 1 | # Algorithms and Data Structures Cheatsheet 2 | 3 | We summarize the performance characteristics of classic algorithms and data structures for sorting, priority queues, symbol tables, and graph processing. 4 | 5 | We also summarize some of the mathematics useful in the analysis of algorithms, including commonly encountered functions; useful formulas and approximations; properties of logarithms; asymptotic notations; and solutions to divide-and-conquer recurrences. 6 | 7 | 8 | ### Sorting 9 | 10 | The table below summarizes the number of compares for a variety of sorting algorithms, as implemented in this textbook. It includes leading constants but ignores lower-order terms. 11 | 12 | 13 | ### Which string sorting algorithm should I use? 14 | 15 | order of growth of typical number calls to charAt() to sort N Strings 16 | from an R-character alphabet (average length w, max length W) 17 | 18 | | algorithm | stable? | inplace? | running time | extra space | sweet spot | 19 | |-----------|---------|----------|--------------|-------------|------------| 20 | | insertion sort for strings | yes | yes | between N and N^2 | 1 | small arrays, arrays in order| 21 | | quicksort | no | yes | N * log^2 N | log N | general-purpose when space is tight | 22 | | mergesort | yes | no | N * log^2 N | N | general-purpose stable sort | 23 | | 3-way quicksort | no | yes | between N and N * log N | log N | large number of equal keys | 24 | | LSD string sort | yes | no | N * W | N | short fixed length strings | 25 | | MSD string sort | yes | no | between N and N * w | N + W * R | random strings | 26 | | 3-way string quicksort | no | yes | between N and N * w | W + log N | general-purpose strings with long prefix maches| 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/graph/directed/digraph.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::util::parser::GraphDataParser; 2 | use crate::graph::IGraph; 3 | use crate::ll::linked_list::Iter; 4 | use crate::ll::LinkedList; 5 | 6 | pub struct Digraph { 7 | nv: usize, // num of vertices 8 | ne: usize, // num of edges 9 | adj: Vec>, 10 | } 11 | 12 | impl IGraph for Digraph { 13 | fn V(&self) -> usize { 14 | self.nv 15 | } 16 | 17 | fn E(&self) -> usize { 18 | self.ne 19 | } 20 | 21 | fn add_edge(&mut self, v: usize, w: usize) { 22 | // 因为是建立 "v -> w" 有方向的边, 23 | // 此处只调用一次push_front, 不同于Graph 24 | self.adj[v].push_front(w); 25 | self.ne += 1; 26 | } 27 | 28 | fn adj(&self, v: usize) -> Iter<'_, usize> { 29 | self.adj[v].iter() 30 | } 31 | 32 | /// reverse of this digraph 33 | fn reverse(&self) -> Box { 34 | let mut r = Digraph::from(self.nv); 35 | for v in 0..self.nv { 36 | for &w in self.adj(v) { 37 | r.add_edge(w, v); 38 | } 39 | } 40 | 41 | Box::new(r) 42 | } 43 | } 44 | 45 | /// create a V-vertex graph with no edges 46 | impl From for Digraph { 47 | fn from(nv: usize) -> Self { 48 | let mut adj = Vec::with_capacity(nv); 49 | for _ in 0..nv { 50 | adj.push(LinkedList::default()); 51 | } 52 | 53 | Self { nv, ne: 0, adj } 54 | } 55 | } 56 | 57 | impl From<&str> for Digraph { 58 | fn from(s: &str) -> Self { 59 | let parser = GraphDataParser::parse(s, false).unwrap(); 60 | let mut g = Self::from(parser.get_v()); 61 | for (v, w) in parser.get_edges() { 62 | g.add_edge(*v, *w); 63 | } 64 | debug_assert!(g.E() == parser.get_e()); 65 | g 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/graph/undirected/mod.rs: -------------------------------------------------------------------------------- 1 | //! Since we consider a large number of graph processing algorithms, 2 | //! our initial design goal is to decouple our implementations from 3 | //! the graph representation. To do so, we develop, for each given 4 | //! task, a task-specific class so that clients can create objects 5 | //! to perform the task. 6 | //! 7 | //! | Problem | Solution 8 | //! |----------------------------------|------------------------------------------ 9 | //! | single source connectivity | DepthFirstSearch (dfs) | 10 | //! | single source paths | DepthFirstPaths (util/paths.rs) | 11 | //! | single source shortest paths | BreadthFirstPaths (util/paths.rs) | 12 | //! | connectivity | CC (cc.rs) | 13 | //! | cycle detection | Cycle (bipartite) | 14 | //! | two-color (bipartite) | TwoColor (bipartite) | 15 | //! 16 | pub use bipartite::Bipartite; 17 | pub use cc::CC; 18 | pub use cycle::Cycle; 19 | pub use dfs::DepthFirstSearch; 20 | pub use dfs2::NonRecursiveDFS; 21 | pub use graph::Graph; 22 | 23 | mod bipartite; 24 | mod cc; 25 | mod cycle; 26 | mod dfs; 27 | mod dfs2; 28 | mod graph; 29 | 30 | use crate::ll::linked_list::Iter; 31 | pub trait IGraph { 32 | /// number of vertices 33 | #[allow(non_snake_case)] 34 | fn V(&self) -> usize; 35 | 36 | /// number of edges 37 | #[allow(non_snake_case)] 38 | fn E(&self) -> usize; 39 | 40 | /// add edge v-w to this graph 41 | fn add_edge(&mut self, v: usize, w: usize); 42 | 43 | /// vertices adjacent to v 44 | fn adj(&self, v: usize) -> Iter<'_, usize>; 45 | 46 | /// directed graph op 47 | fn reverse(&self) -> Box { 48 | panic!("No Support"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/graph/directed/sort.rs: -------------------------------------------------------------------------------- 1 | //! A digraph has a topological order if and only if it is a DAG. 2 | 3 | use crate::graph::directed::{DepthFirstOrders, DirectedCycle, EdgeWeightedDirectedCycle}; 4 | use crate::graph::{IEWDigraph, IGraph}; 5 | use std::slice::Iter; 6 | 7 | /// The Topological represents a data type for 8 | /// determining a topological order of a directed acyclic graph (DAG). 9 | /// A digraph has a topological order if and only if it is a DAG. 10 | /// The has_order operation determines whether the digraph has 11 | /// a topological order, and if so, the order operation 12 | /// returns one. 13 | /// This implementation uses depth-first search. 14 | pub struct Topological { 15 | order: Option>, 16 | } 17 | 18 | impl Topological { 19 | /// Does the digraph have a topological order? 20 | /// true if the digraph has a topological order (or equivalently, 21 | /// if the digraph is a DAG), and false otherwise 22 | pub fn has_order(&self) -> bool { 23 | self.order.is_some() 24 | } 25 | 26 | /// Returns a topological order if the digraph has a topologial order, 27 | /// and None otherwise. 28 | pub fn order(&self) -> Option> { 29 | self.order.as_ref().map(|v| v.iter()) 30 | } 31 | } 32 | 33 | macro_rules! impl_from { 34 | ($From: ty, $Cycle: ident) => { 35 | impl From<$From> for Topological { 36 | fn from(g: $From) -> Self { 37 | let cycle = $Cycle::from(g); 38 | let order = if cycle.has_cycle() { 39 | None 40 | } else { 41 | let dfs = DepthFirstOrders::from(g); 42 | Some(dfs.rev_post().cloned().collect()) 43 | }; 44 | 45 | Self { order } 46 | } 47 | } 48 | }; 49 | } 50 | 51 | impl_from!(&dyn IGraph, DirectedCycle); 52 | impl_from!(&dyn IEWDigraph, EdgeWeightedDirectedCycle); 53 | -------------------------------------------------------------------------------- /src/tree/binary/avl.rs: -------------------------------------------------------------------------------- 1 | //! AVL 树 2 | //! 3 | //! 为了度量一棵二叉树的平衡,我们可以比较左右分支的高度差,如果差很大, 4 | //! 则说明树不平衡。定义一棵树的高度差如下: 5 | //! δ(T) = |Tr| − |Tl| 6 | //! 其中 |T | 代表树 T 的高度,Tl 和 Tr 分别代表左右分支。 7 | //! 8 | //! 如果一棵二叉搜索树的所有子树都满足如下条件,我们称之为 AVL 树。 9 | //! |δ(T )| ≤ 1 10 | //! 11 | //! 12 | //! 结论: 13 | //! AVL树是在1962年由Adelson-Velskii和Landis发表的。AVL树的命名来自两位作者的名字。 14 | //! 它的历史要比红黑树更早。人们很自然会比较AVL树和红黑树。它们都是自平衡二叉搜索树,对于 15 | //! 主要的树操作,它们的性能都是 O(lg n) 的。AVL树的平衡性更为严格,因此在频繁查询的情况下, 16 | //! 其表现要好于红黑树。但红黑树在频繁插入和删除的情况下性能更佳。 17 | //! 很多流行的程序库使用红黑树作为自平衡二叉搜索树的内部实现,例如STL,AVL树同样也可以直观、高效 18 | //! 地解决平衡问题。 19 | //! 20 | //! 如下tree,是一棵正确的rb tree,而不是一棵正确的avl tree 21 | //! 22 | //! https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 23 | //! 24 | //! 输入序列: [100, 150, 50, 125, 114, 107] 25 | //! 26 | //! B(100) 27 | //! / \ 28 | //! B(50) R(125) 29 | //! / \ 30 | //! B(114) B(150) 31 | //! / 32 | //! R(107) 33 | //! 34 | //! 35 | 36 | /* 37 | 38 | 1. ll lean (左左偏) 39 | 40 | (z) 41 | / \ 42 | (y) D 43 | / \ 44 | (x) C 45 | / \ 46 | A B 47 | 48 | delta(z) = -2 49 | delta(y) = -1 50 | 51 | 2. rr lean 52 | 53 | (x) 54 | / \ 55 | A (y) 56 | / \ 57 | B (z) 58 | / \ 59 | C D 60 | 61 | delta(x) = 2 62 | delta(y) = 1 63 | 64 | 3. rl lean 65 | (x) 66 | / \ 67 | A (z) 68 | / \ 69 | (y) D 70 | / \ 71 | B C 72 | 73 | delta(x) = 2 74 | delta(z) = -1 75 | 76 | 4. lr lean 77 | (z) 78 | / \ 79 | (x) D 80 | / \ 81 | A (y) 82 | / \ 83 | B C 84 | 85 | delta(z) = -2 86 | delta(x) = 1 87 | 88 | =========================================== 89 | 90 | 被修复为一个统一形式 91 | 92 | (y) 93 | / \ 94 | (x) (z) 95 | / \ / \ 96 | A B C D 97 | 98 | delta(y) = 0 99 | 100 | */ 101 | -------------------------------------------------------------------------------- /src/dp/coin.rs: -------------------------------------------------------------------------------- 1 | //! 凑零钱问题 2 | //! 3 | //! 先看下题目: 4 | //! 给你 k 种面值的硬币,面值分别为 c1, c2 ... ck,每种硬币的数量无限,再给一个总金额 amount, 5 | //! 问你最少需要几枚硬币凑出这个金额,如果不可能凑出,算法返回 -1 。 6 | //! 7 | //! 算法的函数签名如下: 8 | //! // coins 中是可选硬币面值,amount 是目标金额 9 | //! int coinChange(int[] coins, int amount); 10 | //! 11 | 12 | macro_rules! check_inputs { 13 | //assert no '0' coin 14 | ($coins:ident, $amount:ident) => { 15 | assert!($coins.iter().all(|&v| v != 0)); 16 | match ($coins.is_empty(), $amount) { 17 | (true, 0) => return 0, 18 | (true, _) | (false, 0) => return -1, 19 | (_, amount) if amount < 0 => return -1, 20 | _ => (), 21 | } 22 | }; 23 | } 24 | 25 | /// 暴力穷举 26 | pub fn make_change_classic(coins: &[i32], amount: i32) -> i32 { 27 | if amount == 0 { 28 | return 0; 29 | } 30 | 31 | if amount < 0 { 32 | return -1; 33 | } 34 | 35 | let mut res = i32::MAX; 36 | for &coin in coins { 37 | match make_change_classic(coins, amount - coin) { 38 | -1 => (), 39 | sub => { 40 | res = std::cmp::min(res, 1 + sub); 41 | } 42 | } 43 | } 44 | 45 | if res != i32::MAX { 46 | res 47 | } else { 48 | -1 49 | } 50 | } 51 | 52 | pub fn make_change_iter(coins: &[i32], amount: i32) -> i32 { 53 | check_inputs!(coins, amount); 54 | let max_amount = amount + 1; 55 | // 为啥 dp 数组初始化为 amount + 1 呢,因为凑成 amount 金额的硬币数最多只 56 | // 可能等于 amount(全用 1 元面值的硬币),所以初始化为 amount + 1 就相当 57 | // 于初始化为正无穷,便于后续取最小值。 58 | let mut dp = vec![max_amount; (amount + 1) as usize]; 59 | dp[0] = 0; 60 | 61 | for i in 0..dp.len() { 62 | for &coin in coins { 63 | if i as i32 - coin < 0 { 64 | continue; 65 | } 66 | 67 | dp[i] = std::cmp::min(dp[i], 1 + dp[i - coin as usize]); 68 | } 69 | } 70 | 71 | let v = dp[amount as usize]; 72 | if v == max_amount { 73 | -1 74 | } else { 75 | v 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/dp/fib.rs: -------------------------------------------------------------------------------- 1 | //! fib 2 | 3 | use std::cell::RefCell; 4 | 5 | /// classic impl 6 | #[allow(unused)] 7 | pub fn fib_classic_recursive(n: usize) -> usize { 8 | match n { 9 | 0 => 0, 10 | 1 | 2 => 1, 11 | _ => fib_classic_recursive(n - 1) + fib_classic_recursive(n - 2), 12 | } 13 | } 14 | 15 | thread_local!(static MEMO: RefCell> = RefCell::new(vec![0; 1000])); 16 | 17 | /// 缓存中间结果 18 | #[allow(unused)] 19 | pub fn fib_cache_result(n: usize) -> usize { 20 | match n { 21 | 0 => 0, 22 | 1 | 2 => 1, 23 | _ => match MEMO.with(|memo| memo.borrow()[n]) { 24 | 0 => { 25 | let v = fib_cache_result(n - 1) + fib_cache_result(n - 2); 26 | MEMO.with(|memo| memo.borrow_mut()[n] = v); 27 | v 28 | } 29 | memo => memo, 30 | }, 31 | } 32 | } 33 | 34 | /// 只保存前两个值,最节省内存和最快的方式 35 | #[allow(unused)] 36 | pub fn fib_classic_iteration_loop(n: usize) -> usize { 37 | match n { 38 | 0 => 0, 39 | 1 | 2 => 1, 40 | _ => { 41 | let mut prev = 1; 42 | let mut cur = 1; 43 | let mut i = 3; 44 | loop { 45 | let sum = prev + cur; 46 | prev = cur; 47 | cur = sum; 48 | 49 | i += 1; 50 | if i > n { 51 | return cur; 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | /// 只保存前两个值,最节省内存和最快的方式 59 | /// 但实际基准测试结果并没有预期的那么快, 有可能是for的原因 60 | #[allow(unused)] 61 | pub fn fib_classic_iteration_for(n: usize) -> usize { 62 | match n { 63 | 0 => 0, 64 | 1 | 2 => 1, 65 | _ => { 66 | let mut prev = 1; 67 | let mut cur = 1; 68 | for _ in 3..=n { 69 | let sum = prev + cur; 70 | prev = cur; 71 | cur = sum; 72 | } 73 | 74 | cur 75 | } 76 | } 77 | } 78 | 79 | extern "C" { 80 | pub fn fib_cache_result_c(v: usize) -> usize; 81 | pub fn fib_classic_iteration_for_c(v: usize) -> usize; 82 | } 83 | -------------------------------------------------------------------------------- /tests/test_graph_mst.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate approx; 3 | 4 | use algo::graph::mst::{EWGraph, KruskalMST, LazyPrimMST, PrimMST, MST}; 5 | use algo::graph::IEWGraph; 6 | 7 | const TINY_EWG: &'static str = include_str!("../res/graph/tinyEWG.txt"); 8 | 9 | #[test] 10 | fn parse() { 11 | let i = TINY_EWG; 12 | let graph = create_graph(i); 13 | assert_eq!(graph.V(), 8); 14 | assert_eq!(graph.E(), 16); 15 | /* 16 | 8 16 17 | 0: 6-0 0.58000 0-2 0.26000 0-4 0.38000 0-7 0.16000 18 | 1: 1-3 0.29000 1-2 0.36000 1-7 0.19000 1-5 0.32000 19 | 2: 6-2 0.40000 2-7 0.34000 1-2 0.36000 0-2 0.26000 2-3 0.17000 20 | 3: 3-6 0.52000 1-3 0.29000 2-3 0.17000 21 | 4: 6-4 0.93000 0-4 0.38000 4-7 0.37000 4-5 0.35000 22 | 5: 1-5 0.32000 5-7 0.28000 4-5 0.35000 23 | 6: 6-4 0.93000 6-0 0.58000 3-6 0.52000 6-2 0.40000 24 | 7: 2-7 0.34000 1-7 0.19000 0-7 0.16000 5-7 0.28000 4-7 0.37000 25 | */ 26 | // println!("{}", graph.to_string()); 27 | } 28 | 29 | #[allow(non_snake_case)] 30 | #[test] 31 | fn lazy_Prim_mst() { 32 | let i = TINY_EWG; 33 | let g = create_graph(i); 34 | let mst = LazyPrimMST::new(g.as_ref()); 35 | assert_relative_eq!(1.81, mst.weight()); 36 | assert!(mst.check(g.as_ref()).is_ok()); 37 | 38 | // for e in mst.edges() { 39 | // println!("{}", e.to_string()); 40 | // } 41 | } 42 | 43 | #[allow(non_snake_case)] 44 | #[test] 45 | fn Prim_mst() { 46 | let i = TINY_EWG; 47 | let g = create_graph(i); 48 | let mst = PrimMST::new(g.as_ref()); 49 | assert_relative_eq!(1.81, mst.weight()); 50 | assert!(mst.check(g.as_ref()).is_ok()); 51 | 52 | // for e in mst.edges() { 53 | // println!("{}", e.to_string()); 54 | // } 55 | } 56 | 57 | #[allow(non_snake_case)] 58 | #[test] 59 | fn Kruskal_mst() { 60 | let i = TINY_EWG; 61 | let g = create_graph(i); 62 | let mst = KruskalMST::new(g.as_ref()); 63 | assert_relative_eq!(1.81, mst.weight()); 64 | assert!(mst.check(g.as_ref()).is_ok()); 65 | 66 | // for e in mst.edges() { 67 | // println!("{}", e.to_string()); 68 | // } 69 | } 70 | 71 | fn create_graph(i: &str) -> Box { 72 | Box::new(EWGraph::from(i)) 73 | } 74 | -------------------------------------------------------------------------------- /todos.md: -------------------------------------------------------------------------------- 1 | ### Todo list 2 | 3 | - algs4 exercises 4 | 5 | - algs4, 1.5.16 plots 6 | - rust plots crate: https://github.com/38/plotters.git 7 | - 借助rust feature条件编译,实现记录统计数据的代码,不影响正常情况的性能 8 | 9 | - benchmark可视化。找一种通用性能剖析方法,比如UF,在union函数中监视parent 和 rank被读了 10 | 多少次,被写了多少次,方便plot。rust如果不具备这个功能,考虑其他语言python, 11 | js, kotlin... (python也许是个好选择,并且有完善的plot库) 12 | 这个语言需要具备的必要条件: 13 | - 监听变量(读 / 写) 14 | - plot 15 | - 读写本地文件 16 | 17 | - algorithms visualization 18 | 19 | algorithms / runtime data / anim render engine..., 20 | independent of each other, connected by gRPC 21 | 22 | algorithms impl as Server 23 | anim render engine as Client, render algorithms runtime data 24 | protobuf choose tonic 25 | 26 | The arch of system must contain all kinds of algorithms, 27 | a kind of algorithm, impl as a plugin, follow spec,amin engine 28 | can render it. 29 | 30 | data format for Excel & Numbers & plotting libs & csv... 31 | 32 | - fix mod/struct/fn doc error to make doc work well, add more docs 33 | 34 | - The [Cheat Sheet](https://algs4.cs.princeton.edu/cheatsheet/) is comprehensive, 35 | rewrite to markdown. 36 | 37 | - resort Index section in README.md follow order showed in textbook 38 | 39 | - strings algorithms lsd/msd/quick3 based bytes 40 | 41 | refact to support chars, std str.chars() poor performance. 42 | build one struct, traverse char by index 43 | 44 | ### 后记 45 | 46 | 项目缘起 47 | 48 | 本人做为从数学系转过来做开发的程序员,没有主修过《算法和数据结构》,一直想找个时 49 | 间补上这一课,趁这个阶段不忙,就动手了。 50 | 51 | 通过这段时间对算法的学习,我感到受益匪浅,特别是图的部分,跟现实问题联系更紧密, 52 | 感觉像打开了一扇窗,以此为基础可以做出许多有意义的项目。 53 | 54 | 任何编程语言都可以用来实现算法,常用的如Python,JavaScript,C++,我选择Rust 55 | 实现我这一遍的算法,我爱Rust,这是特别好的编程语言,特别是在除错方面,Rust编译 56 | 器能帮你非常多。当项目通过编译之后,你知道:80% OK了,可以放心的回家睡觉,养足 57 | 精神之后,元气满满的开始第二天的工作。 58 | 59 | 用Rust实现算法,一开始真的非常难 (如果你不想体验这种煎熬,我建议选择一种支持GC 60 | 的高级语言, Python或JavaScript, 开启你的算法之旅; 对于初学编程的同学,学会一 61 | 门编程语言之后,往往就不知道该干什么了,而写算法是很好的编程进阶训练),当咬牙挺过 62 | 来之后,会对Rust有更深刻的理解,特别是能熟练运用unsafe和lifetimes标注;但是, 63 | 我感觉对Rust的学习是没有尽头的,当写的更多和读的更多之后,你总能预见有下一个高 64 | 度需要去攀登,花这些时间也是值得的,因为通过一番努力之后,代码会更好。Rust真的 65 | 是非常独特,没有哪种语言会给你这些很奇怪的感受。 66 | 67 | 关于Rust我还想多说一些,Rust社区为Rust准备的这组工具包,真是堪称豪华:单元测试, 68 | 性能测试,fmt, clippy,随着项目迭代,这些工具保证你无忧于重构和一致性,让你毫无 69 | 顾虑的大步前进; 同时希望: 这个小项目能为Rust的流行产生一些积极作用。 70 | 71 | 如果你对开发是严肃的,一定要把算法实现一遍,这就像圣徒的麦加圣地,是一定要去的。 -------------------------------------------------------------------------------- /src/graph/shortest/ew_digraph.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::shortest::DirectedEdge; 2 | use crate::graph::util::parser::GraphDataParser; 3 | use crate::graph::IEWDigraph; 4 | use crate::ll::linked_list::Iter; 5 | use crate::ll::LinkedList; 6 | 7 | pub struct EWDigraph { 8 | nv: usize, // number of vertices in this digraph 9 | ne: usize, // number of edges in this digraph 10 | adj: Vec>, // adj[v] = adjacency list for vertex v 11 | in_degree: Vec, // in_degree[v] = in degree of vertex v 12 | } 13 | 14 | impl IEWDigraph for EWDigraph { 15 | fn V(&self) -> usize { 16 | self.nv 17 | } 18 | 19 | fn E(&self) -> usize { 20 | self.ne 21 | } 22 | 23 | fn add_edge(&mut self, v: usize, w: usize, weight: f32) { 24 | let e = DirectedEdge::new(v, w, weight); 25 | self.adj[v].push_front(e); 26 | self.in_degree[w] += 1; 27 | self.ne += 1; 28 | } 29 | 30 | fn adj(&self, v: usize) -> Iter<'_, DirectedEdge> { 31 | self.adj[v].iter() 32 | } 33 | 34 | fn edges(&self) -> Vec { 35 | let mut list = Vec::new(); 36 | for v in 0..self.V() { 37 | for e in self.adj(v) { 38 | list.push(*e) 39 | } 40 | } 41 | list 42 | } 43 | 44 | fn out_degree(&self, v: usize) -> usize { 45 | self.adj[v].len() 46 | } 47 | 48 | fn in_degree(&self, v: usize) -> usize { 49 | self.in_degree[v] 50 | } 51 | } 52 | 53 | impl From for EWDigraph { 54 | fn from(nv: usize) -> Self { 55 | let mut adj = Vec::with_capacity(nv); 56 | for _ in 0..nv { 57 | adj.push(LinkedList::default()); 58 | } 59 | 60 | Self { 61 | nv, 62 | ne: 0, 63 | adj, 64 | in_degree: vec![0; nv], 65 | } 66 | } 67 | } 68 | 69 | impl From<&str> for EWDigraph { 70 | fn from(s: &str) -> Self { 71 | let parser = GraphDataParser::parse(s, true).unwrap(); 72 | let mut g = Self::from(parser.get_v()); 73 | for (v, w, weight) in parser.get_weighted_edges() { 74 | g.add_edge(*v, *w, *weight); 75 | } 76 | debug_assert!(g.E() == parser.get_e()); 77 | g 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/strings/kmp.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | #![allow(clippy::needless_range_loop)] 3 | 4 | //! 5 | //! worst case for brute force search 6 | //! compare with KMP: 7 | //! 8 | //! let pat = "AAAAAAAAAB"; 9 | //! let txt = "A".repeat(10000); 10 | //! 11 | //! test sub_search_brute_force ... bench: 68,616 ns/iter (+/- 9,302) 12 | //! test sub_search_kmp ... bench: 17,805 ns/iter (+/- 2,240) 13 | //! 14 | //! 15 | //! In practice, the speedup over the brute-force method is not 16 | //! often important because few applications involve searching 17 | //! for highly self-repetitive patterns in highly self-repetitive 18 | //! text. Still, the method has the practical advantage that it 19 | //! never backs up in the input. This property makes KMP substring 20 | //! search more convenient for use on an input stream of undetermined 21 | //! length (such as standard input) than algorithms requiring backup, 22 | //! which need some complicated buffering in this situation. 23 | 24 | use crate::common::util::byte_at; 25 | 26 | pub struct KMP { 27 | M: usize, // length of pattern 28 | // dfa is R rows, pat.len() columns 29 | dfa: Vec>, // the KMP automaton 30 | } 31 | 32 | impl KMP { 33 | /// Returns the index of the first occurrence of the pattern string 34 | /// in the text string. 35 | pub fn search(&self, txt: &str) -> Option { 36 | let dfa = self.dfa.as_slice(); 37 | let M = self.M; 38 | let N = txt.len(); 39 | let mut i = 0; 40 | let mut j = 0; 41 | while i < N && j < M { 42 | j = dfa[byte_at(txt, i)][j]; 43 | i += 1; 44 | } 45 | if j == M { 46 | Some(i - M) 47 | } else { 48 | None 49 | } 50 | } 51 | } 52 | 53 | impl From<&str> for KMP { 54 | fn from(pat: &str) -> Self { 55 | let R = 256; 56 | let M = pat.len(); 57 | 58 | // build DFA from pattern 59 | let mut dfa = vec![vec![0; M]; R]; 60 | dfa[byte_at(pat, 0)][0] = 1; 61 | let mut x = 0; 62 | for j in 1..M { 63 | // Compute dfa[][j]. 64 | for c in 0..R { 65 | dfa[c][j] = dfa[c][x]; // Copy mismatch cases. 66 | } 67 | // for match case, DFA step to j + 1 68 | dfa[byte_at(pat, j)][j] = j + 1; // Set match case. 69 | x = dfa[byte_at(pat, j)][x]; // Update restart state. 70 | } 71 | 72 | Self { M, dfa } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/test_dp.rs: -------------------------------------------------------------------------------- 1 | use algo::dp; 2 | 3 | #[test] 4 | fn make_changes() { 5 | let coins = vec![1, 2, 5]; 6 | //(min coins, amount) 7 | let solutions = vec![ 8 | (3, 11), 9 | (3, 12), 10 | (4, 13), 11 | (4, 14), 12 | (3, 15), 13 | (4, 16), 14 | (4, 17), 15 | (5, 18), 16 | (5, 19), 17 | (4, 20), 18 | ]; 19 | for (expect, amount) in solutions { 20 | assert_eq!(expect, dp::coin::make_change_classic(&coins, amount)); 21 | assert_eq!(expect, dp::coin::make_change_iter(&coins, amount)); 22 | } 23 | } 24 | 25 | #[test] 26 | fn make_changes_fail() { 27 | let coins = vec![2, 5]; 28 | let solutions = vec![(-1, 3)]; 29 | for (expect, amount) in solutions { 30 | assert_eq!(expect, dp::coin::make_change_classic(&coins, amount)); 31 | assert_eq!(expect, dp::coin::make_change_iter(&coins, amount)); 32 | } 33 | } 34 | 35 | #[test] 36 | fn fib_classic_recursive() { 37 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 38 | for (i, expect) in values.iter().enumerate() { 39 | assert_eq!(*expect, dp::fib::fib_classic_recursive(i)); 40 | } 41 | } 42 | 43 | #[test] 44 | fn fib_cache_result() { 45 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 46 | for (i, expect) in values.iter().enumerate() { 47 | assert_eq!(*expect, dp::fib::fib_cache_result(i)); 48 | } 49 | } 50 | 51 | #[test] 52 | fn fib_classic_iteration_loop() { 53 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 54 | for (i, expect) in values.iter().enumerate() { 55 | assert_eq!(*expect, dp::fib::fib_classic_iteration_loop(i)); 56 | } 57 | } 58 | 59 | #[test] 60 | fn fib_classic_iteration_for() { 61 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 62 | for (i, expect) in values.iter().enumerate() { 63 | assert_eq!(*expect, dp::fib::fib_classic_iteration_for(i)); 64 | } 65 | } 66 | 67 | #[test] 68 | fn fib_classic_recursive_c() { 69 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 70 | for (i, expect) in values.iter().enumerate() { 71 | assert_eq!(*expect, unsafe { dp::fib::fib_cache_result_c(i) }); 72 | } 73 | } 74 | 75 | #[test] 76 | fn fib_classic_iteration_for_c() { 77 | let values = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 78 | for (i, expect) in values.iter().enumerate() { 79 | assert_eq!(*expect, unsafe { dp::fib::fib_classic_iteration_for_c(i) }); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/graph/mst/mod.rs: -------------------------------------------------------------------------------- 1 | //! 2 | //! MST Definition 3 | //! Recall that a spanning tree of a graph is a connected subgraph 4 | //! with no cycles that includes all the vertices. 5 | //! A minimum spanning tree (MST) of an edge-weighted graph is a 6 | //! spanning tree whose weight (the sum of the weights of its edges) 7 | //! is no larger than the weight of any other spanning tree. 8 | //! 9 | //! Assumptions 10 | //! The graph is connected 11 | //! The edge weights are not necessarily distances 12 | //! The edge weights may be zero or negative 13 | //! The edge weights are all different. 14 | //! 15 | //! Definition 16 | //! A cut of a graph is a partition of its vertices into two nonempty 17 | //! disjoint sets. A crossing edge of a cut is an edge that connects 18 | //! a vertex in one set with a vertex in the other. 19 | //! 20 | //! Proposition J. 21 | //! (Cut property) Given any cut in an edge weighted graph, the crossing 22 | //! edge of minimum weight is in the MST of the graph. 23 | //! 24 | //! Proposition K. 25 | //! (Greedy MST algorithm) The following method colors black all edges in 26 | //! the the MST of any connected edge weighted graph with V vertices: 27 | //! starting with all edges colored gray, find a cut with no black edges, 28 | //! color its minimum-weight edge black, and continue until V - 1 edges 29 | //! have been colored black. 30 | //! 31 | 32 | mod edge; 33 | mod ew_graph; 34 | mod kruskal_mst; 35 | mod lazy_prim_mst; 36 | mod prim_mst; 37 | 38 | use crate::ll::linked_list::Iter; 39 | pub use edge::Edge; 40 | pub use ew_graph::EWGraph; 41 | pub use kruskal_mst::KruskalMST; 42 | pub use lazy_prim_mst::LazyPrimMST; 43 | pub use prim_mst::PrimMST; 44 | 45 | pub trait MST { 46 | /// Returns the edges in a minimum spanning tree (or forest) 47 | fn edges(&self) -> Iter<'_, Edge>; 48 | /// Returns the sum of the edge weights in a minimum spanning tree (or forest) 49 | fn weight(&self) -> f32; 50 | } 51 | 52 | /// Edge weighted graph 53 | pub trait IEWGraph { 54 | /// number of vertices 55 | #[allow(non_snake_case)] 56 | fn V(&self) -> usize; 57 | 58 | /// number of edges 59 | #[allow(non_snake_case)] 60 | fn E(&self) -> usize; 61 | 62 | /// Adds the undirected edge e to this edge-weighted graph 63 | fn add_edge(&mut self, v: usize, w: usize, weight: f32); 64 | 65 | /// Returns the edges incident on vertex v 66 | fn adj(&self, v: usize) -> Iter<'_, Edge>; 67 | 68 | /// Returns all edges in this edge-weighted graph 69 | fn edges(&self) -> Vec; 70 | 71 | /// Returns the degree of vertex v 72 | fn degree(&self, v: usize) -> usize; 73 | } 74 | -------------------------------------------------------------------------------- /tests/test_common_heap.rs: -------------------------------------------------------------------------------- 1 | use algo::common::max_heap; 2 | 3 | #[test] 4 | fn heapify() { 5 | //verify empty ok 6 | let mut t: Vec = vec![]; 7 | let expect: Vec = vec![]; 8 | max_heap::heapify(&mut t, 1); 9 | assert_eq!(t, expect, "t = {:?}, expect = {:?}", t, expect); 10 | 11 | //normal 12 | let t = vec![16, 4, 10, 14, 7, 9, 3, 2, 8, 1]; 13 | let expect = vec![16, 14, 10, 8, 7, 9, 3, 2, 4, 1]; 14 | let mut tt = t.clone(); 15 | max_heap::heapify(&mut tt, 1); 16 | assert_eq!(tt, expect, "t = {:?}, expect = {:?}", t, expect); 17 | } 18 | 19 | #[test] 20 | fn build_heap() { 21 | //verify empty ok 22 | let mut t: Vec = vec![]; 23 | let expect: Vec = vec![]; 24 | max_heap::build_heap(&mut t); 25 | assert_eq!(t, expect, "t = {:?}, expect = {:?}", t, expect); 26 | 27 | //normal 28 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 29 | let expect = vec![16, 14, 10, 8, 7, 9, 3, 2, 4, 1]; 30 | let mut tt = t.clone(); 31 | max_heap::build_heap(&mut tt); 32 | assert_eq!(tt, expect, "t = {:?}, expect = {:?}", t, expect) 33 | } 34 | 35 | #[test] 36 | fn pop() { 37 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 38 | let mut heap = max_heap::BinaryHeap::new(t); 39 | for v in vec![16, 14, 10, 9, 8, 7, 4, 3, 2, 1] { 40 | assert_eq!(heap.pop(), Some(v)); 41 | } 42 | assert_eq!(heap.pop(), None); 43 | } 44 | 45 | #[test] 46 | fn set() { 47 | //only 1 48 | let t = vec![10]; 49 | let mut heap = max_heap::BinaryHeap::new(t); 50 | // data layout: 51 | // vec![10]; 52 | heap.set(0, 100); 53 | let data = heap.keys_slice(); 54 | assert_eq!(data, vec![100]); 55 | 56 | //set fail 57 | let t = vec![10]; 58 | let mut heap = max_heap::BinaryHeap::new(t); 59 | // data layout: 60 | // vec![10]; 61 | heap.set(0, 9); 62 | let data = heap.keys_slice(); 63 | assert_eq!(data, vec![10]); 64 | 65 | //normal 66 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 67 | let mut heap = max_heap::BinaryHeap::new(t); 68 | // data layout: 69 | // vec![16, 14, 10, 8, 7, 9, 3, 2, 4, 1]; 70 | heap.set(3, 100); 71 | let data = heap.keys_slice(); 72 | assert_eq!(data, vec![100, 16, 10, 14, 7, 9, 3, 2, 4, 1]) 73 | } 74 | 75 | #[test] 76 | fn insert() { 77 | //normal 78 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 79 | let mut heap = max_heap::BinaryHeap::new(t); 80 | // data layout: 81 | // vec![16, 14, 10, 8, 7, 9, 3, 2, 4, 1]; 82 | heap.insert(100); 83 | let data = heap.keys_slice(); 84 | assert_eq!(data, vec![100, 16, 10, 8, 14, 9, 3, 2, 4, 1, 7]) 85 | } 86 | -------------------------------------------------------------------------------- /src/graph/undirected/cc.rs: -------------------------------------------------------------------------------- 1 | //! The CC represents a data type for 2 | //! determining the connected components in an undirected graph. 3 | //! The *id* operation determines in which connected component 4 | //! a given vertex lies; the *connected* operation 5 | //! determines whether two vertices are in the same connected component; 6 | //! the *count* operation determines the number of connected 7 | //! components; and the *size* operation determines the number 8 | //! of vertices in the connect component containing a given vertex. 9 | //! 10 | //! The component identifier of a connected component is one of the 11 | //! vertices in the connected component: two vertices have the same component 12 | //! identifier if and only if they are in the same connected component. 13 | //! 14 | //! This implementation uses a recursive DFS. To avoid needing 15 | //! a potentially very large stack size, replace with a non recursive 16 | //! DFS ala NonRecursiveDFS 17 | 18 | use crate::graph::IGraph; 19 | 20 | /// Connected components 21 | pub struct CC { 22 | count: usize, // number of connected components 23 | marked: Vec, // marked[v] = has vertex v been marked? 24 | id: Vec, // id[v] = id of connected component containing v 25 | size: Vec, // size[id] = number of vertices in given component 26 | } 27 | 28 | impl CC { 29 | pub fn new(g: &dyn IGraph) -> Self { 30 | let mut cc = Self { 31 | count: 0, 32 | marked: vec![false; g.V()], 33 | id: vec![0; g.V()], 34 | size: vec![0; g.V()], 35 | }; 36 | 37 | for v in 0..g.V() { 38 | if !cc.marked[v] { 39 | cc.dfs(g, v); 40 | cc.count += 1; 41 | } 42 | } 43 | 44 | cc 45 | } 46 | 47 | /// are v and w connected? 48 | pub fn connected(&self, v: usize, w: usize) -> bool { 49 | self.id[v] == self.id[w] 50 | } 51 | 52 | /// number of connected components 53 | pub fn count(&self) -> usize { 54 | self.count 55 | } 56 | 57 | /// component identifier for v 58 | /// ( between 0 and count()-1 ) 59 | pub fn id(&self, v: usize) -> usize { 60 | self.id[v] 61 | } 62 | 63 | /// Returns the number of vertices in the connected component containing vertex *v*. 64 | pub fn size(&self, v: usize) -> usize { 65 | self.size[self.id[v]] 66 | } 67 | } 68 | 69 | impl CC { 70 | fn dfs(&mut self, g: &dyn IGraph, v: usize) { 71 | self.marked[v] = true; 72 | self.id[v] = self.count; 73 | self.size[self.count] += 1; 74 | for &w in g.adj(v) { 75 | if !self.marked[w] { 76 | self.dfs(g, w); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /benches/strings.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | #![allow(non_snake_case)] 3 | extern crate test; 4 | 5 | use algo::common; 6 | use algo::strings::{brute_force, Quick3String, KMP, LSD, MSD}; 7 | use test::Bencher; 8 | 9 | const WORDS3: &'static str = include_str!("../res/strings/words3.txt"); 10 | const SHELLS: &'static str = include_str!("../res/strings/shells.txt"); 11 | 12 | #[bench] 13 | fn sort_str_std_Vec(b: &mut Bencher) { 14 | let i = WORDS3; 15 | let mut words = extract_words(i); 16 | b.iter(|| { 17 | words.sort(); 18 | }); 19 | } 20 | 21 | #[bench] 22 | fn sort_i32_std_Vec(b: &mut Bencher) { 23 | let mut nums: Vec = (0..1000).rev().collect(); 24 | b.iter(|| { 25 | nums.sort(); 26 | }); 27 | } 28 | 29 | #[bench] 30 | fn sort_str_LSD_radix(b: &mut Bencher) { 31 | let i = WORDS3; 32 | let mut words = extract_words(i); 33 | let w = words[0].len(); 34 | b.iter(|| { 35 | LSD::sort(&mut words, w); 36 | }); 37 | } 38 | 39 | #[bench] 40 | fn sort_i32_LSD_radix(b: &mut Bencher) { 41 | let mut nums: Vec = (0..1000).rev().collect(); 42 | b.iter(|| { 43 | LSD::sort_i32(&mut nums); 44 | }); 45 | } 46 | 47 | #[bench] 48 | fn sort_str_MSD_radix(b: &mut Bencher) { 49 | let i = SHELLS; 50 | let mut words = extract_words(i); 51 | b.iter(|| { 52 | MSD::sort(&mut words); 53 | }); 54 | } 55 | 56 | #[bench] 57 | fn sort_str_quick3strings(b: &mut Bencher) { 58 | let i = SHELLS; 59 | let mut words = extract_words(i); 60 | b.iter(|| { 61 | Quick3String::sort(&mut words); 62 | }); 63 | } 64 | 65 | #[bench] 66 | fn MSD_worst_case(b: &mut Bencher) { 67 | // examines just 1 char to distinguish among the keys 68 | let mut words = vec!["1DNB377"; 26]; 69 | b.iter(|| { 70 | MSD::sort(&mut words); 71 | }); 72 | } 73 | 74 | #[bench] 75 | fn MSD_best_case(b: &mut Bencher) { 76 | // all strings equal, need check all chars 77 | let words = common::util::vec_alphabet("1DNB377".len()); 78 | let mut words: Vec<&str> = words.iter().map(|it| it.as_str()).collect(); 79 | b.iter(|| { 80 | MSD::sort(&mut words); 81 | }); 82 | } 83 | 84 | #[bench] 85 | fn sub_search_kmp(b: &mut Bencher) { 86 | let mut pat = "A".repeat(10); 87 | pat.push('B'); 88 | let txt = "A".repeat(10000); 89 | let kmp = KMP::from(pat.as_str()); 90 | b.iter(|| kmp.search(txt.as_str())); 91 | } 92 | 93 | #[bench] 94 | fn sub_search_brute_force(b: &mut Bencher) { 95 | // worst case for brute force search 96 | let mut pat = "A".repeat(10); 97 | pat.push('B'); 98 | let txt = "A".repeat(10000); 99 | b.iter(|| brute_force::search1(pat.as_str(), txt.as_str())); 100 | } 101 | 102 | fn extract_words(i: &str) -> Vec<&str> { 103 | i.split_whitespace().collect() 104 | } 105 | -------------------------------------------------------------------------------- /src/graph/undirected/cycle.rs: -------------------------------------------------------------------------------- 1 | //! The Cycle represents a data type for 2 | //! determining whether an undirected graph has a simple cycle. 3 | //! The *has_cycle* operation determines whether the graph has 4 | //! a cycle and, if so, the *cycle* operation returns one. 5 | 6 | use crate::common::Stack; 7 | use crate::graph::IGraph; 8 | use crate::ll::linked_list::Iter; 9 | 10 | pub struct Cycle { 11 | marked: Vec, 12 | cycle: Option>, 13 | edge_to: Vec, 14 | } 15 | 16 | impl Cycle { 17 | pub fn new(g: &dyn IGraph) -> Self { 18 | let mut cycle = Self { 19 | marked: vec![false; g.V()], 20 | cycle: None, 21 | edge_to: vec![0; g.V()], 22 | }; 23 | 24 | if !cycle.has_parallel_edges(g) { 25 | for s in 0..g.V() { 26 | if !cycle.marked[s] { 27 | cycle.dfs(g, s, s); 28 | } 29 | } 30 | } 31 | 32 | cycle 33 | } 34 | 35 | /// Returns true if the graph G has a cycle. 36 | pub fn has_cycle(&self) -> bool { 37 | self.cycle.is_some() 38 | } 39 | 40 | /// Returns a cycle in the graph G. 41 | pub fn cycle(&self) -> Option> { 42 | self.cycle.as_ref().map(|v| v.iter()) 43 | } 44 | } 45 | 46 | impl Cycle { 47 | fn dfs(&mut self, g: &dyn IGraph, v: usize, u: usize) { 48 | self.marked[v] = true; 49 | for &w in g.adj(v) { 50 | // short circuit if cycle already found 51 | if self.cycle.is_some() { 52 | return; 53 | } 54 | 55 | if !self.marked[w] { 56 | self.edge_to[w] = v; 57 | self.dfs(g, w, v); 58 | } else if w != u { 59 | let mut cycle = Stack::default(); 60 | let mut x = v; 61 | while x != w { 62 | cycle.push(x); 63 | x = self.edge_to[x]; 64 | } 65 | cycle.push(w); 66 | cycle.push(v); 67 | self.cycle = Some(cycle); 68 | } 69 | } 70 | } 71 | 72 | // does this graph have two parallel edges? 73 | fn has_parallel_edges(&mut self, graph: &dyn IGraph) -> bool { 74 | self.marked.fill(false); 75 | 76 | for v in 0..graph.V() { 77 | for &w in graph.adj(v) { 78 | if self.marked[w] { 79 | let mut cycle = Stack::default(); 80 | cycle.push(v); 81 | cycle.push(w); 82 | cycle.push(v); 83 | self.cycle = Some(cycle); 84 | return true; 85 | } 86 | self.marked[w] = true; 87 | } 88 | 89 | // reset so marked[v] = false for all v 90 | self.marked.fill(false); 91 | } 92 | 93 | false 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/graph/undirected/bipartite.rs: -------------------------------------------------------------------------------- 1 | use crate::common::Stack; 2 | use crate::graph::IGraph; 3 | 4 | /// 双色问题 5 | /// Can the vertices of a given graph be assigned one of two colors 6 | /// in such a way that no edge connects vertices of the same color? 7 | /// which is equivalent to this question: Is the graph bipartite ? 8 | /// 能够用两种颜色将图的所有顶点着色,使得任意一条边的两个端点的颜色都不相同吗? 9 | /// 这个问题也等价于:这是一幅二分图吗? 10 | /// 11 | /// bipartite example: 12 | /// file movies.txt, from the Internet Movie Database (IMDB), 13 | /// Recall that this file consists of lines listing a movie name followed 14 | /// by a list of the performers in the movie. In the context of graph processing, 15 | /// we can view it as defining a graph with movies and performers as vertices and 16 | /// each line defining the adjacency list of edges connect- ing each movie to its 17 | /// performers. 18 | /// Note that the graph is a bipartite graph—there are no edges connecting 19 | /// performers to performers or movies to movies. 20 | pub struct Bipartite { 21 | marked: Vec, 22 | color: Vec, 23 | edge_to: Vec, 24 | cycle: Option>, 25 | is_bipartite: bool, 26 | } 27 | 28 | impl Bipartite { 29 | pub fn new(g: &dyn IGraph) -> Self { 30 | let mut tc = Self { 31 | marked: vec![false; g.V()], 32 | color: vec![false; g.V()], 33 | edge_to: vec![0; g.V()], 34 | cycle: None, 35 | is_bipartite: true, 36 | }; 37 | 38 | for s in 0..g.V() { 39 | if !tc.marked[s] { 40 | tc.dfs(g, s); 41 | } 42 | } 43 | 44 | tc 45 | } 46 | 47 | pub fn is_bipartite(&self) -> bool { 48 | self.is_bipartite 49 | } 50 | 51 | /// Returns the side of the bipartite that vertex v is on. 52 | pub fn color(&self, v: usize) -> bool { 53 | if !self.is_bipartite { 54 | panic!("graph is not bipartite"); 55 | } 56 | self.color[v] 57 | } 58 | } 59 | 60 | impl Bipartite { 61 | fn dfs(&mut self, g: &dyn IGraph, v: usize) { 62 | self.marked[v] = true; 63 | for &w in g.adj(v) { 64 | // short circuit if odd-length cycle found 65 | if self.cycle.is_some() { 66 | return; 67 | } 68 | 69 | if !self.marked[w] { 70 | self.edge_to[w] = v; 71 | self.color[w] = !self.color[v]; 72 | self.dfs(g, w); 73 | } else if self.color[w] == self.color[v] { 74 | self.is_bipartite = false; 75 | let mut cycle = Stack::default(); 76 | cycle.push(w); 77 | let mut x = v; 78 | while x != w { 79 | cycle.push(x); 80 | x = self.edge_to[x]; 81 | } 82 | cycle.push(w); 83 | self.cycle = Some(cycle); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/test_sort.rs: -------------------------------------------------------------------------------- 1 | #![feature(is_sorted)] 2 | 3 | use algo::common; 4 | use algo::sort; 5 | 6 | macro_rules! case { 7 | // to test fn is "sort::$p::sort" 8 | // testcase name is "fn $p()" 9 | ($p: ident) => { 10 | #[test] 11 | fn $p() { 12 | let mut data = gen_vec_data(); 13 | for t in data.iter_mut() { 14 | sort::$p::sort(t); 15 | assert!(t.is_sorted()); 16 | } 17 | } 18 | }; 19 | // to test fn is "sort::$p::$f" 20 | // testcase name is "fn $f()" 21 | ($p: ident, $f: ident) => { 22 | #[test] 23 | fn $f() { 24 | let mut data = gen_vec_data(); 25 | for t in data.iter_mut() { 26 | sort::$p::$f(t); 27 | assert!(t.is_sorted()); 28 | } 29 | } 30 | }; 31 | } 32 | 33 | case!(bubble); 34 | case!(insert); 35 | case!(selection); 36 | case!(selection, sort_cocktail); 37 | case!(quick); 38 | case!(shell); 39 | case!(floyd); 40 | 41 | #[test] 42 | fn insert_sort_dth() { 43 | let mut data = common::util::vec_alphabet(1); 44 | common::util::shuffle(&mut data); 45 | let len = data.len(); 46 | sort::insert::sort_dth(&mut data, 0, len - 1, 0); 47 | assert!(data.is_sorted()); 48 | 49 | // 0-th char equal 50 | let mut data = vec!["af", "ae", "ad", "ac", "ab", "aa"]; 51 | let len = data.len(); 52 | sort::insert::sort_dth(&mut data, 0, len - 1, 0); 53 | assert!(data.is_sorted()); 54 | 55 | // length 56 | let mut data = vec!["aaaaaa", "aaaaa", "aaaa", "aaa", "aa", "a"]; 57 | let len = data.len(); 58 | sort::insert::sort_dth(&mut data, 0, len - 1, 0); 59 | assert!(data.is_sorted()); 60 | } 61 | 62 | #[test] 63 | fn tournament_tree() { 64 | let mut data = gen_vec_data(); 65 | for t in data.iter_mut() { 66 | let t = sort::tree_selection::sort_desc(t); 67 | assert!(t.iter().rev().is_sorted()); 68 | } 69 | } 70 | 71 | #[test] 72 | fn merge() { 73 | let mut data = gen_vec_data(); 74 | for t in data.iter_mut() { 75 | let t = sort::merge::v1::sort(t); 76 | assert!(t.is_sorted()); 77 | } 78 | 79 | let mut data = gen_vec_data(); 80 | for t in data.iter_mut() { 81 | sort::merge::v2::sort(t); 82 | assert!(t.is_sorted()); 83 | } 84 | 85 | let mut data = gen_vec_data(); 86 | for t in data.iter_mut() { 87 | sort::merge::v3::sort(t); 88 | assert!(t.is_sorted()); 89 | } 90 | } 91 | 92 | // utils 93 | 94 | fn gen_vec_data() -> Vec> { 95 | let sorted: Vec = (1..100).collect(); 96 | let mut unsorted = sorted.clone(); 97 | common::util::shuffle(&mut unsorted); 98 | 99 | vec![ 100 | //empty 101 | vec![], 102 | //only 1 103 | vec![1], 104 | sorted, 105 | unsorted, 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /src/graph/mst/ew_graph.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::mst::Edge; 2 | use crate::graph::util::parser::GraphDataParser; 3 | use crate::graph::IEWGraph; 4 | use crate::ll::linked_list::Iter; 5 | use crate::ll::LinkedList; 6 | use std::cmp::Ordering; 7 | 8 | /// The EWGraph class represents an edge-weighted 9 | /// graph of vertices named 0 through V – 1, where each 10 | /// undirected edge is of type Edge and has a real-valued weight. 11 | /// It supports the following two primary operations: add an edge to the graph, 12 | /// iterate over all of the edges incident to a vertex. It also provides 13 | /// methods for returning the degree of a vertex, the number of vertices 14 | /// V in the graph, and the number of edges E in the graph. 15 | /// Parallel edges and self-loops are permitted. 16 | /// By convention, a self-loop v-v appears in the 17 | /// adjacency list of v twice and contributes two to the degree 18 | /// of v. 19 | pub struct EWGraph { 20 | nv: usize, 21 | ne: usize, 22 | adj: Vec>, 23 | } 24 | 25 | impl IEWGraph for EWGraph { 26 | fn V(&self) -> usize { 27 | self.nv 28 | } 29 | 30 | fn E(&self) -> usize { 31 | self.ne 32 | } 33 | 34 | fn add_edge(&mut self, v: usize, w: usize, weight: f32) { 35 | let e = Edge::new(v, w, weight); 36 | self.adj[v].push_front(e); 37 | self.adj[w].push_front(e); 38 | self.ne += 1; 39 | } 40 | 41 | fn adj(&self, v: usize) -> Iter<'_, Edge> { 42 | self.adj[v].iter() 43 | } 44 | 45 | fn edges(&self) -> Vec { 46 | let mut list = Vec::new(); 47 | for v in 0..self.V() { 48 | let mut self_loops = 0; 49 | for e in self.adj(v) { 50 | match e.other(v).cmp(&v) { 51 | Ordering::Greater => list.push(*e), 52 | Ordering::Equal => { 53 | // add only one copy of each self loop (self loops will be consecutive) 54 | // add_edge(v, v, weighted), add_edge实现,加入两个edge 55 | if self_loops % 2 == 0 { 56 | list.push(*e); 57 | } 58 | self_loops += 1; 59 | } 60 | Ordering::Less => (), 61 | } 62 | } 63 | } 64 | list 65 | } 66 | 67 | fn degree(&self, v: usize) -> usize { 68 | self.adj[v].len() 69 | } 70 | } 71 | 72 | impl From for EWGraph { 73 | fn from(nv: usize) -> Self { 74 | let mut adj = Vec::with_capacity(nv); 75 | for _ in 0..nv { 76 | adj.push(LinkedList::default()); 77 | } 78 | 79 | Self { nv, ne: 0, adj } 80 | } 81 | } 82 | 83 | impl From<&str> for EWGraph { 84 | fn from(s: &str) -> Self { 85 | let parser = GraphDataParser::parse(s, true).unwrap(); 86 | let mut g = Self::from(parser.get_v()); 87 | for (v, w, weight) in parser.get_weighted_edges() { 88 | g.add_edge(*v, *w, *weight); 89 | } 90 | debug_assert!(g.E() == parser.get_e()); 91 | g 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tests/test_linked_list.rs: -------------------------------------------------------------------------------- 1 | use algo::ll::{self, LinkedList}; 2 | 3 | #[test] 4 | fn normal() { 5 | let data = vec![1, 2, 3, 4, 5]; 6 | let ll = create_ll(&data); 7 | 8 | //len 9 | assert_eq!(ll.len(), data.len()); 10 | 11 | //verify data 12 | let ll_data: Vec = ll.into_iter().collect(); 13 | assert_eq!(ll_data, data); 14 | } 15 | 16 | #[test] 17 | fn push_front() { 18 | let mut data = vec![1, 2, 3, 4, 5]; 19 | let mut ll = LinkedList::default(); 20 | for &v in &data { 21 | ll.push_front(v); 22 | } 23 | 24 | //len 25 | assert_eq!(ll.len(), data.len()); 26 | 27 | //verify data 28 | let ll_data: Vec = ll.into_iter().collect(); 29 | data.reverse(); 30 | assert_eq!(ll_data, data); 31 | } 32 | 33 | #[test] 34 | fn reverse() { 35 | let mut data = vec![1, 2, 3, 4, 5]; 36 | let mut ll = create_ll(&data); 37 | 38 | //reverse 39 | data.reverse(); 40 | ll.reverse(); 41 | assert_eq!(ll.first(), data.first()); 42 | assert_eq!(ll.last(), data.last()); 43 | let ll_data: Vec = ll.into_iter().collect(); 44 | assert_eq!(ll_data, data); 45 | } 46 | 47 | #[test] 48 | fn find_kth2tail() { 49 | let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; 50 | let ll = create_ll(&data); 51 | 52 | let p = ll::kth2tail::find(&ll, 2); 53 | assert_eq!(unsafe { p.unwrap().as_ref().element }, 8); 54 | 55 | let p = ll::kth2tail::find(&ll, 5); 56 | assert_eq!(unsafe { p.unwrap().as_ref().element }, 5); 57 | 58 | let p = ll::kth2tail::find(&ll, 10); 59 | assert_eq!(p, None); 60 | } 61 | 62 | #[test] 63 | fn drop_clear() { 64 | use algo::common::drop::{self, Elem}; 65 | drop::with(|ctx| { 66 | let mut ll = LinkedList::default(); 67 | ll.push_back(Elem); 68 | ll.push_front(Elem); 69 | ll.push_back(Elem); 70 | ll.push_front(Elem); 71 | drop(ll); 72 | assert_eq!(4, ctx.get()); 73 | }); 74 | } 75 | 76 | #[test] 77 | fn drop_clear_with_reverse() { 78 | use algo::common::drop::{self, Elem}; 79 | drop::with(|ctx| { 80 | let mut ll = LinkedList::default(); 81 | ll.push_back(Elem); 82 | ll.push_front(Elem); 83 | ll.push_back(Elem); 84 | ll.push_front(Elem); 85 | ll.reverse(); // do reverse 86 | drop(ll); 87 | assert_eq!(4, ctx.get()); 88 | }) 89 | } 90 | 91 | #[test] 92 | fn drop_with_pop() { 93 | use algo::common::drop::{self, Elem}; 94 | drop::with(|ctx| { 95 | let mut ll = LinkedList::default(); 96 | ll.push_back(Elem); 97 | ll.push_front(Elem); 98 | ll.push_back(Elem); 99 | ll.push_front(Elem); 100 | 101 | // do pop, and drop Elem 102 | drop(ll.pop_front()); 103 | drop(ll.pop_front()); 104 | assert_eq!(2, ctx.get()); 105 | 106 | drop(ll); 107 | assert_eq!(4, ctx.get()); 108 | }); 109 | } 110 | 111 | fn create_ll(data: &[T]) -> LinkedList 112 | where 113 | T: Copy, 114 | { 115 | let mut ll = LinkedList::default(); 116 | for v in data { 117 | ll.push_back(*v); 118 | } 119 | ll 120 | } 121 | -------------------------------------------------------------------------------- /src/graph/shortest/arbitrage.rs: -------------------------------------------------------------------------------- 1 | //! Proposition Z. 2 | //! The arbitrage problem is a negative-cycle-detection problem 3 | //! in edge-weighted digraphs. 4 | //! 5 | //! Proof: 6 | //! Replace each weight by its logarithm, negated. With this change, 7 | //! computing path weights by multiplying edge weights in the original 8 | //! problem corresponds to adding them in the transformed problem. 9 | //! Specifically, any product w1w2 . . . wk corresponds to a sum 10 | //! - ln(w1) - ln(w2) - . . . - ln(wk). The transformed edge weights 11 | //! might be negative or positive, a path from v to w gives a way of 12 | //! converting from currency v to currency w, and any negative cycle 13 | //! is an arbitrage opportunity. 14 | 15 | use crate::graph::shortest::{BellmanFordSP, DirectedEdge, EWDigraph}; 16 | use crate::graph::IEWDigraph; 17 | 18 | /// The Arbitrage provides a client that finds an arbitrage 19 | /// opportunity in a currency exchange table by constructing a 20 | /// complete-digraph representation of the exchange table and then finding 21 | /// a negative cycle in the digraph. 22 | /// This implementation uses the Bellman-Ford algorithm to find a 23 | /// negative cycle in the complete digraph. 24 | pub struct Arbitrage<'a> { 25 | names: Vec<&'a str>, 26 | cycle: Option>, // negative cycle (or null if no such cycle) 27 | } 28 | 29 | impl<'a> Arbitrage<'a> { 30 | pub fn has_opportunity(&self) -> bool { 31 | self.cycle.is_some() 32 | } 33 | 34 | pub fn opportunity_cycle(&self) -> Option> { 35 | self.cycle.as_ref().map(|cycle| { 36 | cycle 37 | .iter() 38 | .map(|v| { 39 | let from = self.names[v.from()]; 40 | let to = self.names[v.to()]; 41 | (from, to, (-v.weight()).exp()) 42 | }) 43 | .collect() 44 | }) 45 | } 46 | 47 | pub fn calc(&self, stake: f32) -> Option { 48 | self.cycle 49 | .as_ref() 50 | .map(|cycle| cycle.iter().fold(stake, |acc, e| acc * (-e.weight()).exp())) 51 | } 52 | } 53 | 54 | impl<'a> std::convert::TryFrom<&'a str> for Arbitrage<'a> { 55 | type Error = (); 56 | 57 | fn try_from(s: &'a str) -> Result { 58 | use crate::graph::util::parser; 59 | 60 | let mut lines = s.lines(); 61 | 62 | // line0: V 63 | let s = lines.next().ok_or(())?; 64 | let (_, nv) = parser::parse_num::(s).ok().ok_or(())?; 65 | 66 | let mut g: Box = Box::new(EWDigraph::from(nv)); 67 | let mut names = Vec::with_capacity(nv); 68 | // line1...: rates 69 | for v in 0..nv { 70 | let s = lines.next().ok_or(())?; 71 | let (_, (name, rates)) = parser::parse_list_rates(s).ok().ok_or(())?; 72 | debug_assert_eq!(nv, rates.len()); 73 | names.push(name); 74 | for (w, rate) in rates.iter().enumerate() { 75 | // ln() is natural logarithm (base e) 76 | g.add_edge(v, w, -rate.ln()); 77 | } 78 | } 79 | 80 | let spt = BellmanFordSP::new(g.as_ref(), 0); 81 | let cycle = spt.negative_cycle().map(|c| c.cloned().collect()); 82 | Ok(Self { names, cycle }) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/tree/binary/builder/level.rs: -------------------------------------------------------------------------------- 1 | //! 按层建立tree 2 | //! For example: Given binary tree {1,#,2,3}, 3 | //! 1 4 | //! \ 5 | //! 2 6 | //! / 7 | //! 3 8 | 9 | use crate::common::binary_tree; 10 | use crate::tree::binary::builder::TreeBuilder; 11 | use crate::tree::binary::node::Node; 12 | use crate::tree::binary::tree::Tree; 13 | use std::ptr::NonNull; 14 | 15 | pub trait BuildTreeInLevel { 16 | fn build_in_level(vec: &[&str]) -> Tree; 17 | } 18 | 19 | impl BuildTreeInLevel for TreeBuilder { 20 | fn build_in_level(vec: &[&str]) -> Tree { 21 | build(vec) 22 | } 23 | } 24 | 25 | // ?? why K: std::str::FromStr 26 | fn build(vec: &[&str]) -> Tree { 27 | let tokens = expand_sharp(vec); 28 | let mut tree = Tree::default(); 29 | let mut tree_size = 0; 30 | // Binary Tree in array 31 | let mut aux: Vec>>> = Vec::new(); 32 | for (i, &token) in tokens.iter().enumerate() { 33 | let node = token.parse().map(Node::new_key).ok(); 34 | aux.push(node); 35 | 36 | if node.is_some() { 37 | tree_size += 1; 38 | } 39 | 40 | if i == 0 { 41 | tree.root = node; 42 | continue; 43 | } 44 | 45 | if let Some(mut node) = node { 46 | unsafe { 47 | let parent = binary_tree::parent(i); 48 | let mut parent_node = aux[parent].unwrap(); 49 | node.as_mut().parent = Some(parent_node); 50 | if binary_tree::left(parent) == i { 51 | parent_node.as_mut().left = Some(node); 52 | } else { 53 | parent_node.as_mut().right = Some(node); 54 | } 55 | } 56 | } 57 | } 58 | 59 | tree.set_size(tree_size); 60 | 61 | tree 62 | } 63 | 64 | // "#" symbol as empty child 65 | fn expand_sharp<'a>(vec: &[&'a str]) -> Vec<&'a str> { 66 | let mut results = Vec::new(); 67 | 68 | for &v in vec.iter() { 69 | // root 70 | if results.is_empty() { 71 | results.push(v); 72 | continue; 73 | } 74 | 75 | // child 76 | if v == "#" { 77 | results.push(v); 78 | } else { 79 | // child 80 | loop { 81 | // new child idx 82 | let idx = results.len(); 83 | let parent = results[binary_tree::parent(idx)]; 84 | if parent == "#" { 85 | // if parent is "#", children are "#", 86 | // so just push "#" 87 | results.push(parent); 88 | } else { 89 | results.push(v); 90 | break; 91 | } 92 | } 93 | } 94 | } 95 | 96 | results 97 | } 98 | 99 | #[test] 100 | fn t_expand_sharp() { 101 | for (tokens, expect) in vec![ 102 | (vec!["1", "#", "2", "3"], vec!["1", "#", "2", "#", "#", "3"]), 103 | ( 104 | vec!["1", "2", "#", "3", "4", "#", "#", "5"], 105 | vec!["1", "2", "#", "3", "4", "#", "#", "5"], 106 | ), 107 | ] { 108 | assert_eq!(expect, expand_sharp(tokens.as_slice())); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/graph/mst/kruskal_mst.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::many_single_char_names)] 2 | 3 | use crate::common::{Queue, UF}; 4 | use crate::graph::mst::{Edge, MST}; 5 | use crate::graph::IEWGraph; 6 | use crate::ll::linked_list::Iter; 7 | 8 | pub struct KruskalMST { 9 | weight: f32, // weight of MST 10 | mst: Queue, // edges in MST 11 | } 12 | 13 | impl KruskalMST { 14 | pub fn new(g: &dyn IEWGraph) -> Self { 15 | let mut edges = g.edges(); 16 | // When applicable, unstable sorting is preferred because it is 17 | // generally faster than stable sorting and it doesn’t allocate 18 | // auxiliary memory. See sort_unstable. 19 | // edges.sort(); 20 | edges.sort_unstable(); // sorted by weight 21 | 22 | let mut mst = Queue::default(); 23 | let mut weight = 0.0; 24 | let mut uf = UF::new(g.V()); 25 | let mut i = 0; 26 | while i < g.E() && mst.len() < g.V() - 1 { 27 | let e = edges[i]; 28 | let v = e.either(); 29 | let w = e.other(v); 30 | 31 | // v-w does not create a cycle 32 | if uf.find(v) != uf.find(w) { 33 | uf.union(v, w); 34 | mst.enqueue(e); 35 | weight += e.weight(); 36 | } 37 | 38 | i += 1; 39 | } 40 | 41 | Self { mst, weight } 42 | } 43 | 44 | pub fn check(&self, g: &dyn IEWGraph) -> Result<(), String> { 45 | // check that it is acyclic 46 | let mut uf = UF::new(g.V()); 47 | for e in self.edges() { 48 | let v = e.either(); 49 | let w = e.other(v); 50 | if uf.find(v) == uf.find(w) { 51 | return Err("Not a forest".to_string()); 52 | } 53 | uf.union(v, w); 54 | } 55 | 56 | // check that it is a spanning forest 57 | for e in g.edges() { 58 | let v = e.either(); 59 | let w = e.other(v); 60 | if uf.find(v) != uf.find(w) { 61 | return Err("Not a spanning forest".to_string()); 62 | } 63 | } 64 | 65 | // check that it is a minimal spanning forest (cut optimality conditions) 66 | for e in self.edges() { 67 | // all edges in MST except e 68 | uf = UF::new(g.V()); 69 | for f in self.edges() { 70 | if f != e { 71 | let x = f.either(); 72 | let y = f.other(x); 73 | uf.union(x, y); 74 | } 75 | } 76 | 77 | // check that e is min weight edge in crossing cut 78 | for f in g.edges() { 79 | let x = f.either(); 80 | let y = f.other(x); 81 | if uf.find(x) != uf.find(y) && f.weight() < e.weight() { 82 | return Err(format!( 83 | "Edge {} violates cut optimality conditions", 84 | f.to_string() 85 | )); 86 | } 87 | } 88 | } 89 | 90 | Ok(()) 91 | } 92 | } 93 | 94 | impl MST for KruskalMST { 95 | fn edges(&self) -> Iter<'_, Edge> { 96 | self.mst.iter() 97 | } 98 | 99 | fn weight(&self) -> f32 { 100 | self.weight 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/common/max_heap.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::many_single_char_names)] 2 | //! 堆 3 | //! 4 | //! 堆可以用于解决很多实际问题,包括排序、带有优先级的调度,实现图算法等等 5 | //! 6 | //! 堆是一种满足如下性质的数据结构: 7 | //! - 顶部(top)总是保存着最小(或最大)的元素 8 | //! - 弹出(pop)操作将顶部元素移除,同时保持堆的性质,新的顶部元素仍然是剩余元素中的最小(或 最大)值 9 | //! - 将新元素插入到堆中仍然保持堆的性质,顶部元素还是所有元素中的最小(或最大)值 10 | //! - 其他操作(例如将两个堆合并),都会保持堆的性质 11 | //! 12 | //! 顶部保存最小元素的堆为最小堆,顶部保存最大元素的堆为最大堆 13 | 14 | use crate::common::binary_tree; 15 | 16 | /// 用数组实现隐式二叉堆 (最大堆) 17 | pub struct BinaryHeap { 18 | keys: Vec, // 索引从0开始 19 | } 20 | 21 | impl BinaryHeap 22 | where 23 | K: Ord, 24 | { 25 | pub fn new(mut keys: Vec) -> Self { 26 | build_heap(&mut keys); 27 | Self { keys } 28 | } 29 | 30 | pub fn pop(&mut self) -> Option { 31 | let len = self.keys.len(); 32 | if len > 0 { 33 | // 从长度为 n 的数组中删除第一个元素需要线性时间 O(n)。 34 | // 这是因为我们需要将所有剩余的元素依次向前移动一个位置。 35 | // 这一操作成为了整个算法的瓶颈,使得算法的复杂度升高了。 36 | // 为了解决这一问题,我们可以交换数组中的第一个和最后一 37 | // 个元素,然后将数组的长度减一。 38 | self.keys.swap(0, len - 1); 39 | let key = self.keys.pop(); 40 | heapify(&mut self.keys, 0); 41 | key 42 | } else { 43 | None 44 | } 45 | } 46 | 47 | pub fn set(&mut self, i: usize, key: K) { 48 | match self.keys.get(i) { 49 | Some(v) if &key >= v => { 50 | self.keys[i] = key; 51 | heap_fix(&mut self.keys, i); 52 | } 53 | _ => (), 54 | } 55 | } 56 | 57 | pub fn insert(&mut self, key: K) { 58 | let i = self.keys.len(); 59 | self.keys.push(key); 60 | heap_fix(&mut self.keys, i); 61 | } 62 | 63 | //for test 64 | pub fn keys_slice(&self) -> &[K] { 65 | self.keys.as_slice() 66 | } 67 | } 68 | 69 | pub fn heapify(keys: &mut [K], mut i: usize) 70 | where 71 | K: Ord, 72 | { 73 | let n = keys.len(); 74 | loop { 75 | let l = binary_tree::left(i); 76 | let r = binary_tree::right(i); 77 | let mut m = i; 78 | 79 | if let Some(v) = keys.get(l) { 80 | if l < n && v >= &keys[m] { 81 | m = l; 82 | } 83 | } 84 | 85 | if let Some(v) = keys.get(r) { 86 | if r < n && v >= &keys[m] { 87 | m = r; 88 | } 89 | } 90 | 91 | if m != i { 92 | keys.swap(i, m); 93 | i = m; 94 | } else { 95 | break; 96 | } 97 | } 98 | } 99 | 100 | pub fn build_heap(keys: &mut [K]) 101 | where 102 | K: Ord, 103 | { 104 | // i以 n / 2作为第一个分支节点,开始构建heap。 105 | // 因为叶子结点,已经满足堆定义,所以从二叉树倒数第二层最后一个节点 106 | // 开始构建,这个分支节点的index,根据等比数列求和公式得到: 107 | // (2 ^ 0 + 2 ^ 1 ... 2 ^ (p - 1) = 2 ^ (p - 1) - 1) 108 | // p为二叉树层数等于log(n) 109 | // index = 2 ^ (p - 1) - 1 = 2 ^ ( log(n) - 1) - 1 <= n / 2 110 | let mut i = keys.len() as i32 / 2; 111 | while i >= 0 { 112 | heapify(keys, i as usize); 113 | i -= 1; 114 | } 115 | } 116 | 117 | // 与heapify的区别: 118 | // heapify 是从i节点开始,调整子树 (向下调整) 119 | // heap_fix 是从i节点开始,调整父节点(向上调整) 120 | fn heap_fix(keys: &mut [K], mut i: usize) 121 | where 122 | K: Ord, 123 | { 124 | while i > 0 { 125 | let parent = binary_tree::parent(i); 126 | if keys[i] >= keys[parent] { 127 | keys.swap(i, parent); 128 | i = parent; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/graph/util/symbol_graph.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::util::parser::parse_list_str; 2 | use crate::graph::IGraph; 3 | use std::collections::HashMap; 4 | 5 | /// Typical applications involve processing graphs defined in files or 6 | /// on web pages, using strings, not integer indices, to define and refer 7 | /// to vertices. To accommodate such applications, we define an input 8 | /// format with the following properties: 9 | /// - Vertex names are strings. 10 | /// - A specified delimiter separates vertex names (to allow for the possibility 11 | /// of spaces in names). 12 | /// - Each line represents a set of edges, connecting the first vertex name on 13 | /// the line to each of the other vertices named on the line. 14 | /// - The number of vertices V and the number of edges E are both implicitly 15 | /// defined. 16 | /// 17 | /// It builds three data structures: 18 | /// - A symbol table st with String keys (vertex names) and int values (indices) 19 | /// - An array keys[] that serves as an inverted index, giving the vertex name 20 | /// associated with each integer index 21 | /// - A Graph G built using the indices to refer to vertices 22 | /// 23 | /// SymbolGraph uses two passes through the data to build these data structures 24 | /// 25 | /// symbol table 26 | /// ST st 27 | /// JFK | 0 28 | /// MCO | 1 29 | /// ORD | 2 30 | /// ... 31 | /// 32 | /// inverted index 33 | /// String[] keys 34 | /// 0 JFK 35 | /// 1 MCO 36 | /// 2 ORD 37 | /// ... 38 | /// 39 | pub struct SymbolGraph<'a> { 40 | st: HashMap<&'a str, usize>, 41 | keys: Vec<&'a str>, 42 | graph: Box, 43 | } 44 | 45 | impl<'a> SymbolGraph<'a> { 46 | /// is key a vertex? 47 | pub fn contains(&self, key: &str) -> bool { 48 | self.st.contains_key(key) 49 | } 50 | 51 | /// index associated with key 52 | pub fn index(&self, key: &str) -> Option { 53 | self.st.get(key).cloned() 54 | } 55 | 56 | /// key associated with index v 57 | pub fn name(&self, v: usize) -> Option<&str> { 58 | self.keys.get(v).cloned() 59 | } 60 | 61 | /// underlying Graph 62 | #[allow(non_snake_case)] 63 | pub fn G(&self) -> &dyn IGraph { 64 | self.graph.as_ref() 65 | } 66 | } 67 | 68 | impl<'a> SymbolGraph<'a> { 69 | /// build graph specified in i using delim to separate vertex names 70 | pub fn new(i: &'a str, sep: &str, ctor: F) -> Self 71 | where 72 | F: FnOnce(usize) -> Box, 73 | { 74 | // First pass 75 | // builds the index, by reading strings to associate each 76 | // distinct string with an index. 77 | let mut st = HashMap::new(); 78 | for l in i.lines() { 79 | if let Ok((_, list)) = parse_list_str(l, sep) { 80 | for v in list { 81 | if st.get(v).is_none() { 82 | st.insert(v, st.len()); 83 | } 84 | } 85 | } 86 | } 87 | 88 | // Inverted index 89 | // to get string keys is an array. 90 | let mut keys = vec![""; st.len()]; 91 | for &name in st.keys() { 92 | keys[*st.get(name).unwrap()] = name; 93 | } 94 | 95 | // Second pass 96 | // builds the graph 97 | let mut g = ctor(st.len()); 98 | for l in i.lines() { 99 | if let Ok((_, list)) = parse_list_str(l, sep) { 100 | let v = st.get(list[0]).unwrap(); 101 | for &s in &list[1..] { 102 | let w = st.get(s).unwrap(); 103 | g.add_edge(*v, *w); 104 | } 105 | } 106 | } 107 | 108 | Self { st, keys, graph: g } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/graph/mst/lazy_prim_mst.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::many_single_char_names)] 2 | 3 | use crate::common::{Queue, PQ, UF}; 4 | use crate::graph::mst::{Edge, MST}; 5 | use crate::graph::IEWGraph; 6 | use crate::ll::linked_list::Iter; 7 | 8 | pub struct LazyPrimMST { 9 | weight: f32, 10 | mst: Queue, 11 | marked: Vec, 12 | pq: PQ, 13 | } 14 | 15 | impl LazyPrimMST { 16 | pub fn new(g: &dyn IEWGraph) -> Self { 17 | let mut mst = Self { 18 | weight: 0.0, 19 | mst: Queue::default(), 20 | marked: vec![false; g.V()], 21 | pq: PQ::new_min_pq(1), 22 | }; 23 | 24 | for v in 0..g.V() { 25 | if !mst.marked[v] { 26 | mst.prim(g, v); 27 | } 28 | } 29 | 30 | mst 31 | } 32 | } 33 | 34 | impl MST for LazyPrimMST { 35 | fn edges(&self) -> Iter<'_, Edge> { 36 | self.mst.iter() 37 | } 38 | 39 | fn weight(&self) -> f32 { 40 | self.weight 41 | } 42 | } 43 | 44 | impl LazyPrimMST { 45 | fn prim(&mut self, g: &dyn IEWGraph, s: usize) { 46 | self.scan(g, s); 47 | while !self.pq.is_empty() { 48 | let e = self.pq.dequeue().unwrap(); 49 | let v = e.either(); 50 | let w = e.other(v); 51 | debug_assert!(self.marked[v] || self.marked[w]); 52 | if self.marked[v] && self.marked[w] { 53 | continue; 54 | } 55 | 56 | self.mst.enqueue(e); 57 | self.weight += e.weight(); 58 | 59 | if !self.marked[v] { 60 | self.scan(g, v); 61 | } 62 | if !self.marked[w] { 63 | self.scan(g, w); 64 | } 65 | } 66 | } 67 | 68 | fn scan(&mut self, g: &dyn IEWGraph, v: usize) { 69 | self.marked[v] = true; 70 | for e in g.adj(v) { 71 | if !self.marked[e.other(v)] { 72 | self.pq.enqueue(*e); 73 | } 74 | } 75 | } 76 | } 77 | 78 | impl LazyPrimMST { 79 | pub fn check(&self, g: &dyn IEWGraph) -> Result<(), String> { 80 | // check that it is acyclic 81 | let mut uf = UF::new(g.V()); 82 | for e in self.edges() { 83 | let v = e.either(); 84 | let w = e.other(v); 85 | if uf.find(v) == uf.find(w) { 86 | return Err("Not a forest".to_string()); 87 | } 88 | uf.union(v, w); 89 | } 90 | 91 | // check that it is a spanning forest 92 | for e in g.edges() { 93 | let v = e.either(); 94 | let w = e.other(v); 95 | if uf.find(v) != uf.find(w) { 96 | return Err("Not a spanning forest".to_string()); 97 | } 98 | } 99 | 100 | // check that it is a minimal spanning forest (cut optimality conditions) 101 | for e in self.edges() { 102 | // all edges in MST except e 103 | uf = UF::new(g.V()); 104 | for f in self.mst.iter() { 105 | if f != e { 106 | let x = f.either(); 107 | let y = f.other(x); 108 | uf.union(x, y); 109 | } 110 | } 111 | 112 | // check that e is min weight edge in crossing cut 113 | for f in g.edges() { 114 | let x = f.either(); 115 | let y = f.other(x); 116 | if uf.find(x) != uf.find(y) && f.weight() < e.weight() { 117 | return Err(format!( 118 | "Edge {} violates cut optimality conditions", 119 | f.to_string() 120 | )); 121 | } 122 | } 123 | } 124 | 125 | Ok(()) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /tests/test_bst_tree.rs: -------------------------------------------------------------------------------- 1 | use algo::tree::binary::bst::BSTree; 2 | use algo::tree::binary::traverse::PreOrderVisitor; 3 | use algo::tree::binary::{bst, Tree}; 4 | 5 | #[test] 6 | fn build_binary_search_tree() { 7 | let mut tree = Tree::default(); 8 | let data = vec![4, 3, 8, 1, 7, 16, 2, 10, 9, 14]; 9 | for v in &data { 10 | tree.insert(*v, *v); 11 | } 12 | let r = unsafe { PreOrderVisitor::iterate(&tree) }; 13 | assert_eq!(r, vec![4, 3, 1, 2, 8, 7, 16, 10, 9, 14]); 14 | 15 | for v in data { 16 | assert!(tree.get(&v).is_some()); 17 | } 18 | assert_eq!(tree.get(&100), None); 19 | } 20 | 21 | #[test] 22 | fn binary_search_tree_min_max() { 23 | let mut tree = Tree::default(); 24 | let data = vec![4, 3, 8, 1, 7, 16, 2, 10, 9, 14]; 25 | for v in &data { 26 | tree.insert(*v, *v); 27 | } 28 | 29 | //min 30 | let v = tree.min(); 31 | assert_eq!(v, Some(&1)); 32 | 33 | //max 34 | let v = tree.max(); 35 | assert_eq!(v, Some(&16)); 36 | } 37 | 38 | #[test] 39 | fn binary_search_tree_succ_pred() { 40 | let mut tree = Tree::default(); 41 | let data = vec![4, 3, 8, 1, 7, 16, 2, 10, 9, 14]; 42 | for v in &data { 43 | tree.insert(*v, *v); 44 | } 45 | 46 | //succ 47 | let v = tree.succ(&8); 48 | assert_eq!(v, Some(&9)); 49 | let v = tree.succ(&2); 50 | assert_eq!(v, Some(&3)); 51 | 52 | //pred 53 | let v = tree.pred(&9); 54 | assert_eq!(v, Some(&8)); 55 | let v = tree.pred(&3); 56 | assert_eq!(v, Some(&2)); 57 | } 58 | 59 | #[test] 60 | fn delete_binary_search_tree() { 61 | let mut tree = Tree::default(); 62 | for v in vec![4, 3, 8, 1, 7, 16, 2, 10, 9, 14] { 63 | tree.insert(v, v); 64 | } 65 | 66 | for (v, expect) in vec![ 67 | (1, vec![4, 3, 2, 8, 7, 16, 10, 9, 14]), 68 | (8, vec![4, 3, 2, 9, 7, 16, 10, 14]), 69 | (4, vec![7, 3, 2, 9, 16, 10, 14]), 70 | ] { 71 | tree.delete(&v); 72 | let r = unsafe { PreOrderVisitor::iterate(&tree) }; 73 | assert_eq!(r, expect); 74 | } 75 | } 76 | 77 | #[test] 78 | fn bst_tree_height() { 79 | // 升序数列,使BST退化成一个linked list 80 | let mut tree = Tree::default(); 81 | for v in 0..100 { 82 | tree.insert(v, v); 83 | } 84 | assert_eq!(tree.height(), 100); 85 | } 86 | 87 | #[test] 88 | fn is_bst() { 89 | let mut tree = Tree::default(); 90 | let data = vec![4, 3, 8, 1, 7, 16, 2, 10, 9, 14]; 91 | for v in &data { 92 | tree.insert(*v, *v); 93 | } 94 | assert!(bst::is_bst(tree.root, None, None)); 95 | } 96 | 97 | #[test] 98 | fn delete_right_left_deviation() { 99 | // right-hand deviation 100 | let mut tree = Tree::default(); 101 | for v in 0..100 { 102 | tree.insert(v, v); 103 | } 104 | let mut height = 100; 105 | for v in 0..100 { 106 | tree.delete(&v); 107 | height -= 1; 108 | assert_eq!(height, tree.height()); 109 | } 110 | 111 | // left-hand deviation 112 | let mut tree = Tree::default(); 113 | for v in (0..100).rev() { 114 | tree.insert(v, v); 115 | } 116 | let mut height = 100; 117 | for v in (0..100).rev() { 118 | tree.delete(&v); 119 | height -= 1; 120 | assert_eq!(height, tree.height()); 121 | } 122 | } 123 | 124 | #[test] 125 | fn drop_clear() { 126 | use algo::common::drop::{self, Elem}; 127 | drop::with(|ctx| { 128 | let mut tree = Tree::default(); 129 | for v in 0..100 { 130 | tree.insert(v, Elem); 131 | } 132 | drop(tree); 133 | assert_eq!(100, ctx.get()); 134 | }); 135 | } 136 | 137 | #[test] 138 | fn drop_with_delete() { 139 | use algo::common::drop::{self, Elem}; 140 | drop::with(|ctx| { 141 | let mut tree = Tree::default(); 142 | for v in 0..100 { 143 | tree.insert(v, Elem); 144 | } 145 | 146 | for v in 0..10 { 147 | tree.delete(&v); 148 | } 149 | assert_eq!(10, ctx.get()); 150 | 151 | drop(tree); 152 | assert_eq!(100, ctx.get()); 153 | }); 154 | } 155 | -------------------------------------------------------------------------------- /tests/test_rb_tree2.rs: -------------------------------------------------------------------------------- 1 | use algo::tree::binary::rb2::RedBlackTreeV2; 2 | use algo::tree::binary::traverse::{InOrderVisitor, PreOrderVisitor}; 3 | use algo::tree::binary::Tree; 4 | 5 | #[test] 6 | fn height() { 7 | let mut tree = Tree::default(); 8 | for v in 0..100 { 9 | tree.insert(v, v); 10 | } 11 | // 即使输入升序数列,rb tree仍然是平衡的 12 | // 证明:含有n个节点的红黑树,其高度不会超过 2 * lg(n + 1) 13 | assert!(tree.height() as f32 <= 2.0 * 100.0f32.log2()) 14 | } 15 | 16 | /// Algorithms 4th Edition by Robert Sedgewick, Kevin Wayne 17 | /// P440 18 | #[test] 19 | fn insert1() { 20 | let mut tree = Tree::default(); 21 | for v in "SEARCHXMPL".chars() { 22 | tree.insert(v, v); 23 | } 24 | 25 | let r = unsafe { PreOrderVisitor::iterate(&tree) }; 26 | assert_eq!(r.iter().collect::(), "MECALHRPXS"); 27 | let r = unsafe { InOrderVisitor::iterate(&tree) }; 28 | assert_eq!(r.iter().collect::(), "ACEHLMPRSX"); 29 | } 30 | 31 | #[test] 32 | fn insert2() { 33 | let mut tree = Tree::default(); 34 | for v in "ACEHLMPRSX".chars() { 35 | tree.insert(v, v); 36 | } 37 | 38 | let r = unsafe { PreOrderVisitor::iterate(&tree) }; 39 | assert_eq!(r.iter().collect::(), "HCAERMLPXS"); 40 | let r = unsafe { InOrderVisitor::iterate(&tree) }; 41 | assert_eq!(r.iter().collect::(), "ACEHLMPRSX"); 42 | } 43 | 44 | #[test] 45 | fn repeat_insert() { 46 | let mut tree = Tree::default(); 47 | for v in "ACEHLMPRSX".chars() { 48 | tree.insert(v, v); 49 | } 50 | 51 | //重复insert 'A' 52 | tree.insert('A', 'A'); 53 | 54 | let r = unsafe { PreOrderVisitor::iterate(&tree) }; 55 | assert_eq!(r.iter().collect::(), "HCAERMLPXS"); 56 | } 57 | 58 | #[test] 59 | fn delete_min() { 60 | let mut tree = Tree::default(); 61 | for v in 0..10 { 62 | tree.insert(v, v); 63 | } 64 | for v in 0..10 { 65 | assert!(tree.contains(&v)); 66 | tree.delete_min(); 67 | assert!(!tree.contains(&v)); 68 | } 69 | } 70 | 71 | #[test] 72 | fn delete_max() { 73 | let mut tree = Tree::default(); 74 | for v in 0..10 { 75 | tree.insert(v, v); 76 | } 77 | for v in (0..10).rev() { 78 | assert!(tree.contains(&v)); 79 | tree.delete_max(); 80 | assert!(!tree.contains(&v)); 81 | } 82 | } 83 | 84 | #[test] 85 | fn delete() { 86 | let mut tree = Tree::default(); 87 | for v in 0..10 { 88 | tree.insert(v, v); 89 | } 90 | for v in (0..10).rev() { 91 | assert!(tree.contains(&v)); 92 | tree.delete(&v); 93 | assert!(!tree.contains(&v)); 94 | } 95 | } 96 | 97 | #[test] 98 | fn min_max() { 99 | let mut tree = Tree::default(); 100 | for v in 0..10 { 101 | tree.insert(v, v); 102 | } 103 | assert_eq!(tree.min(), Some(&0)); 104 | assert_eq!(tree.max(), Some(&9)); 105 | } 106 | 107 | #[test] 108 | fn keys() { 109 | let mut tree = Tree::default(); 110 | for v in 0..10 { 111 | tree.insert(v, v); 112 | } 113 | assert_eq!(tree.keys(), vec![&0, &1, &2, &3, &4, &5, &6, &7, &8, &9]); 114 | 115 | // 倒序加入 116 | let mut tree = Tree::default(); 117 | for v in (0..10).rev() { 118 | tree.insert(v, v); 119 | } 120 | assert_eq!(tree.keys(), vec![&0, &1, &2, &3, &4, &5, &6, &7, &8, &9]); 121 | } 122 | 123 | #[test] 124 | fn drop_clear() { 125 | use algo::common::drop::{self, Elem}; 126 | drop::with(|ctx| { 127 | let mut tree = Tree::default(); 128 | for v in 0..100 { 129 | tree.insert(v, Elem); 130 | } 131 | drop(tree); 132 | assert_eq!(100, ctx.get()); 133 | }); 134 | } 135 | 136 | #[test] 137 | fn drop_with_delete() { 138 | use algo::common::drop::{self, Elem}; 139 | drop::with(|ctx| { 140 | let mut tree = Tree::default(); 141 | for v in 0..100 { 142 | tree.insert(v, Elem); 143 | } 144 | 145 | for v in 0..10 { 146 | tree.delete(&v); 147 | } 148 | assert_eq!(10, ctx.get()); 149 | 150 | drop(tree); 151 | assert_eq!(100, ctx.get()); 152 | }); 153 | } 154 | -------------------------------------------------------------------------------- /src/math/sparse_vector.rs: -------------------------------------------------------------------------------- 1 | /// The SparseVector represents a d dimensional mathematical vector. 2 | /// Vectors are mutable: their values can be changed after they are created. 3 | /// It includes methods for addition, subtraction, 4 | /// dot product, scalar product, unit vector, and Euclidean norm. 5 | /// 6 | /// The implementation is a symbol table (Red Black Tree) of indices and values 7 | /// for which the vector coordinates are nonzero. This makes it efficient when 8 | /// most of the vector coordindates are zero. 9 | /// 10 | /// ref: https://github.com/kevin-wayne/algs4.git 11 | use crate::tree::binary::rb2::RedBlackTreeV2; 12 | use crate::tree::binary::Tree; 13 | use std::ops::{Add, Sub}; 14 | 15 | pub struct SparseVector { 16 | d: usize, 17 | st: Tree, 18 | } 19 | 20 | impl SparseVector { 21 | /// Initializes a d-dimensional zero vector. 22 | pub fn new(d: usize) -> Self { 23 | let st = Tree::default(); 24 | Self { d, st } 25 | } 26 | 27 | /// Sets the ith coordinate of this vector to the specified value. 28 | pub fn put(&mut self, i: usize, v: f64) { 29 | if v == 0.0 { 30 | self.st.delete(&i); 31 | } else { 32 | self.st.insert(i, v); 33 | } 34 | } 35 | 36 | /// Returns the ith coordinate of this vector 37 | pub fn get(&self, i: usize) -> f64 { 38 | *self.st.get(&i).unwrap_or(&0.0) 39 | } 40 | 41 | /// Returns the number of nonzero entries in this vector. 42 | pub fn nnz(&self) -> usize { 43 | self.st.size() 44 | } 45 | 46 | /// Returns the dimension of this vector. 47 | pub fn dimension(&self) -> usize { 48 | self.d 49 | } 50 | 51 | /// Returns the inner product of this vector with the specified vector. 52 | pub fn dot(&self, that: &Self) -> Result { 53 | if self.d != that.d { 54 | Err(Err::Dimension) 55 | } else { 56 | let keys = if self.nnz() <= that.nnz() { 57 | self.st.keys() 58 | } else { 59 | that.st.keys() 60 | }; 61 | 62 | let sum = keys.iter().fold(0.0, |acc, &i| { 63 | let delta = match (self.st.get(i), that.st.get(i)) { 64 | (Some(a), Some(b)) => a * b, 65 | _ => 0.0, 66 | }; 67 | acc + delta 68 | }); 69 | 70 | Ok(sum) 71 | } 72 | } 73 | 74 | /// Returns the magnitude of this vector. 75 | /// This is also known as the L2 norm or the Euclidean norm. 76 | pub fn magnitude(&self) -> f64 { 77 | self.dot(self).unwrap().sqrt() 78 | } 79 | 80 | /// Returns the scalar-vector product of this vector with the specified scalar. 81 | pub fn scale(&self, alpha: f64) -> Self { 82 | let mut c = Self::new(self.d); 83 | for &i in self.st.keys() { 84 | c.put(i, alpha * self.get(i)); 85 | } 86 | c 87 | } 88 | } 89 | 90 | impl Add for SparseVector { 91 | type Output = Self; 92 | 93 | fn add(self, rhs: Self) -> Self::Output { 94 | let mut c = self; 95 | for &i in rhs.st.keys() { 96 | c.put(i, c.get(i) + rhs.get(i)); 97 | } 98 | c 99 | } 100 | } 101 | 102 | impl Sub for SparseVector { 103 | type Output = Self; 104 | 105 | fn sub(self, rhs: Self) -> Self::Output { 106 | let mut c = self; 107 | for &i in rhs.st.keys() { 108 | c.put(i, c.get(i) - rhs.get(i)); 109 | } 110 | c 111 | } 112 | } 113 | 114 | impl ToString for SparseVector { 115 | fn to_string(&self) -> String { 116 | let keys = self.st.keys(); 117 | let mut v = Vec::with_capacity(keys.len()); 118 | for &i in keys { 119 | v.push(format!("({}, {})", i, self.get(i))); 120 | } 121 | v.join("") 122 | } 123 | } 124 | 125 | impl Clone for SparseVector { 126 | fn clone(&self) -> Self { 127 | let mut c = Self::new(self.d); 128 | for &i in self.st.keys() { 129 | c.put(i, self.get(i)); 130 | } 131 | c 132 | } 133 | } 134 | 135 | #[derive(Debug)] 136 | pub enum Err { 137 | Dimension, 138 | } 139 | -------------------------------------------------------------------------------- /src/graph/directed/order.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::{IEWDigraph, IGraph}; 2 | use std::iter::Rev; 3 | use std::slice::Iter; 4 | 5 | /// The DepthFirstOrder represents a data type for 6 | /// determining depth-first search ordering of the vertices in a digraph 7 | /// or edge-weighted digraph, including preorder, postorder, and reverse 8 | /// postorder. 9 | /// This implementation uses depth-first search. 10 | pub struct DepthFirstOrders { 11 | pre_order: Vec, // vertices in preorder 12 | pre: Vec, // pre[v] = preorder number of v 13 | pre_counter: usize, // counter or preorder numbering 14 | post_order: Vec, // vertices in postorder 15 | post: Vec, // post[v] = postorder number of v 16 | post_counter: usize, // counter for postorder numbering 17 | marked: Vec, // marked[v] = has v been marked in dfs? 18 | } 19 | 20 | impl DepthFirstOrders { 21 | /// Returns the vertices in preorder. 22 | pub fn pre(&self) -> Iter<'_, usize> { 23 | self.pre_order.iter() 24 | } 25 | 26 | /// Returns the vertices in postorder 27 | pub fn post(&self) -> Iter<'_, usize> { 28 | self.post_order.iter() 29 | } 30 | 31 | /// Returns the vertices in reverse postorder. 32 | pub fn rev_post(&self) -> Rev> { 33 | self.post_order.iter().rev() 34 | } 35 | } 36 | 37 | impl DepthFirstOrders { 38 | fn new(nv: usize) -> Self { 39 | Self { 40 | pre_order: Vec::with_capacity(nv), 41 | pre: vec![0; nv], 42 | pre_counter: 0, 43 | post_order: Vec::with_capacity(nv), 44 | post: vec![0; nv], 45 | post_counter: 0, 46 | marked: vec![false; nv], 47 | } 48 | } 49 | 50 | /// run DFS in digraph G from vertex v and compute preorder/postorder 51 | fn dfs(&mut self, graph: &dyn IGraph, v: usize) { 52 | self.marked[v] = true; 53 | self.pre[v] = self.pre_counter; 54 | self.pre_counter += 1; 55 | self.pre_order.push(v); 56 | for &w in graph.adj(v) { 57 | if !self.marked[w] { 58 | self.dfs(graph, w); 59 | } 60 | } 61 | self.post_order.push(v); 62 | self.post[v] = self.post_counter; 63 | self.post_counter += 1; 64 | } 65 | 66 | /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder 67 | fn dfs_ewd(&mut self, graph: &dyn IEWDigraph, v: usize) { 68 | self.marked[v] = true; 69 | self.pre[v] = self.pre_counter; 70 | self.pre_counter += 1; 71 | self.pre_order.push(v); 72 | for e in graph.adj(v) { 73 | let w = e.to(); 74 | if !self.marked[w] { 75 | self.dfs_ewd(graph, w); 76 | } 77 | } 78 | self.post_order.push(v); 79 | self.post[v] = self.post_counter; 80 | self.post_counter += 1; 81 | } 82 | 83 | /// check that pre() and post() are consistent with pre[v] and post[v] 84 | pub fn check(&self) -> Result<(), &'static str> { 85 | let mut r = 0; 86 | for &v in self.post() { 87 | if self.post[v] != r { 88 | return Err("post[v] and post() inconsistent"); 89 | } 90 | r += 1; 91 | } 92 | 93 | r = 0; 94 | for &v in self.pre() { 95 | if self.pre[v] != r { 96 | return Err("pre[v] and pre() inconsistent"); 97 | } 98 | r += 1; 99 | } 100 | 101 | Ok(()) 102 | } 103 | } 104 | 105 | macro_rules! impl_from { 106 | ($G: ty, $dfs: ident) => { 107 | impl From<$G> for DepthFirstOrders { 108 | fn from(g: $G) -> Self { 109 | let nv = g.V(); 110 | let mut order = Self::new(nv); 111 | 112 | for v in 0..nv { 113 | if !order.marked[v] { 114 | order.$dfs(g, v); 115 | } 116 | } 117 | 118 | debug_assert!(order.check().is_ok()); 119 | order 120 | } 121 | } 122 | }; 123 | } 124 | 125 | impl_from!(&dyn IGraph, dfs); 126 | impl_from!(&dyn IEWDigraph, dfs_ewd); 127 | -------------------------------------------------------------------------------- /src/graph/util/paths.rs: -------------------------------------------------------------------------------- 1 | use crate::common::Queue; 2 | use crate::graph::IGraph; 3 | use crate::ll::linked_list::LinkedList; 4 | 5 | /// Finding paths 6 | /// Given a graph and a source vertex s, support queries 7 | /// of the form: Is there a path from s to a given target 8 | /// vertex v? If so, find such a path. 9 | pub trait Paths { 10 | /// is there a path from s to v ? 11 | fn has_path(&self, v: usize) -> bool; 12 | /// path from s to v; None if no such path 13 | fn path_to(&self, v: usize) -> Option>; 14 | } 15 | 16 | /// Run depth-first search on an undirected graph. 17 | /// 18 | /// Determine reachability in a digraph from a given vertex using 19 | /// depth-first search. 20 | /// Runs in O(E + V) time. 21 | pub struct DepthFirstPaths { 22 | marked: Vec, // marked[v] = is there an s-v path? 23 | edge_to: Vec, // edgeTo[v] = last edge on s-v path 24 | s: usize, // source vertex 25 | } 26 | 27 | /// Run breadth first search on an undirected graph. 28 | /// Runs in O(E + V) time. 29 | /// 30 | /// Run breadth-first search on a digraph. 31 | /// Runs in O(E + V) time. 32 | pub struct BreadthFirstPaths { 33 | marked: Vec, // marked[v] = is there an s-v path 34 | edge_to: Vec, // edgeTo[v] = previous edge on shortest s-v path 35 | dist_to: Vec, // distTo[v] = number of edges shortest s-v path 36 | s: usize, // source vertex 37 | } 38 | 39 | impl Paths for DepthFirstPaths { 40 | fn has_path(&self, v: usize) -> bool { 41 | self.marked[v] 42 | } 43 | 44 | fn path_to(&self, v: usize) -> Option> { 45 | if self.has_path(v) { 46 | let mut paths = LinkedList::default(); 47 | let s = self.s; 48 | let mut x = v; 49 | 50 | while x != s { 51 | paths.push_front(x); 52 | x = self.edge_to[x]; 53 | } 54 | paths.push_front(s); 55 | 56 | Some(paths) 57 | } else { 58 | None 59 | } 60 | } 61 | } 62 | 63 | impl Paths for BreadthFirstPaths { 64 | fn has_path(&self, v: usize) -> bool { 65 | self.marked[v] 66 | } 67 | 68 | fn path_to(&self, v: usize) -> Option> { 69 | if self.has_path(v) { 70 | let mut paths = LinkedList::default(); 71 | let s = self.s; 72 | let mut x = v; 73 | 74 | while x != s { 75 | paths.push_front(x); 76 | x = self.edge_to[x]; 77 | } 78 | paths.push_front(s); 79 | 80 | Some(paths) 81 | } else { 82 | None 83 | } 84 | } 85 | } 86 | 87 | impl DepthFirstPaths { 88 | pub fn new(g: &dyn IGraph, s: usize) -> Self { 89 | let marked = vec![false; g.V()]; 90 | let edge_to = vec![0; g.V()]; 91 | let mut h = Self { marked, s, edge_to }; 92 | h.dfs(g, s); 93 | h 94 | } 95 | 96 | fn dfs(&mut self, g: &dyn IGraph, v: usize) { 97 | self.marked[v] = true; 98 | for &w in g.adj(v) { 99 | if !self.marked[w] { 100 | self.edge_to[w] = v; 101 | self.dfs(g, w); 102 | } 103 | } 104 | } 105 | } 106 | 107 | impl BreadthFirstPaths { 108 | pub fn new(g: &dyn IGraph, s: usize) -> Self { 109 | let marked = vec![false; g.V()]; 110 | let edge_to = vec![0; g.V()]; 111 | let dist_to = vec![usize::MAX; g.V()]; 112 | let mut h = Self { 113 | marked, 114 | s, 115 | edge_to, 116 | dist_to, 117 | }; 118 | h.bfs(g, s); 119 | h 120 | } 121 | 122 | pub fn dist_to(&self, v: usize) -> usize { 123 | self.dist_to[v] 124 | } 125 | 126 | fn bfs(&mut self, g: &dyn IGraph, s: usize) { 127 | let mut queue = Queue::default(); 128 | self.marked[s] = true; 129 | self.dist_to[s] = 0; 130 | queue.enqueue(s); 131 | while let Some(v) = queue.dequeue() { 132 | for &w in g.adj(v) { 133 | if !self.marked[w] { 134 | self.edge_to[w] = v; 135 | self.dist_to[w] = self.dist_to[v] + 1; 136 | self.marked[w] = true; 137 | queue.enqueue(w); 138 | } 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/graph/shortest/cpm.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::many_single_char_names)] 2 | 3 | use crate::graph::shortest::{AcyclicLP, EWDigraph}; 4 | use crate::graph::util::parser; 5 | use crate::graph::IEWDigraph; 6 | 7 | /// Parallel job scheduling 8 | /// Given a set of jobs of specified duration to be completed, with 9 | /// precedence constraints that specify that certain jobs have to be 10 | /// completed before certain other jobs are begun, how can we schedule 11 | /// the jobs on identical processors (as many as needed) such that they 12 | /// are all completed in the minimum amount of time while still respecting 13 | /// the constraints? 14 | /// 15 | /// We assume that we have sufficient processors to perform as many jobs as 16 | /// possible, limited only by precedence constraints. 17 | /// 18 | /// Every sequence of jobs, each constrained to follow the job just 19 | /// preceding it in the sequence, represents a lower bound on the 20 | /// length of the schedule. If we define the length of such a sequence 21 | /// to be its earliest possible completion time (total of the durations 22 | /// of its jobs), the longest sequence is known as a critical path 23 | /// because any delay in the start- ing time of any job delays the best 24 | /// achievable completion time of the entire project. 25 | /// 26 | /// Critical path method for parallel precedence-constrained job scheduling 27 | 28 | pub struct CPM { 29 | n: usize, // number of jobs 30 | lp: AcyclicLP, 31 | } 32 | 33 | impl CPM { 34 | /// number of jobs 35 | pub fn len(&self) -> usize { 36 | self.n 37 | } 38 | 39 | pub fn is_empty(&self) -> bool { 40 | self.n == 0 41 | } 42 | 43 | pub fn dist_to(&self, i: usize) -> f32 { 44 | self.lp.dist_to(i) 45 | } 46 | 47 | pub fn finish_time(&self) -> f32 { 48 | let sink = 2 * self.n + 1; 49 | self.lp.dist_to(sink) 50 | } 51 | } 52 | 53 | impl std::convert::TryFrom<&str> for CPM { 54 | type Error = (); 55 | 56 | /// Definition. 57 | /// The critical path method for parallel scheduling is to proceed 58 | /// as follows: Create an edge-weighted DAG with a source s, a sink 59 | /// t, and two vertices for each job (a start vertex and an end vertex). 60 | /// For each job, add an edge from its start vertex to its end vertex 61 | /// with weight equal to its duration. For each precedence constraint 62 | /// v->w, add a zero-weight edge from the end vertex corresponding tovs 63 | /// to the beginning vertex corresponding to w. Also add zero-weight 64 | /// edges from the source to each job’s start vertex and from each 65 | /// job’s end vertex to the sink. Now, schedule each job at the time 66 | /// given by the length of its longest path from the source. 67 | fn try_from(i: &str) -> Result { 68 | let mut lines = i.lines(); 69 | 70 | // number of jobs 71 | let s = lines.next().ok_or(())?; 72 | let (_, n) = parser::parse_num::(s).ok().ok_or(())?; 73 | 74 | // source and sink 75 | // a source s, a sink t, and two vertices for each 76 | // job (a start vertex and an end vertex) 77 | let source = 2 * n; 78 | let sink = 2 * n + 1; 79 | 80 | // build network 81 | let mut g = EWDigraph::from(2 * n + 2); 82 | for i in 0..n { 83 | let s = lines.next().ok_or(())?; 84 | if let Ok((_, v)) = parser::parse_list_float(s) { 85 | let duration = v[0]; 86 | // add zero-weight edges from the source to each job’s 87 | // start vertex and from each job’s end vertex to the sink 88 | g.add_edge(source, i, 0.0); 89 | g.add_edge(i + n, sink, 0.0); 90 | // For each job, add an edge from its start vertex to 91 | // its end vertex with weight equal to its duration 92 | g.add_edge(i, i + n, duration); 93 | 94 | let m = v[1] as usize; 95 | if m > 0 { 96 | for v in &v[2..] { 97 | let successor = *v as usize; 98 | // For each precedence constraint v->w, add a zero-weight edge from the 99 | // end vertex corresponding tovs to the begin- ning vertex corresponding to w. 100 | g.add_edge(i + n, successor, 0.0); 101 | } 102 | } 103 | } 104 | } 105 | 106 | let lp = AcyclicLP::new(&g, source).ok().ok_or(())?; 107 | Ok(CPM { n, lp }) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/graph/undirected/graph.rs: -------------------------------------------------------------------------------- 1 | //! 2 | //! Algorithhms 4th Edition by Robert Sedgewick, Kevin Wayne 3 | //! CHAPTER 4 4 | //! Representation alternatives. 5 | //! 6 | //! The next decision that we face in graph processing is which 7 | //! graph representation (data structure) to use to implement 8 | //! this API. We have two basic requirements: 9 | //! - We must have the space to accommodate the types of graphs 10 | //! that we are likely to encounter in applications. 11 | //! - We want to develop time-efficient implementations of Graph 12 | //! instance methods the basic methods that we need to develop 13 | //! graph processing clients. 14 | //! 15 | //! These requirements are a bit vague, but they are still helpful 16 | //! in choosing among the three data structures that immediately 17 | //! suggest themselves for representing graphs: 18 | //! 19 | //! - An adjacency matrix, where we main- tain a V-by-V boolean array, 20 | //! with the entry in row v and column w defined to be true if there is 21 | //! an edge adjacent to both vertex v and vertex w in the graph, and to 22 | //! be false otherwise. This representation fails on the first count graphs 23 | //! with millions of vertices are common and the space cost for the V 2 boolean 24 | //! values needed is prohibitive. 25 | //! Beyond these performance objectives, a detailed examination reveals other 26 | //! considerations that can be important in some applications. For example, 27 | //! allowing parallel edges precludes the use of an adjacency matrix, since 28 | //! the adjacency matrix has no way to represent them. 29 | //! 30 | //! - An array of edges, using an Edge class with two instance variables of type 31 | //! int. This direct representation is simple, but it fails on the second count 32 | //! implementing adj() would involve examining all the edges in the graph. 33 | //! 34 | //! - An array of adjacency lists, where we maintain a vertex-indexed array of 35 | //! lists of the vertices adjacent to each vertex. This data structure satisfies 36 | //! both requirements for typical applications and is the one that we will use 37 | //! throughout this chapter. 38 | 39 | use crate::graph::util::parser::GraphDataParser; 40 | use crate::graph::IGraph; 41 | use crate::ll::{linked_list::Iter, LinkedList}; 42 | 43 | pub struct Graph { 44 | nv: usize, // num of vertices 45 | ne: usize, // num of edges 46 | adj: Vec>, 47 | } 48 | 49 | impl IGraph for Graph { 50 | fn V(&self) -> usize { 51 | self.nv 52 | } 53 | 54 | fn E(&self) -> usize { 55 | self.ne 56 | } 57 | 58 | fn add_edge(&mut self, v: usize, w: usize) { 59 | // Algorithhms 4th Edition by Robert Sedgewick, Kevin Wayne 60 | // p538, Adjacency-lists data structure 61 | // first adjacent vertex in input is last on list 62 | self.adj[v].push_front(w); 63 | self.adj[w].push_front(v); 64 | self.ne += 1; 65 | } 66 | 67 | fn adj(&self, v: usize) -> Iter<'_, usize> { 68 | self.adj[v].iter() 69 | } 70 | } 71 | 72 | impl Graph { 73 | /// compute the degree of v 74 | pub fn degree(&self, v: usize) -> usize { 75 | self.adj(v).fold(0, |acc, _| acc + 1) 76 | } 77 | 78 | /// compute maximum degree 79 | pub fn max_degree(&self) -> usize { 80 | let mut max = 0; 81 | for v in 0..self.V() { 82 | max = std::cmp::max(max, self.degree(v)); 83 | } 84 | max 85 | } 86 | 87 | /// compute average degree 88 | pub fn avg_degree(&self) -> f32 { 89 | 2.0 * self.E() as f32 / self.V() as f32 90 | } 91 | 92 | /// count self-loops 93 | pub fn number_of_self_loops(&self) -> usize { 94 | let mut count = 0; 95 | for v in 0..self.V() { 96 | for &w in self.adj(v) { 97 | if v == w { 98 | count += 1; 99 | } 100 | } 101 | } 102 | 103 | // each edge counted twice 104 | count / 2 105 | } 106 | } 107 | 108 | /// create a V-vertex graph with no edges 109 | impl From for Graph { 110 | fn from(nv: usize) -> Self { 111 | let mut adj = Vec::with_capacity(nv); 112 | for _ in 0..nv { 113 | adj.push(LinkedList::default()); 114 | } 115 | 116 | Self { nv, ne: 0, adj } 117 | } 118 | } 119 | 120 | impl From<&str> for Graph { 121 | fn from(s: &str) -> Self { 122 | let parser = GraphDataParser::parse(s, false).unwrap(); 123 | let mut g = Self::from(parser.get_v()); 124 | for (v, w) in parser.get_edges() { 125 | g.add_edge(*v, *w); 126 | } 127 | debug_assert!(g.E() == parser.get_e()); 128 | g 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/graph/mst/prim_mst.rs: -------------------------------------------------------------------------------- 1 | use crate::common::{IndexPQ, UF}; 2 | use crate::graph::mst::Edge; 3 | use crate::graph::IEWGraph; 4 | 5 | /// The PrimMST represents a data type for computing a 6 | /// minimum spanning tree in an edge-weighted graph. 7 | /// The edge weights can be positive, zero, or negative and need not 8 | /// be distinct. If the graph is not connected, it computes a minimum 9 | /// spanning forest, which is the union of minimum spanning trees 10 | /// in each connected component. The weight() method returns the 11 | /// weight of a minimum spanning tree and the edges() method 12 | /// returns its edges. 13 | /// This implementation uses Prim's algorithm with an indexed 14 | /// binary heap. 15 | pub struct PrimMST { 16 | edge_to: Vec>, // edgeTo[v] = shortest edge from tree vertex to non-tree vertex 17 | dist_to: Vec, // distTo[v] = weight of shortest such edge 18 | marked: Vec, // marked[v] = true if v on tree, false otherwise 19 | pq: IndexPQ, // eligible crossing edges 20 | } 21 | 22 | impl PrimMST { 23 | /// Compute a minimum spanning tree (or forest) of an edge-weighted graph 24 | pub fn new(g: &dyn IEWGraph) -> Self { 25 | let gv = g.V(); 26 | let mut mst = Self { 27 | edge_to: vec![None; gv], 28 | dist_to: vec![f32::MAX; gv], 29 | marked: vec![false; gv], 30 | pq: IndexPQ::new_min_pq(gv), 31 | }; 32 | 33 | for s in 0..gv { 34 | if !mst.marked[s] { 35 | mst.prim(g, s); 36 | } 37 | } 38 | 39 | mst 40 | } 41 | 42 | /// Returns the edges in a minimum spanning tree (or forest) 43 | pub fn edges(&self) -> Vec { 44 | self.edge_to.iter().cloned().flatten().collect() 45 | } 46 | 47 | /// Returns the sum of the edge weights in a minimum spanning tree (or forest) 48 | pub fn weight(&self) -> f32 { 49 | self.edge_to 50 | .iter() 51 | .flatten() 52 | .fold(0.0, |acc, e| acc + e.weight()) 53 | } 54 | 55 | /// run Prim's algorithm in graph G, starting from vertex s 56 | fn prim(&mut self, g: &dyn IEWGraph, s: usize) { 57 | let _ = self.pq.enqueue(s, 0.0); 58 | while !self.pq.is_empty() { 59 | let v = self.pq.dequeue().unwrap(); 60 | self.scan(g, v); 61 | } 62 | } 63 | 64 | fn scan(&mut self, g: &dyn IEWGraph, v: usize) { 65 | self.marked[v] = true; 66 | for e in g.adj(v) { 67 | let w = e.other(v); 68 | if self.marked[w] { 69 | continue; 70 | } 71 | if e.weight() < self.dist_to[w] { 72 | self.dist_to[w] = e.weight(); 73 | self.edge_to[w] = Some(*e); 74 | if self.pq.contains(w) { 75 | let _ = self.pq.decrease_key(w, self.dist_to[w]); 76 | } else { 77 | let _ = self.pq.enqueue(w, self.dist_to[w]); 78 | } 79 | } 80 | } 81 | } 82 | 83 | pub fn check(&self, g: &dyn IEWGraph) -> Result<(), String> { 84 | // check that it is acyclic 85 | let mut uf = UF::new(g.V()); 86 | for e in self.edges() { 87 | let v = e.either(); 88 | let w = e.other(v); 89 | if uf.find(v) == uf.find(w) { 90 | return Err("Not a forest".to_string()); 91 | } 92 | uf.union(v, w); 93 | } 94 | 95 | // check that it is a spanning forest 96 | for e in g.edges() { 97 | let v = e.either(); 98 | let w = e.other(v); 99 | if uf.find(v) != uf.find(w) { 100 | return Err("Not a spanning forest".to_string()); 101 | } 102 | } 103 | 104 | // check that it is a minimal spanning forest (cut optimality conditions) 105 | let mst = self.edges(); 106 | for e in mst.iter() { 107 | // all edges in MST except e 108 | uf = UF::new(g.V()); 109 | for f in mst.iter() { 110 | if f != e { 111 | let x = f.either(); 112 | let y = f.other(x); 113 | uf.union(x, y); 114 | } 115 | } 116 | 117 | // check that e is min weight edge in crossing cut 118 | for f in g.edges() { 119 | let x = f.either(); 120 | let y = f.other(x); 121 | if uf.find(x) != uf.find(y) && f.weight() < e.weight() { 122 | return Err(format!( 123 | "Edge {} violates cut optimality conditions", 124 | f.to_string() 125 | )); 126 | } 127 | } 128 | } 129 | 130 | Ok(()) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/strings/alphabet.rs: -------------------------------------------------------------------------------- 1 | //! A data type for alphabets, for use with string-processing code 2 | //! that must convert between an alphabet of size R and the integers 3 | //! 0 through R-1. 4 | //! 5 | //! Warning: supports only the basic multilingual plane (BMP), i.e, 6 | //! Unicode characters between U+0000 and U+FFFF. 7 | use std::convert::TryFrom; 8 | 9 | // const MAX_VALUE: usize = char::MAX as usize; 10 | const MAX_VALUE: usize = 65535; 11 | 12 | macro_rules! declare { 13 | ($name:ident, $v:expr) => { 14 | lazy_static! { 15 | pub static ref $name: Alphabet = Alphabet::try_from($v).unwrap(); 16 | } 17 | }; 18 | } 19 | 20 | // The binary alphabet { 0, 1 } 21 | declare!(BINARY, "01"); 22 | // The octal alphabet { 0, 1, 2, 3, 4, 5, 6, 7 } 23 | declare!(OCTAL, "01234567"); 24 | // The decimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } 25 | declare!(DECIMAL, "0123456789"); 26 | // The hexadecimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F } 27 | declare!(HEXADECIMAL, "0123456789ABCDEF"); 28 | // The DNA alphabet { A, C, T, G } 29 | declare!(DNA, "ACGT"); 30 | // The lowercase alphabet { a, b, c, ..., z } 31 | declare!(LOWERCASE, "abcdefghijklmnopqrstuvwxyz"); 32 | // The uppercase alphabet { A, B, C, ..., Z } 33 | declare!(UPPERCASE, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 34 | // The protein alphabet { A, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y } 35 | declare!(PROTEIN, "ACDEFGHIKLMNPQRSTVWY"); 36 | // The base-64 alphabet (64 characters) 37 | declare!( 38 | BASE64, 39 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 40 | ); 41 | // The ASCII alphabet (0-127) 42 | declare!(ASCII, 128); 43 | // The extended ASCII alphabet (0-255) 44 | declare!(EXTENDED_ASCII, 256); 45 | // The Unicode 16 alphabet (0-65,535) 46 | declare!(UNICODE16, 65535); 47 | 48 | pub struct Alphabet { 49 | alphabet: Vec, 50 | inverse: Vec, 51 | radix: usize, 52 | } 53 | 54 | impl TryFrom<&str> for Alphabet { 55 | type Error = String; 56 | 57 | fn try_from(s: &str) -> Result { 58 | let alphabet: Vec = s.chars().collect(); 59 | let mut unicode = vec![false; MAX_VALUE]; 60 | for &c in &alphabet { 61 | if unicode[c as usize] { 62 | return Err(format!("Illegal alphabet: repeated character = {:?}", c)); 63 | } 64 | unicode[c as usize] = true; //set code point 65 | } 66 | 67 | let radix = alphabet.len(); 68 | let mut inverse = vec![-1; MAX_VALUE]; 69 | for i in 0..radix { 70 | inverse[alphabet[i] as usize] = i as i32; 71 | } 72 | 73 | Ok(Self { 74 | alphabet, 75 | inverse, 76 | radix, 77 | }) 78 | } 79 | } 80 | 81 | impl TryFrom for Alphabet { 82 | type Error = (); 83 | 84 | fn try_from(radix: u16) -> Result { 85 | let inverse = (0..=radix as i32).collect(); 86 | let alphabet: Vec<_> = (0..=radix).collect(); 87 | let alphabet = String::from_utf16_lossy(&alphabet).chars().collect(); 88 | Ok(Self { 89 | alphabet, 90 | inverse, 91 | radix: radix as usize, 92 | }) 93 | } 94 | } 95 | 96 | impl Alphabet { 97 | /// Returns the index corresponding to the argument character 98 | pub fn to_index(&self, c: char) -> Option<&i32> { 99 | self.inverse.get(c as usize) 100 | } 101 | 102 | /// Returns the indices corresponding to the argument characters 103 | pub fn to_indices(&self, s: &str) -> Vec { 104 | s.chars() 105 | .map(|c| self.to_index(c).unwrap()) 106 | .cloned() 107 | .collect() 108 | } 109 | 110 | /// Returns the character corresponding to the argument index 111 | pub fn to_char(&self, i: i32) -> Option<&char> { 112 | self.alphabet.get(i as usize) 113 | } 114 | 115 | /// Returns the characters corresponding to the argument indices 116 | pub fn to_chars(&self, indices: &[i32]) -> String { 117 | let mut buf = String::new(); 118 | for &i in indices { 119 | if let Some(&c) = self.to_char(i) { 120 | buf.push(c); 121 | } 122 | } 123 | buf 124 | } 125 | 126 | /// Returns true if the argument is a character in this alphabet 127 | pub fn contains(&self, c: char) -> bool { 128 | self.inverse.get(c as usize) != Some(&-1) 129 | } 130 | 131 | /// Returns the number of characters in this alphabet (the radix) 132 | pub fn radix(&self) -> usize { 133 | self.radix 134 | } 135 | 136 | /// Returns the binary logarithm of the number of characters in this alphabet 137 | pub fn lg_r(&self) -> usize { 138 | let mut lg_r = 0; 139 | let mut t = self.radix - 1; 140 | while t >= 1 { 141 | lg_r += 1; 142 | t /= 2; 143 | } 144 | lg_r 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/ll/linked_list.rs: -------------------------------------------------------------------------------- 1 | use crate::ll::reverse::do_reverse; 2 | use std::marker::PhantomData; 3 | use std::ptr::NonNull; 4 | 5 | pub struct Node { 6 | pub element: T, 7 | pub next: Option>>, 8 | } 9 | 10 | impl Node { 11 | fn new(element: T) -> NonNull { 12 | let v = Box::new(Node { 13 | element, 14 | next: None, 15 | }); 16 | Box::leak(v).into() 17 | } 18 | } 19 | 20 | pub struct LinkedList { 21 | pub head: Option>>, 22 | pub tail: Option>>, 23 | len: usize, 24 | } 25 | 26 | pub struct Iter<'a, T: 'a> { 27 | head: Option>>, 28 | // tail: Option>>, 29 | len: usize, 30 | marker: PhantomData<&'a Node>, 31 | } 32 | 33 | pub struct IntoIter { 34 | list: LinkedList, 35 | } 36 | 37 | impl LinkedList { 38 | pub fn len(&self) -> usize { 39 | self.len 40 | } 41 | 42 | pub fn is_empty(&self) -> bool { 43 | self.len == 0 44 | } 45 | 46 | pub fn push_back(&mut self, element: T) { 47 | let mut node = Node::new(element); 48 | unsafe { 49 | node.as_mut().next = None; 50 | 51 | match self.tail { 52 | Some(mut tail) => tail.as_mut().next = Some(node), 53 | None => self.head = Some(node), 54 | } 55 | } 56 | 57 | self.tail = Some(node); 58 | self.len += 1; 59 | } 60 | 61 | pub fn push_front(&mut self, element: T) { 62 | let mut node = Node::new(element); 63 | unsafe { 64 | node.as_mut().next = self.head; 65 | } 66 | 67 | if self.head.is_none() { 68 | self.tail = Some(node); 69 | } 70 | 71 | self.head = Some(node); 72 | self.len += 1; 73 | } 74 | 75 | pub fn pop_front(&mut self) -> Option { 76 | unsafe { 77 | self.head.map(|head| { 78 | let node = Box::from_raw(head.as_ptr()); 79 | self.head = node.next; 80 | 81 | if self.head.is_none() { 82 | self.tail = None; 83 | } 84 | 85 | self.len -= 1; 86 | node.element 87 | }) 88 | } 89 | } 90 | 91 | pub fn iter(&self) -> Iter<'_, T> { 92 | Iter { 93 | head: self.head, 94 | // tail: self.tail, 95 | len: self.len, 96 | marker: PhantomData, 97 | } 98 | } 99 | 100 | pub fn first(&self) -> Option<&T> { 101 | unsafe { self.head.map(|node| &node.as_ref().element) } 102 | } 103 | 104 | pub fn last(&self) -> Option<&T> { 105 | unsafe { self.tail.map(|node| &node.as_ref().element) } 106 | } 107 | 108 | /// 反转链表 109 | pub fn reverse(&mut self) { 110 | let head = self.head; 111 | let new_head = unsafe { do_reverse(head) }; 112 | self.head = new_head; 113 | self.tail = head; 114 | } 115 | } 116 | 117 | impl IntoIterator for LinkedList { 118 | type Item = T; 119 | type IntoIter = IntoIter; 120 | 121 | /// Consumes the list into an iterator yielding elements by value. 122 | #[inline] 123 | fn into_iter(self) -> IntoIter { 124 | IntoIter { list: self } 125 | } 126 | } 127 | 128 | impl<'a, T> Iterator for Iter<'a, T> { 129 | type Item = &'a T; 130 | 131 | #[inline] 132 | fn next(&mut self) -> Option<&'a T> { 133 | if self.len == 0 { 134 | None 135 | } else { 136 | self.head.map(|node| unsafe { 137 | // Need an unbound lifetime to get 'a 138 | let node = &*node.as_ptr(); 139 | self.len -= 1; 140 | self.head = node.next; 141 | &node.element 142 | }) 143 | } 144 | } 145 | 146 | #[inline] 147 | fn size_hint(&self) -> (usize, Option) { 148 | (self.len, Some(self.len)) 149 | } 150 | } 151 | 152 | impl Iterator for IntoIter { 153 | type Item = T; 154 | 155 | #[inline] 156 | fn next(&mut self) -> Option { 157 | self.list.pop_front() 158 | } 159 | 160 | #[inline] 161 | fn size_hint(&self) -> (usize, Option) { 162 | (self.list.len, Some(self.list.len)) 163 | } 164 | } 165 | 166 | impl Default for LinkedList { 167 | fn default() -> Self { 168 | Self { 169 | head: None, 170 | tail: None, 171 | len: 0, 172 | } 173 | } 174 | } 175 | 176 | impl Drop for LinkedList { 177 | fn drop(&mut self) { 178 | unsafe { do_drop(self.head) } 179 | self.head = None; 180 | self.len = 0; 181 | } 182 | } 183 | 184 | unsafe fn do_drop(head: Option>>) { 185 | let mut p = head; 186 | while let Some(node) = p { 187 | let mut node = Box::from_raw(node.as_ptr()); 188 | p = node.next.take(); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/graph/util/parser.rs: -------------------------------------------------------------------------------- 1 | use nom::bytes::complete::{is_not, tag, take_till}; 2 | use nom::character::complete::{digit1, space0}; 3 | use nom::multi::separated_list1; 4 | use nom::number::complete::float; 5 | use nom::sequence::tuple; 6 | use nom::IResult; 7 | use std::fmt::Debug; 8 | use std::slice::Iter; 9 | use std::str::FromStr; 10 | 11 | pub struct GraphDataParser { 12 | nv: usize, 13 | ne: usize, 14 | edges: Vec<(usize, usize)>, 15 | weighted_edges: Vec<(usize, usize, f32)>, 16 | } 17 | 18 | impl GraphDataParser { 19 | pub fn parse(s: &str, is_weighted: bool) -> Result { 20 | let lines = s.lines(); 21 | 22 | let mut nv = 0; 23 | let mut ne = 0; 24 | let mut edges: Vec<(usize, usize)> = Vec::new(); 25 | let mut weighted_edges: Vec<(usize, usize, f32)> = Vec::new(); 26 | let mut sm = SM::V; 27 | for s in lines { 28 | if s.is_empty() { 29 | continue; 30 | } 31 | 32 | match sm { 33 | SM::V => { 34 | let (_, v) = parse_num(s).ok().ok_or(())?; 35 | nv = v; 36 | } 37 | SM::E => { 38 | let (_, v) = parse_num(s).ok().ok_or(())?; 39 | ne = v; 40 | } 41 | SM::Edge => { 42 | if is_weighted { 43 | let (_, v) = parse_list_float(s).ok().ok_or(())?; 44 | weighted_edges.push((v[0] as usize, v[1] as usize, v[2])); 45 | } else { 46 | let (_, v) = parse_list_num(s).ok().ok_or(())?; 47 | edges.push((v[0], v[1])); 48 | } 49 | } 50 | } 51 | sm = sm.step(); 52 | } 53 | 54 | Ok(Self { 55 | nv, 56 | ne, 57 | edges, 58 | weighted_edges, 59 | }) 60 | } 61 | 62 | pub fn get_v(&self) -> usize { 63 | self.nv 64 | } 65 | 66 | pub fn get_e(&self) -> usize { 67 | self.ne 68 | } 69 | 70 | pub fn get_edges(&self) -> Iter<'_, (usize, usize)> { 71 | self.edges.iter() 72 | } 73 | 74 | pub fn get_weighted_edges(&self) -> Iter<'_, (usize, usize, f32)> { 75 | self.weighted_edges.iter() 76 | } 77 | } 78 | 79 | pub fn parse_num(i: &str) -> IResult<&str, K> 80 | where 81 | K: FromStr, 82 | ::Err: Debug, 83 | { 84 | let (i, (_, v)) = tuple((space0, digit1))(i)?; 85 | Ok((i, v.parse().unwrap())) 86 | } 87 | 88 | pub fn parse_float(i: &str) -> IResult<&str, f32> { 89 | let (i, (_, v)) = tuple((space0, float))(i)?; 90 | Ok((i, v)) 91 | } 92 | 93 | /// 用空格分割的两个数字 94 | /// "1 2" 95 | pub fn parse_list_num(i: &str) -> IResult<&str, Vec> 96 | where 97 | K: FromStr, 98 | ::Err: Debug, 99 | { 100 | let sep = " "; 101 | separated_list1(tag(sep), parse_num)(i) 102 | } 103 | 104 | pub fn parse_list_float(i: &str) -> IResult<&str, Vec> { 105 | let sep = " "; 106 | separated_list1(tag(sep), parse_float)(i) 107 | } 108 | 109 | /// 用sep分割的字符串 110 | pub fn parse_list_str<'a>(i: &'a str, sep: &str) -> IResult<&'a str, Vec<&'a str>> { 111 | separated_list1(tag(sep), is_not(sep))(i) 112 | } 113 | 114 | // USD 1 0.741 0.657 1.061 1.005 115 | pub fn parse_list_rates(i: &str) -> IResult<&str, (&str, Vec)> { 116 | let (i, name) = take_till(|c| c == ' ')(i)?; 117 | let (i, rates) = parse_list_float(i)?; 118 | Ok((i, (name, rates))) 119 | } 120 | 121 | enum SM { 122 | V, 123 | E, 124 | Edge, 125 | } 126 | 127 | impl SM { 128 | fn step(self) -> Self { 129 | match self { 130 | SM::V => Self::E, 131 | SM::E => Self::Edge, 132 | SM::Edge => Self::Edge, 133 | } 134 | } 135 | } 136 | 137 | #[test] 138 | fn t() { 139 | assert_eq!(parse_num("13"), Ok(("", 13))); 140 | // leading space 141 | assert_eq!(parse_num(" 13"), Ok(("", 13))); 142 | assert_eq!(parse_list_num("0 5"), Ok(("", vec![0, 5]))); 143 | // leading space 144 | assert_eq!(parse_list_num(" 0 5"), Ok(("", vec![0, 5]))); 145 | assert_eq!(parse_list_str("0 5", " "), Ok(("", vec!["0", "5"]))); 146 | assert_eq!(parse_list_str("LAS PHX", " "), Ok(("", vec!["LAS", "PHX"]))); 147 | assert_eq!( 148 | parse_list_str("aaa/bbb/ccc", "/"), 149 | Ok(("", vec!["aaa", "bbb", "ccc"])) 150 | ); 151 | assert_eq!( 152 | parse_list_str("aaa, (1991)/bbb, 111/ccc (C)", "/"), 153 | Ok(("", vec!["aaa, (1991)", "bbb, 111", "ccc (C)"])) 154 | ); 155 | assert_eq!(parse_list_float("4 5 0.35"), Ok(("", vec![4.0, 5.0, 0.35]))); 156 | assert_eq!( 157 | parse_list_float("41.0 3 1 7 9"), 158 | Ok(("", vec![41.0, 3.0, 1.0, 7.0, 9.0])) 159 | ); 160 | assert_eq!( 161 | parse_list_float("6 4 -1.25"), 162 | Ok(("", vec![6.0, 4.0, -1.25])) 163 | ); 164 | assert_eq!( 165 | parse_list_rates("USD 1 0.741 0.657 1.061 1.005"), 166 | Ok(("", ("USD", vec![1.0, 0.741, 0.657, 1.061, 1.005]))) 167 | ) 168 | } 169 | -------------------------------------------------------------------------------- /src/strings/quick3.rs: -------------------------------------------------------------------------------- 1 | //! Three-way string quicksort 2 | //! 3 | //! Adapt quicksort to MSD string sorting by using 3-way 4 | //! partitioning on the leading character of the keys, 5 | //! moving to the next character on only the middle 6 | //! subarray (keys with leading character equal to the 7 | //! partitioning character). 8 | //! 9 | //! ### Compare to MSD 10 | //! 11 | //! Three-way string quicksort divides the array into 12 | //! only three parts, so it involves more data movement 13 | //! than MSD string sort when the number of nonempty 14 | //! partitions is large because it has to 15 | //! do a series of 3-way partitions to get the effect of 16 | //! the multiway partition. On the other hand, MSD string 17 | //! sort can create large numbers of (empty) subarrays, 18 | //! whereas 3-way string quicksort always has just three. 19 | //! Thus, 3-way string quicksort adapts well to handling 20 | //! equal keys, keys with long common prefixes, keys that 21 | //! fall into a small range, and small arrays— all situations 22 | //! where MSD string sort runs slowly. Of particular importance 23 | //! is that the partitioning adapts to different kinds of structure 24 | //! in different parts of the key. Also, like quicksort, 3-way string 25 | //! quicksort does not use extra space (other than the implicit stack 26 | //! to support recursion), which is an important advantage over MSD 27 | //! string sort, which requires space for both frequency counts and 28 | //! an auxiliary array. 29 | 30 | #![allow(clippy::many_single_char_names)] 31 | use crate::{common, sort}; 32 | use std::cmp::Ordering; 33 | use std::marker::PhantomData; 34 | 35 | const CUTOFF: usize = 15; // cutoff to insertion sort 36 | 37 | /// The Quick3String provides static methods for sorting an 38 | /// array of strings using 3-way radix quicksort. 39 | pub struct Quick3String { 40 | _marker: PhantomData, 41 | } 42 | 43 | /// The Quick3Way provides static methods for sorting an 44 | /// array using quicksort with 3-way partitioning. 45 | pub struct Quick3Way { 46 | _marker: PhantomData, 47 | } 48 | 49 | impl Quick3String 50 | where 51 | T: AsRef, 52 | { 53 | /// Rearranges the array of strings in ascending order. 54 | pub fn sort(a: &mut [T]) { 55 | // Randomization. 56 | // As with any quicksort, it is generally worthwhile to 57 | // shuffle the array beforehand or to use a random paritioning 58 | // item by swapping the first item with a random one. The primary 59 | // reason to do so is to protect against worst-case performance 60 | // in the case that the array is already sorted or nearly sorted. 61 | common::util::shuffle(a); 62 | let n = a.len(); 63 | Self::do_sort(a, 0, n.saturating_sub(1), 0); 64 | } 65 | 66 | /// 3-way string quicksort a[lo..hi] starting at d-th character 67 | fn do_sort(a: &mut [T], lo: usize, hi: usize, d: usize) { 68 | if hi <= lo + CUTOFF { 69 | sort::insert::sort_dth(a, lo, hi, d); 70 | return; 71 | } 72 | 73 | let (mut lt, mut gt, mut i) = (lo, hi, lo + 1); 74 | let v = common::util::byte_at_checked(a[lo].as_ref(), d); 75 | while i <= gt { 76 | let t = common::util::byte_at_checked(a[i].as_ref(), d); 77 | match t.cmp(&v) { 78 | Ordering::Less => { 79 | a.swap(lt, i); 80 | lt += 1; 81 | i += 1; 82 | } 83 | Ordering::Greater => { 84 | a.swap(i, gt); 85 | gt -= 1; 86 | } 87 | Ordering::Equal => i += 1, 88 | } 89 | } 90 | 91 | // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi] 92 | Self::do_sort(a, lo, lt.saturating_sub(1), d); 93 | if v >= 0 { 94 | // moving to the next character on only the middle 1ubarray 95 | // (keys with leading character equal to the partitioning character) 96 | Self::do_sort(a, lt, gt, d + 1); 97 | } 98 | Self::do_sort(a, gt + 1, hi, d); 99 | } 100 | } 101 | 102 | impl Quick3Way 103 | where 104 | T: Ord + Clone, 105 | { 106 | /// Rearranges the array in ascending order, using the natural order. 107 | pub fn sort(a: &mut [T]) { 108 | common::util::shuffle(a); 109 | let n = a.len(); 110 | Self::do_sort(a, 0, n.saturating_sub(1)); 111 | } 112 | 113 | /// quicksort the subarray a[lo .. hi] using 3-way partitioning 114 | fn do_sort(a: &mut [T], lo: usize, hi: usize) { 115 | if hi <= lo { 116 | return; 117 | } 118 | 119 | let (mut lt, mut gt, mut i) = (lo, hi, lo + 1); 120 | let v = a[lo].clone(); 121 | while i <= gt { 122 | match a[i].cmp(&v) { 123 | Ordering::Less => { 124 | a.swap(lt, i); 125 | lt += 1; 126 | i += 1; 127 | } 128 | Ordering::Greater => { 129 | a.swap(i, gt); 130 | gt -= 1; 131 | } 132 | Ordering::Equal => i += 1, 133 | } 134 | } 135 | 136 | Self::do_sort(a, lo, lt.saturating_sub(1)); 137 | Self::do_sort(a, gt + 1, hi); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/graph/shortest/acyclic_sp.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::directed::Topological; 2 | use crate::graph::shortest::DirectedEdge; 3 | use crate::graph::IEWDigraph; 4 | 5 | /// The AcyclicSP represents a data type for solving the 6 | /// single-source shortest paths problem in edge-weighted directed acyclic 7 | /// graphs (DAGs). The edge weights can be positive, negative, or zero. 8 | /// This implementation uses a topological-sort based algorithm. 9 | pub struct AcyclicSP { 10 | dist_to: Vec, // dist_to[v] = distance of shortest s->v path 11 | edge_to: Vec>, // edge_to[v] = last edge on shortest s->v path 12 | } 13 | 14 | /// The AcyclicLP represents a data type for solving the 15 | /// single-source shortest paths problem in edge-weighted directed acyclic 16 | /// graphs (DAGs). The edge weights can be positive, negative, or zero. 17 | /// This implementation uses a topological-sort based algorithm. 18 | pub struct AcyclicLP { 19 | dist_to: Vec, // dist_to[v] = distance of longest s->v path 20 | edge_to: Vec>, // edge_to[v] = last edge on longest s->v path 21 | } 22 | 23 | impl AcyclicSP { 24 | pub fn new(g: &dyn IEWDigraph, s: usize) -> Result { 25 | let topological = Topological::from(g); 26 | if let Some(order) = topological.order() { 27 | let nv = g.V(); 28 | let mut sp = Self { 29 | dist_to: vec![f32::MAX; nv], 30 | edge_to: vec![None; nv], 31 | }; 32 | sp.dist_to[s] = 0.0; 33 | 34 | // let order: Vec = order.cloned().collect(); 35 | // println!("order = {:?}", order); 36 | 37 | for &v in order { 38 | for e in g.adj(v) { 39 | sp.relax(e); 40 | } 41 | } 42 | 43 | Ok(sp) 44 | } else { 45 | Err("Digraph is not acyclic.") 46 | } 47 | } 48 | 49 | /// Returns the length of a shortest path from the source vertex s to vertex v 50 | pub fn dist_to(&self, v: usize) -> f32 { 51 | self.dist_to[v] 52 | } 53 | 54 | /// Is there a path from the source vertex s to vertex v? 55 | pub fn has_path_to(&self, v: usize) -> bool { 56 | self.dist_to[v] < f32::MAX 57 | } 58 | 59 | /// Returns a shortest path from the source vertex s to vertex v 60 | pub fn path_to(&self, v: usize) -> Option> { 61 | if !self.has_path_to(v) { 62 | None 63 | } else { 64 | let mut path = Vec::new(); 65 | let mut edge = self.edge_to[v]; 66 | while let Some(e) = edge { 67 | path.push(e); 68 | edge = self.edge_to[e.from()]; 69 | } 70 | path.reverse(); 71 | Some(path) 72 | } 73 | } 74 | 75 | fn relax(&mut self, e: &DirectedEdge) { 76 | let v = e.from(); 77 | let w = e.to(); 78 | if self.dist_to[w] > self.dist_to[v] + e.weight() { 79 | self.dist_to[w] = self.dist_to[v] + e.weight(); 80 | self.edge_to[w] = Some(*e); 81 | } 82 | } 83 | } 84 | 85 | impl AcyclicLP { 86 | pub fn new(g: &dyn IEWDigraph, s: usize) -> Result { 87 | let topological = Topological::from(g); 88 | if let Some(order) = topological.order() { 89 | let nv = g.V(); 90 | let mut sp = Self { 91 | dist_to: vec![f32::MIN; nv], 92 | edge_to: vec![None; nv], 93 | }; 94 | sp.dist_to[s] = 0.0; 95 | 96 | // let order: Vec = order.cloned().collect(); 97 | // println!("order = {:?}", order); 98 | 99 | for &v in order { 100 | for e in g.adj(v) { 101 | sp.relax(e); 102 | } 103 | } 104 | 105 | Ok(sp) 106 | } else { 107 | Err("Digraph is not acyclic.") 108 | } 109 | } 110 | 111 | /// Returns the length of a longest path from the source vertex s to vertex v 112 | pub fn dist_to(&self, v: usize) -> f32 { 113 | self.dist_to[v] 114 | } 115 | 116 | /// Is there a path from the source vertex s to vertex v? 117 | pub fn has_path_to(&self, v: usize) -> bool { 118 | self.dist_to[v] > f32::MIN 119 | } 120 | 121 | /// Returns a longest path from the source vertex s to vertex v 122 | pub fn path_to(&self, v: usize) -> Option> { 123 | if !self.has_path_to(v) { 124 | None 125 | } else { 126 | let mut path = Vec::new(); 127 | let mut edge = self.edge_to[v]; 128 | while let Some(e) = edge { 129 | path.push(e); 130 | edge = self.edge_to[e.from()]; 131 | } 132 | path.reverse(); 133 | Some(path) 134 | } 135 | } 136 | 137 | /// relax edge e, but update if you find a *longer* path 138 | fn relax(&mut self, e: &DirectedEdge) { 139 | let v = e.from(); 140 | let w = e.to(); 141 | if self.dist_to[w] < self.dist_to[v] + e.weight() { 142 | self.dist_to[w] = self.dist_to[v] + e.weight(); 143 | self.edge_to[w] = Some(*e); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/strings/lsd.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | //! LSD string sort 3 | //! 4 | //! The first string-sorting method that we consider is known 5 | //! as least-significant-digit first (LSD) string sort. Consider 6 | //! the following motivating application: 7 | //! Suppose that a highway engineer sets up a device that records 8 | //! the license plate numbers of all vehicles using a busy highway 9 | //! for a given period of time and wants to know the number of 10 | //! different vehicles that used the highway. As you know from 11 | //! Section 2.1, one easy way to solve this problem is to sort the 12 | //! numbers, then make a pass through to count the different values, 13 | //! as in Dedup (page 490). License plates are a mixture of numbers 14 | //! and letters, so it is natural to represent them as strings. 15 | //! In the simplest situation (such as the California license 16 | //! plate examples at right) the strings all have the same number 17 | //! of characters. This situation is often found in sort 18 | //! applications—for example, telephone numbers, bank account numbers, 19 | //! and IP addresses are typically fixed-length strings. 20 | //! 21 | //! If the strings are each of length W, 22 | //! we sort the strings W times with key-indexed counting, using 23 | //! each of the positions as the key, proceeding from right to left. 24 | //! It is not easy, at first, to be convinced that the method produces 25 | //! a sorted array—in fact, it does not work at all unless the key-indexed 26 | //! count implementation is stable. 27 | //! 28 | //! Proposition B. LSD string sort stably sorts fixed-length strings. 29 | //! Proof: This fact depends crucially on the key-indexed counting 30 | //! implementation being stable, as indicated in Proposition A. 31 | //! After sorting keys on their i trailing characters (in a stable manner), 32 | //! we know that any two keys appear in proper order in the array ( 33 | //! considering just those characters) either because the first of their 34 | //! i trailing characters is different, in which case the sort on that 35 | //! character puts them in order, or because the first of their ith 36 | //! trailing characters is the same, in which case they are in order 37 | //! because of stability (and by induction, for i-1). 38 | 39 | const R_ASCII: usize = 256; // extend ASCII alphabet size 40 | const BITS_PER_BYTE: usize = 8; 41 | const R_I32: usize = 1 << BITS_PER_BYTE; 42 | 43 | /// The LSD provides static methods for sorting an 44 | /// array of w-character strings or 32-bit integers 45 | /// using LSD radix sort. 46 | pub struct LSD; 47 | 48 | impl LSD { 49 | /// Rearranges the array of w-character strings in ascending order. 50 | /// `a` the array to be sorted 51 | /// `w` the number of characters per string 52 | pub fn sort + Copy>(a: &mut [T], w: usize) { 53 | let n = a.len(); 54 | 55 | // a[0] just for init helper, no practical significance 56 | let mut aux = vec![a[0]; n]; 57 | 58 | for d in (0..w).rev() { 59 | // sort by key-indexed counting on d-th character 60 | 61 | // compute frequency counts 62 | let mut count = [0; R_ASCII + 1]; 63 | for it in a.iter().take(n) { 64 | let c = it.as_ref().as_bytes()[d]; 65 | count[c as usize + 1] += 1; 66 | } 67 | 68 | // compute cumulates 69 | for r in 0..R_ASCII { 70 | count[r + 1] += count[r]; 71 | } 72 | 73 | // move data 74 | for it in a.iter().take(n) { 75 | let c = it.as_ref().as_bytes()[d]; 76 | aux[count[c as usize]] = *it; 77 | count[c as usize] += 1; 78 | } 79 | 80 | // copy back 81 | a[..n].clone_from_slice(&aux[..n]); 82 | } 83 | } 84 | 85 | pub fn sort_i32(a: &mut [i32]) { 86 | let BITS = 32; 87 | let MASK = R_I32 - 1; 88 | let w = BITS / BITS_PER_BYTE; 89 | 90 | let n = a.len(); 91 | let mut aux = vec![0; n]; 92 | for d in 0..w { 93 | // compute frequency counts 94 | let mut count = [0; R_I32 + 1]; 95 | for it in a.iter().take(n) { 96 | let c = *it >> (BITS_PER_BYTE * d) & MASK as i32; 97 | count[c as usize + 1] += 1; 98 | } 99 | 100 | // compute cumulates 101 | for r in 0..R_I32 { 102 | count[r + 1] += count[r]; 103 | } 104 | 105 | // for most significant byte, 0x80-0xFF comes before 0x00-0x7F 106 | if d == w - 1 { 107 | let shift1 = count[R_I32] - count[R_I32 / 2]; 108 | let shift2 = count[R_I32 / 2]; 109 | for it in count.iter_mut().take(R_I32 / 2) { 110 | *it += shift1; 111 | } 112 | for it in count.iter_mut().take(R_I32).skip(R_I32 / 2) { 113 | *it -= shift2; 114 | } 115 | } 116 | 117 | // move data 118 | for it in a.iter().take(n) { 119 | let c = *it >> (BITS_PER_BYTE * d) & MASK as i32; 120 | aux[count[c as usize]] = *it; 121 | count[c as usize] += 1; 122 | } 123 | 124 | // copy back 125 | a[..n].clone_from_slice(&aux[..n]); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /tests/test_common.rs: -------------------------------------------------------------------------------- 1 | use algo::common::{ 2 | IndexPQ, Queue, QuickFindUF, QuickUnionUF, Stack, TopM, WeightedQuickUnionUF, PQ, UF, 3 | }; 4 | use std::str::FromStr; 5 | 6 | const TOBE: &'static str = include_str!("../res/common/tobe.txt"); 7 | const TINY_UF: &'static str = include_str!("../res/common/tinyUF.txt"); 8 | // const M_UF: &'static str = include_str!("../res/common/mediumUF.txt"); 9 | 10 | #[test] 11 | fn queue() { 12 | let v: Vec<&str> = TOBE.split(' ').collect(); 13 | let mut queue = Queue::default(); 14 | let mut r = Vec::new(); 15 | for s in v { 16 | match s { 17 | "-" => { 18 | if let Some(s) = queue.dequeue() { 19 | r.push(s); 20 | } 21 | } 22 | _ => queue.enqueue(s), 23 | } 24 | } 25 | 26 | assert_eq!("to be or not to be", r.join(" ")); 27 | assert_eq!(2, queue.len()); 28 | } 29 | 30 | #[test] 31 | fn stack() { 32 | let v: Vec<&str> = TOBE.split(' ').collect(); 33 | let mut stack = Stack::default(); 34 | let mut r = Vec::new(); 35 | for s in v { 36 | match s { 37 | "-" => { 38 | if let Some(s) = stack.pop() { 39 | r.push(s); 40 | } 41 | } 42 | _ => stack.push(s), 43 | } 44 | } 45 | 46 | assert_eq!("to be not that or be", r.join(" ")); 47 | assert_eq!(2, stack.len()); 48 | } 49 | 50 | #[test] 51 | fn min_pq() { 52 | //case-1, test insert & del_min 53 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 54 | let mut min_pq = PQ::new_min_pq(t.len()); 55 | for v in &t { 56 | min_pq.enqueue(*v); 57 | } 58 | assert!(!min_pq.is_empty()); 59 | assert_eq!(t.len(), min_pq.len()); 60 | assert_eq!(Some(1), min_pq.peek().cloned()); 61 | for v in vec![1, 2, 3, 4, 7, 8, 9, 10, 14, 16] { 62 | assert_eq!(min_pq.dequeue(), Some(v)); 63 | } 64 | assert!(min_pq.is_empty()); 65 | assert_eq!(0, min_pq.len()); 66 | assert_eq!(None, min_pq.peek()); 67 | assert_eq!(min_pq.dequeue(), None); 68 | } 69 | 70 | #[test] 71 | fn max_pq() { 72 | //case-1, test insert & del_max 73 | let t = vec![4, 1, 3, 2, 16, 9, 10, 14, 8, 7]; 74 | let mut max_pq = PQ::new_max_pq(t.len()); 75 | for v in &t { 76 | max_pq.enqueue(*v); 77 | } 78 | assert!(!max_pq.is_empty()); 79 | assert_eq!(t.len(), max_pq.len()); 80 | assert_eq!(Some(16), max_pq.peek().cloned()); 81 | for v in vec![16, 14, 10, 9, 8, 7, 4, 3, 2, 1] { 82 | assert_eq!(max_pq.dequeue(), Some(v)); 83 | } 84 | assert!(max_pq.is_empty()); 85 | assert_eq!(0, max_pq.len()); 86 | assert_eq!(None, max_pq.peek()); 87 | assert_eq!(max_pq.dequeue(), None); 88 | } 89 | 90 | #[test] 91 | fn index_min_pq() { 92 | fn queue(i: &str) -> Queue<&str> { 93 | let mut queue = Queue::default(); 94 | for s in i.split_whitespace() { 95 | queue.enqueue(s); 96 | } 97 | queue 98 | } 99 | let mut inputs = vec![ 100 | queue("A B C F G I I Z"), 101 | queue("B D H P Q Q"), 102 | queue("A B E F J N"), 103 | ]; 104 | 105 | // init 106 | let mut pq = IndexPQ::new_min_pq(inputs.len()); 107 | for i in 0..inputs.len() { 108 | if let Some(v) = inputs[i].dequeue() { 109 | let _ = pq.enqueue(i, v); 110 | } 111 | } 112 | 113 | let mut vec = Vec::new(); 114 | while !pq.is_empty() { 115 | vec.push(pq.peek_key().unwrap().to_string()); 116 | let i = pq.dequeue().unwrap(); 117 | if let Some(v) = inputs[i as usize].dequeue() { 118 | let _ = pq.enqueue(i as usize, v); 119 | } 120 | } 121 | assert_eq!("A A B B B C D E F F G H I I J N P Q Q Z", vec.join(" ")); 122 | } 123 | 124 | #[test] 125 | fn index_max_pq() { 126 | fn queue(i: &str) -> Queue<&str> { 127 | let mut queue = Queue::default(); 128 | for s in i.split_whitespace() { 129 | queue.enqueue(s); 130 | } 131 | queue 132 | } 133 | let mut inputs = vec![ 134 | queue("A B C F G I I Z"), 135 | queue("B D H P Q Q"), 136 | queue("A B E F J N"), 137 | ]; 138 | 139 | // init 140 | let mut pq = IndexPQ::new_max_pq(inputs.len()); 141 | for i in 0..inputs.len() { 142 | if let Some(v) = inputs[i].dequeue() { 143 | let _ = pq.enqueue(i, v); 144 | } 145 | } 146 | 147 | let mut vec = Vec::new(); 148 | while !pq.is_empty() { 149 | vec.push(pq.peek_key().unwrap().to_string()); 150 | let i = pq.dequeue().unwrap(); 151 | if let Some(v) = inputs[i as usize].dequeue() { 152 | let _ = pq.enqueue(i as usize, v); 153 | } 154 | } 155 | assert_eq!("B D H P Q Q A B E F J N A B C F G I I Z", vec.join(" ")); 156 | } 157 | 158 | #[test] 159 | fn quick_find_uf() { 160 | let i = TINY_UF; 161 | 162 | let uf = QuickFindUF::from_str(i).unwrap(); 163 | assert_eq!(2, uf.count()); 164 | 165 | let uf = QuickUnionUF::from_str(i).unwrap(); 166 | assert_eq!(2, uf.count()); 167 | 168 | let uf = WeightedQuickUnionUF::from_str(i).unwrap(); 169 | assert_eq!(2, uf.count()); 170 | 171 | let uf = UF::from_str(i).unwrap(); 172 | assert_eq!(2, uf.count()); 173 | } 174 | 175 | #[test] 176 | fn top_m() { 177 | let mut top = TopM::new(5); 178 | for v in 0..100 { 179 | top.insert(v); 180 | } 181 | assert_eq!(vec![99, 98, 97, 96, 95], top.into_vec()); 182 | } 183 | -------------------------------------------------------------------------------- /src/tree/binary/builder/tournament.rs: -------------------------------------------------------------------------------- 1 | use crate::tree::binary::builder::TreeBuilder; 2 | use crate::tree::binary::node::Node; 3 | use crate::tree::binary::tree::Tree; 4 | use crate::tree::binary::NodeQuery; 5 | use std::cmp::max; 6 | use std::ptr::NonNull; 7 | 8 | pub trait BuildTournamentTree { 9 | fn build_tournament_tree(data: &[K]) -> Tree; 10 | fn tournament_tree_pop(tree: &mut Tree) -> Option; 11 | } 12 | 13 | impl BuildTournamentTree for TreeBuilder 14 | where 15 | K: Copy + std::cmp::Ord + Minimal, 16 | { 17 | fn build_tournament_tree(data: &[K]) -> Tree { 18 | do_build(data) 19 | } 20 | 21 | fn tournament_tree_pop(tree: &mut Tree) -> Option { 22 | pop(tree) 23 | } 24 | } 25 | 26 | pub trait Minimal { 27 | fn minimal() -> Self; 28 | } 29 | 30 | impl Minimal for i32 { 31 | fn minimal() -> Self { 32 | i32::MIN 33 | } 34 | } 35 | 36 | fn pop(tree: &mut Tree) -> Option 37 | where 38 | K: Copy + std::cmp::Ord + Minimal, 39 | { 40 | let nq = NodeQuery::new(tree.root); 41 | match nq.get_key() { 42 | Some(key) if *key != K::minimal() => { 43 | let key = *key; 44 | // 每次取出锦标赛树的根节点后,自顶向下将其替换为min 45 | let leaf = replace_max_by_min(nq.node.unwrap(), key); 46 | // 由叶子节点向上回溯,设置新的最大值 47 | setup_new_max(leaf); 48 | Some(key) 49 | } 50 | _ => None, 51 | } 52 | } 53 | 54 | // 返回叶子节点的序号 55 | fn replace_max_by_min(node: NonNull>, root_key: K) -> NonNull> 56 | where 57 | K: Copy + std::cmp::Ord + Minimal, 58 | { 59 | let mut nq = NodeQuery::new(Some(node)); 60 | nq.set_entry((K::minimal(), None)); 61 | 62 | while nq.is_branch() { 63 | nq = if nq.left_key() == Some(&root_key) { 64 | nq.left() 65 | } else { 66 | nq.right() 67 | }; 68 | 69 | nq.set_entry((K::minimal(), None)); 70 | } 71 | 72 | nq.node.unwrap() 73 | } 74 | 75 | fn setup_new_max(node: NonNull>) 76 | where 77 | K: Copy + std::cmp::Ord, 78 | { 79 | let mut nq = NodeQuery::new_parent(Some(node)); 80 | while nq.is_some() { 81 | let mut new_max = *nq.get_key().unwrap(); 82 | if let Some(v) = nq.left_key() { 83 | new_max = new_max.max(*v); 84 | } 85 | if let Some(v) = nq.right_key() { 86 | new_max = new_max.max(*v); 87 | } 88 | nq.set_entry((new_max, None)); 89 | nq = nq.parent(); 90 | } 91 | } 92 | 93 | /// 构建锦标赛树, from bottom to top 94 | /// a中不能包含T::minimal()这个特殊值,pop需要用到T::minimal()做临界值 95 | fn do_build(data: &[K]) -> Tree 96 | where 97 | K: Copy + std::cmp::Ord, 98 | { 99 | //build leaf 100 | let mut nodes: Vec>> = data.iter().map(|v| Node::new_key(*v)).collect(); 101 | while nodes.len() > 1 { 102 | nodes = nodes 103 | .chunks(2) 104 | .map(|chunk| match *chunk { 105 | [t1, t2] => unsafe { branch(t1, t2) }, 106 | [t] => t, 107 | _ => unreachable!(), 108 | }) 109 | .collect(); 110 | } 111 | 112 | let mut tree = Tree::default(); 113 | tree.root = nodes.first().cloned(); 114 | tree 115 | } 116 | 117 | /// 创建分支节点,取t1, t2较大者的value构造parent 118 | unsafe fn branch( 119 | mut n1: NonNull>, 120 | mut n2: NonNull>, 121 | ) -> NonNull> 122 | where 123 | K: Copy + std::cmp::Ord, 124 | { 125 | let v = max(n1.as_ref().key, n2.as_ref().key); 126 | let node = Node::new(v, None, Some(n1), Some(n2), None); 127 | n1.as_mut().parent = Some(node); 128 | n2.as_mut().parent = Some(node); 129 | node 130 | } 131 | 132 | #[test] 133 | fn t_build_tree() { 134 | /* 135 | 16 136 | / \ 137 | 16 14 138 | / \ / \ 139 | 16 13 10 14 140 | / \ / \ / \ / \ 141 | 7 16 8 13 10 9 12 14 142 | / \ / \ / \ / \ / \ / \ / \ / \ 143 | 7 6 15 16 8 4 13 3 5 10 9 1 12 2 11 14 144 | 145 | */ 146 | let a = &[7, 6, 15, 16, 8, 4, 13, 3, 5, 10, 9, 1, 12, 2, 11, 14]; 147 | 148 | let tree: Tree = do_build(a); 149 | let r = unsafe { crate::tree::binary::traverse::PreOrderVisitor::recursive(&tree) }; 150 | assert_eq!( 151 | r, 152 | vec![ 153 | 16, 16, 16, 7, 7, 6, 16, 15, 16, 13, 8, 8, 4, 13, 13, 3, 14, 10, 10, 5, 10, 9, 9, 1, 154 | 14, 12, 12, 2, 14, 11, 14 155 | ] 156 | ); 157 | 158 | let r = unsafe { crate::tree::binary::traverse::InOrderVisitor::recursive(&tree) }; 159 | assert_eq!( 160 | r, 161 | vec![ 162 | 7, 7, 6, 16, 15, 16, 16, 16, 8, 8, 4, 13, 13, 13, 3, 16, 5, 10, 10, 10, 9, 9, 1, 14, 163 | 12, 12, 2, 14, 11, 14, 14 164 | ] 165 | ); 166 | } 167 | 168 | #[test] 169 | fn t_pop() { 170 | let mut a = vec![7, 6, 15, 16, 8, 4, 13, 3, 5, 10, 9, 1, 12, 2, 11, 14]; 171 | let mut tree: Tree = do_build(&a); 172 | 173 | //make a desc sorted 174 | a.sort(); 175 | a.reverse(); 176 | 177 | for v in a { 178 | assert_eq!(pop(&mut tree), Some(v)); 179 | } 180 | 181 | assert_eq!(pop(&mut tree), None); 182 | } 183 | -------------------------------------------------------------------------------- /src/graph/shortest/dijkstra_sp.rs: -------------------------------------------------------------------------------- 1 | //! Dijkstra's algorithm. Computes the shortest path tree. 2 | //! Assumes all weights are non-negative. 3 | 4 | use crate::common::IndexPQ; 5 | use crate::graph::shortest::DirectedEdge; 6 | use crate::graph::IEWDigraph; 7 | 8 | pub struct DijkstraSP { 9 | dist_to: Vec, // distTo[v] = distance of shortest s->v path 10 | edge_to: Vec>, // edgeTo[v] = last edge on shortest s->v path 11 | pq: IndexPQ, // priority queue of vertices 12 | } 13 | 14 | /// The DijkstraAllPairsSP represents a data type for solving the 15 | /// all-pairs shortest paths problem in edge-weighted digraphs 16 | /// where the edge weights are non-negative. 17 | pub struct DijkstraAllPairsSP { 18 | all: Vec, 19 | } 20 | 21 | impl DijkstraSP { 22 | pub fn new(g: &dyn IEWDigraph, s: usize) -> Self { 23 | for e in g.edges() { 24 | if e.weight() < 0.0 { 25 | panic!("edge {} has negative weight", e.to_string()); 26 | } 27 | } 28 | 29 | let gv = g.V(); 30 | let mut sp = Self { 31 | dist_to: vec![f32::MAX; gv], 32 | edge_to: vec![None; gv], 33 | pq: IndexPQ::new_min_pq(gv), 34 | }; 35 | 36 | sp.dist_to[s] = 0.0; 37 | let _ = sp.pq.enqueue(s, sp.dist_to[s]); 38 | while !sp.pq.is_empty() { 39 | let v = sp.pq.dequeue().unwrap(); 40 | for e in g.adj(v) { 41 | sp.relax(e); 42 | } 43 | } 44 | 45 | sp 46 | } 47 | 48 | // relax edge e and update pq if changed 49 | fn relax(&mut self, e: &DirectedEdge) { 50 | let v = e.from(); 51 | let w = e.to(); 52 | if self.dist_to[w] > self.dist_to[v] + e.weight() { 53 | self.dist_to[w] = self.dist_to[v] + e.weight(); 54 | self.edge_to[w] = Some(*e); 55 | if self.pq.contains(w) { 56 | let _ = self.pq.decrease_key(w, self.dist_to[w]); 57 | } else { 58 | let _ = self.pq.enqueue(w, self.dist_to[w]); 59 | } 60 | } 61 | } 62 | 63 | /// Returns the length of a shortest path from the source vertex s to vertex v 64 | pub fn dist_to(&self, v: usize) -> f32 { 65 | self.dist_to[v] 66 | } 67 | 68 | /// Returns true if there is a path from the source vertex s to vertex v 69 | pub fn has_path_to(&self, v: usize) -> bool { 70 | self.dist_to[v] < f32::MAX 71 | } 72 | 73 | /// Returns a shortest path from the source vertex s to vertex v 74 | pub fn path_to(&self, v: usize) -> Option> { 75 | if !self.has_path_to(v) { 76 | None 77 | } else { 78 | let mut path = Vec::new(); 79 | let mut edge = self.edge_to[v]; 80 | while let Some(e) = edge { 81 | path.push(e); 82 | edge = self.edge_to[e.from()]; 83 | } 84 | path.reverse(); 85 | Some(path) 86 | } 87 | } 88 | 89 | pub fn check(&self, g: &dyn IEWDigraph, s: usize) -> Result<(), String> { 90 | for e in g.edges() { 91 | if e.weight() < 0.0 { 92 | return Err("negative edge weight detected".to_string()); 93 | } 94 | } 95 | 96 | // check that dist_to[v] and edge_to[v] are consistent 97 | if self.dist_to[s] != 0.0 || self.edge_to[s].is_some() { 98 | return Err("dist_to[s] and edge_to[s] inconsistent".to_string()); 99 | } 100 | for v in 0..g.V() { 101 | if v == s { 102 | continue; 103 | } 104 | if self.edge_to[v].is_none() && self.dist_to[v] != f32::MAX { 105 | return Err("dist_to[s] and edge_to[s] inconsistent".to_string()); 106 | } 107 | } 108 | 109 | // check that all edges e = v->w satisfy dist_to[w] <= dist_to[v] + e.weight() 110 | for v in 0..g.V() { 111 | for e in g.adj(v) { 112 | let w = e.to(); 113 | if self.dist_to[v] + e.weight() < self.dist_to[w] { 114 | return Err(format!("edge {} no relaxed", e.to_string())); 115 | } 116 | } 117 | } 118 | 119 | // check that all edges e = v->w on SPT satisfy dist_to[w] == dist_to[v] + e.weight() 120 | for w in 0..g.V() { 121 | if self.edge_to[w].is_none() { 122 | continue; 123 | } 124 | let e = self.edge_to[w].unwrap(); 125 | let v = e.from(); 126 | if (self.dist_to[v] + e.weight() - self.dist_to[w]).abs() > f32::EPSILON { 127 | return Err(format!("edge {} on shortest path not tight", e.to_string())); 128 | } 129 | } 130 | 131 | Ok(()) 132 | } 133 | } 134 | 135 | impl DijkstraAllPairsSP { 136 | /// Computes a shortest paths tree from each vertex to to every other vertex in 137 | /// the edge-weighted digraph 138 | pub fn new(g: &dyn IEWDigraph) -> Self { 139 | let mut all = Vec::with_capacity(g.V()); 140 | for v in 0..g.V() { 141 | all.push(DijkstraSP::new(g, v)); 142 | } 143 | Self { all } 144 | } 145 | 146 | /// Returns a shortest path from vertex s to vertex t 147 | pub fn path(&self, s: usize, t: usize) -> Option> { 148 | self.all[s].path_to(t) 149 | } 150 | 151 | /// Is there a path from the vertex s to vertex t? 152 | pub fn has_path(&self, s: usize, t: usize) -> bool { 153 | self.all[s].dist_to(t) < f32::MAX 154 | } 155 | 156 | /// Returns the length of a shortest path from vertex s to vertex t 157 | pub fn dist(&self, s: usize, t: usize) -> f32 { 158 | self.all[s].dist_to(t) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Overview 2 | 3 | This repository contains the Rust source code 4 | for the algorithms in the textbook 5 | [Algorithms, 4th Edition](http://amzn.to/13VNJi7) 6 | by Robert Sedgewick and Kevin Wayne. 7 | 8 | The official Java source code is 9 | [here](https://github.com/kevin-wayne/algs4). 10 | 11 | ### Goals 12 | 13 | Make a Rust implementation of the library so that 14 | a Rust programmer can follow this book easily or 15 | prefer to demonstrate the algorithms using Rust. 16 | 17 | Try to keep the interface and variable name consistent 18 | with the original book while writing idiomatic rust 19 | code. 20 | 21 | I hope that this project helped you understand why 22 | Rust is so wonderful and loved right now. Rust is proving 23 | to be a productive tool for reliable and efficient software. 24 | In Rust, the compiler plays 25 | a gatekeeper role by refusing to compile code with 26 | these elusive bugs, including concurrency bugs. 27 | By working alongside the compiler, you can spend your 28 | time focusing on the program’s logic rather than 29 | chasing down bugs. After you finish a day's work, 30 | go home and rest, can be at ease a good night's sleep, 31 | never worry about system crash. 32 | 33 | ### Index 34 | 35 | The table index [follow](https://algs4.cs.princeton.edu/code/). 36 | 37 | | 1 | FUNDAMENTALS | | 38 | |-----|----------------------|----------------------------------| 39 | | 1.2 | Stack | LIFO stack | 40 | | 1.3 | Queue | FIFO queue | 41 | | 1.4 | LinkedList | multiset (linked list) | 42 | | 1.5 | QuickFindUF | quick find | 43 | | - | QuickUnionUF | quick union | 44 | | - | WeightedQuickUnionUF | weighted quick union | 45 | | - | UF | union-by-rank with path halving | 46 | | 2 | SORTING | | 47 | | 2.1 | insert.rs | insertion sort | 48 | | 2.2 | selection.rs | selection sort | 49 | | 2.3 | shell.rs | shellsort | 50 | | 2.4 | merge.rs | Merge Sort | 51 | | 2.5 | quick.rs | quicksort | 52 | | - | Quick3Way | quicksort with 3-way partitioning | 53 | | 2.6 | PQ::new_max_pq | max heap priority queue | 54 | | - | PQ::new_min_pq | min heap priority queue | 55 | | - | IndexPQ::new_min_pq | index min heap priority queue | 56 | | - | IndexPQ::new_max_pq | index max heap priority queue | 57 | | - | TopM | Find the largest M elements | 58 | | 2.7 | floyd.rs | heapsort | 59 | | 3 | SEARCHING | | 60 | | 3.4 | rb2.rs | red-black tree | 61 | | 3.6 | SparseVector | sparse vector | 62 | | 4 | GRAPHS | | 63 | | - | Graph | undirected graph | 64 | | - | DepthFirstSearch | depth-first search in a graph | 65 | | - | NonRecursiveDFS | DFS in a graph (nonrecursive) | 66 | | 4.1 | DepthFirstPaths | paths in a graph (DFS) | 67 | | 4.2 | BreadthFirstPaths | paths in a graph (BFS) | 68 | | 4.3 | CC | connected components of a graph | 69 | | - | Bipartite | bipartite or odd cycle (DFS) | 70 | | - | Cycle | cycle in a graph | 71 | | - | SymbolGraph | symbol graph | 72 | | - | Digraph | directed graph | 73 | | 4.4 | DepthFirstPaths | paths in a digraph (DFS) | 74 | | - | BreadthFirstPaths | paths in a digraph (BFS) | 75 | | - | DirectedCycle | cycle in a digraph | 76 | | 4.5 | Topological | topological order in a DAG | 77 | | - | TransitiveClosure | transitive closure | 78 | | 4.6 | KosarajuSCC | strong components (Kosaraju–Sharir) | 79 | | - | EWGraph | edge-weighted graph | 80 | | - | LazyPrimMST | MST (lazy Prim) | 81 | | 4.7 | PrimMST | MST (Prim) | 82 | | 4.8 | KruskalMST | MST (Kruskal) | 83 | | - | EdgeWeightedDigraphCycle | edge-weighted digraph | 84 | | 4.9 | DijkstraSP | shortest paths (Dijkstra) | 85 | | - | DijkstraAllPairsSP | all-pairs shortest paths | 86 | | 4.10 | AcyclicSP | shortest paths in a DAG | 87 | | - | AcyclicLP | longest paths in a DAG | 88 | | - | CPM | critical path method | 89 | | 4.11 | BellmanFordSP | shortest paths (Bellman–Ford) | 90 | | - | Arbitrage | arbitrage detection | 91 | | 5 | STRINGS | | 92 | | - | Alphabet | alphabet | 93 | | - | count.rs | alphabet client | 94 | | 5.1 | LSD | LSD radix sort | 95 | | 5.2 | MSD | MSD radix sort | 96 | | 5.3 | Quick3String | 3-way string quicksort | 97 | | 5.4 | TrieST | multiway trie symbol table | 98 | | 5.5 | TST | ternary search trie | 99 | | 5.6 | KMP | substring search (Knuth–Morris–Pratt) | 100 | 101 | 102 | 103 | ### Running 104 | 105 | ``` 106 | # setup Rust Toolchain 107 | make test 108 | ``` 109 | 110 | ### Roadmap 111 | 112 | - Implement algorithms in the textbook 113 | [Algorithms, 4th Edition](http://amzn.to/13VNJi7) 114 | - Algorithms visualization (Easy to study and short learning curve) --------------------------------------------------------------------------------