Skip to content

Commit c9cb78e

Browse files
committed
merge utils
1 parent 903480d commit c9cb78e

File tree

21 files changed

+165
-120
lines changed

21 files changed

+165
-120
lines changed

CheatSheet.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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+

benches/sort.rs

+44-21
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#![feature(test)]
22
extern crate test;
33

4-
use algo::sort;
5-
use algo::sort::util;
64
use algo::strings::Quick3Way;
5+
use algo::{common, sort};
76
use test::Bencher;
87

8+
static DATA_LEN: usize = 1000;
9+
910
#[bench]
1011
fn small_merge_v1(b: &mut Bencher) {
1112
b.iter(|| {
@@ -16,7 +17,7 @@ fn small_merge_v1(b: &mut Bencher) {
1617

1718
#[bench]
1819
fn large_merge_v1(b: &mut Bencher) {
19-
let data = util::random_data(util::DATA_LEN);
20+
let data = gen_random_data(DATA_LEN);
2021
b.iter(|| {
2122
let mut numbs = data.clone();
2223
sort::merge::v1::sort(&mut numbs);
@@ -25,7 +26,7 @@ fn large_merge_v1(b: &mut Bencher) {
2526

2627
#[bench]
2728
fn large_sorted_asc_merge_v1(b: &mut Bencher) {
28-
let data = util::sorted_data_asc(util::DATA_LEN);
29+
let data = gen_asc_data(DATA_LEN);
2930
b.iter(|| {
3031
let mut numbs = data.clone();
3132
sort::merge::v1::sort(&mut numbs);
@@ -34,7 +35,7 @@ fn large_sorted_asc_merge_v1(b: &mut Bencher) {
3435

3536
#[bench]
3637
fn large_sorted_desc_merge_v1(b: &mut Bencher) {
37-
let data = util::sorted_data_desc(util::DATA_LEN);
38+
let data = gen_desc_data(DATA_LEN);
3839
b.iter(|| {
3940
let mut numbs = data.clone();
4041
sort::merge::v1::sort(&mut numbs);
@@ -43,7 +44,7 @@ fn large_sorted_desc_merge_v1(b: &mut Bencher) {
4344

4445
#[bench]
4546
fn eq_data_merge_v1(b: &mut Bencher) {
46-
let data = util::eq_data(util::DATA_LEN);
47+
let data = gen_eq_data(DATA_LEN);
4748
b.iter(|| {
4849
let mut numbs = data.clone();
4950
sort::merge::v1::sort(&mut numbs);
@@ -60,7 +61,7 @@ fn small_merge_v2(b: &mut Bencher) {
6061

6162
#[bench]
6263
fn large_merge_v2(b: &mut Bencher) {
63-
let data = util::random_data(util::DATA_LEN);
64+
let data = gen_random_data(DATA_LEN);
6465
b.iter(|| {
6566
let mut numbs = data.clone();
6667
sort::merge::v2::sort(&mut numbs);
@@ -69,7 +70,7 @@ fn large_merge_v2(b: &mut Bencher) {
6970

7071
#[bench]
7172
fn large_sorted_asc_merge_v2(b: &mut Bencher) {
72-
let data = util::sorted_data_asc(util::DATA_LEN);
73+
let data = gen_asc_data(DATA_LEN);
7374
b.iter(|| {
7475
let mut numbs = data.clone();
7576
sort::merge::v2::sort(&mut numbs);
@@ -78,7 +79,7 @@ fn large_sorted_asc_merge_v2(b: &mut Bencher) {
7879

7980
#[bench]
8081
fn large_sorted_desc_merge_v2(b: &mut Bencher) {
81-
let data = util::sorted_data_desc(util::DATA_LEN);
82+
let data = gen_desc_data(DATA_LEN);
8283
b.iter(|| {
8384
let mut numbs = data.clone();
8485
sort::merge::v2::sort(&mut numbs);
@@ -87,7 +88,7 @@ fn large_sorted_desc_merge_v2(b: &mut Bencher) {
8788

8889
#[bench]
8990
fn eq_data_merge_v2(b: &mut Bencher) {
90-
let data = util::eq_data(util::DATA_LEN);
91+
let data = gen_eq_data(DATA_LEN);
9192
b.iter(|| {
9293
let mut numbs = data.clone();
9394
sort::merge::v2::sort(&mut numbs);
@@ -104,7 +105,7 @@ fn small_merge_v3(b: &mut Bencher) {
104105

105106
#[bench]
106107
fn large_merge_v3(b: &mut Bencher) {
107-
let data = util::random_data(util::DATA_LEN);
108+
let data = gen_random_data(DATA_LEN);
108109
b.iter(|| {
109110
let mut numbs = data.clone();
110111
sort::merge::v3::sort(&mut numbs);
@@ -113,7 +114,7 @@ fn large_merge_v3(b: &mut Bencher) {
113114

114115
#[bench]
115116
fn large_sorted_asc_merge_v3(b: &mut Bencher) {
116-
let data = util::sorted_data_asc(util::DATA_LEN);
117+
let data = gen_asc_data(DATA_LEN);
117118
b.iter(|| {
118119
let mut numbs = data.clone();
119120
sort::merge::v3::sort(&mut numbs);
@@ -122,7 +123,7 @@ fn large_sorted_asc_merge_v3(b: &mut Bencher) {
122123

123124
#[bench]
124125
fn large_sorted_desc_merge_v3(b: &mut Bencher) {
125-
let data = util::sorted_data_desc(util::DATA_LEN);
126+
let data = gen_desc_data(DATA_LEN);
126127
b.iter(|| {
127128
let mut numbs = data.clone();
128129
sort::merge::v3::sort(&mut numbs);
@@ -131,7 +132,7 @@ fn large_sorted_desc_merge_v3(b: &mut Bencher) {
131132

132133
#[bench]
133134
fn eq_data_merge_v3(b: &mut Bencher) {
134-
let data = util::eq_data(util::DATA_LEN);
135+
let data = gen_eq_data(DATA_LEN);
135136
b.iter(|| {
136137
let mut numbs = data.clone();
137138
sort::merge::v3::sort(&mut numbs);
@@ -148,7 +149,7 @@ fn small_quick(b: &mut Bencher) {
148149

149150
#[bench]
150151
fn large_quick(b: &mut Bencher) {
151-
let data = util::random_data(util::DATA_LEN);
152+
let data = gen_random_data(DATA_LEN);
152153
b.iter(|| {
153154
let mut numbs = data.clone();
154155
sort::quick::sort(&mut numbs);
@@ -157,7 +158,7 @@ fn large_quick(b: &mut Bencher) {
157158

158159
#[bench]
159160
fn large_quick_3way(b: &mut Bencher) {
160-
let data = util::random_data(util::DATA_LEN);
161+
let data = gen_random_data(DATA_LEN);
161162
b.iter(|| {
162163
let mut numbs = data.clone();
163164
Quick3Way::sort(&mut numbs);
@@ -166,7 +167,7 @@ fn large_quick_3way(b: &mut Bencher) {
166167

167168
#[bench]
168169
fn large_sorted_asc_quick(b: &mut Bencher) {
169-
let data = util::sorted_data_asc(util::DATA_LEN);
170+
let data = gen_asc_data(DATA_LEN);
170171
b.iter(|| {
171172
let mut numbs = data.clone();
172173
sort::quick::sort(&mut numbs);
@@ -175,7 +176,7 @@ fn large_sorted_asc_quick(b: &mut Bencher) {
175176

176177
#[bench]
177178
fn large_sorted_desc_quick(b: &mut Bencher) {
178-
let data = util::sorted_data_desc(util::DATA_LEN);
179+
let data = gen_desc_data(DATA_LEN);
179180
b.iter(|| {
180181
let mut numbs = data.clone();
181182
sort::quick::sort(&mut numbs);
@@ -184,7 +185,7 @@ fn large_sorted_desc_quick(b: &mut Bencher) {
184185

185186
#[bench]
186187
fn eq_data_quick(b: &mut Bencher) {
187-
let data = util::eq_data(util::DATA_LEN);
188+
let data = gen_eq_data(DATA_LEN);
188189
b.iter(|| {
189190
let mut numbs = data.clone();
190191
sort::quick::sort(&mut numbs);
@@ -209,7 +210,7 @@ fn small_selection_tree_selection(b: &mut Bencher) {
209210

210211
#[bench]
211212
fn large_selection_sort(b: &mut Bencher) {
212-
let data = util::random_data(util::DATA_LEN);
213+
let data = gen_random_data(DATA_LEN);
213214
b.iter(|| {
214215
let mut numbs = data.clone();
215216
sort::selection::sort(&mut numbs);
@@ -218,9 +219,31 @@ fn large_selection_sort(b: &mut Bencher) {
218219

219220
#[bench]
220221
fn large_selection_tree_selection(b: &mut Bencher) {
221-
let data = util::random_data(util::DATA_LEN);
222+
let data = gen_random_data(DATA_LEN);
222223
b.iter(|| {
223224
let numbs = data.clone();
224225
sort::tree_selection::sort_desc(&numbs);
225226
});
226227
}
228+
229+
// utils
230+
231+
fn gen_random_data(len: usize) -> Vec<i32> {
232+
let mut data: Vec<i32> = (0..len as i32).collect();
233+
common::util::shuffle(&mut data);
234+
data
235+
}
236+
237+
pub fn gen_asc_data(len: usize) -> Vec<i32> {
238+
(0..len as i32).collect()
239+
}
240+
241+
pub fn gen_desc_data(len: usize) -> Vec<i32> {
242+
let mut data = gen_asc_data(len);
243+
data.reverse();
244+
data
245+
}
246+
247+
pub fn gen_eq_data(len: usize) -> Vec<i32> {
248+
vec![100; len]
249+
}

benches/strings.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#![feature(test)]
22
extern crate test;
33

4-
use algo::strings::{util, Quick3String, LSD, MSD};
4+
use algo::common;
5+
use algo::strings::{Quick3String, LSD, MSD};
56
use test::Bencher;
67

78
const WORDS3: &'static str = include_str!("../res/strings/words3.txt");
@@ -80,7 +81,7 @@ fn MSD_worst_case(b: &mut Bencher) {
8081
#[bench]
8182
fn MSD_best_case(b: &mut Bencher) {
8283
// all strings equal, need check all chars
83-
let words = util::vec_alphabet("1DNB377".len());
84+
let words = common::util::vec_alphabet("1DNB377".len());
8485
let mut words: Vec<&str> = words.iter().map(|it| it.as_str()).collect();
8586
b.iter(|| {
8687
MSD::sort(&mut words);

src/common/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod queue;
44
mod stack;
55
mod top_m;
66
mod uf;
7+
pub mod util;
78

89
pub use priority_queue::{IndexPQ, PQ};
910
pub use queue::Queue;

src/strings/util.rs renamed to src/common/util.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
use rand;
2+
use rand::prelude::SliceRandom;
3+
4+
pub fn shuffle<T>(data: &mut [T]) {
5+
let mut rng = rand::thread_rng();
6+
data.shuffle(&mut rng);
7+
}
8+
19
// n, item length
210
// n = 1, vec!["a", "b", ... "z"]
311
// n = 2, vec!["aa", "bb", ... "zz"]

src/graph/directed/transitive_closure.rs

-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
//!
88
//! Compute transitive closure of a digraph and support
99
//! reachability queries.
10-
//!
11-
//! Preprocessing time: O(V(E + V)) time.
12-
//! Query time: O(1).
13-
//! Space: O(V^2).
1410
1511
use crate::graph::directed::DirectedDFS;
1612
use crate::graph::IGraph;

src/graph/mst/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@
2828
//! color its minimum-weight edge black, and continue until V - 1 edges
2929
//! have been colored black.
3030
//!
31-
//! | algorithm | space | time |
32-
//! |------------------------------------
33-
//! | lazy Prim | E | E log E |
34-
//! | eager Prim | V | E log V |
35-
//! | Kruskal | E | E log E |
3631
3732
mod edge;
3833
mod ew_graph;

src/graph/undirected/cc.rs

-10
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,6 @@
1111
//! vertices in the connected component: two vertices have the same component
1212
//! identifier if and only if they are in the same connected component.
1313
//!
14-
//! This implementation uses depth-first search.
15-
//! The constructor takes O(V + E) time,
16-
//! where *V* is the number of vertices and *E* is the
17-
//! number of edges.
18-
//! Each instance method takes O(1) time.
19-
//! It uses O(V) extra space (not including the graph).
20-
//!
21-
//! Compute connected components using depth first search.
22-
//! Runs in O(E + V) time.
23-
//!
2414
//! This implementation uses a recursive DFS. To avoid needing
2515
//! a potentially very large stack size, replace with a non recursive
2616
//! DFS ala NonRecursiveDFS

src/graph/undirected/cycle.rs

-10
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,6 @@
22
//! determining whether an undirected graph has a simple cycle.
33
//! The *has_cycle* operation determines whether the graph has
44
//! a cycle and, if so, the *cycle* operation returns one.
5-
//!
6-
//! This implementation uses depth-first search.
7-
//! The constructor takes O(V + E) time in the
8-
//! worst case, where *V* is the number of vertices and
9-
//! *E* is the number of edges.
10-
//! (The depth-first search part takes only *O(V)* time;
11-
//! however, checking for self-loops and parallel edges takes
12-
//! O(V + E) time in the worst case.)
13-
//! Each instance method takes O(1) time.
14-
//! It uses O(V) extra space (not including the graph).
155
166
use crate::common::Stack;
177
use crate::graph::IGraph;

src/graph/undirected/graph.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
//! - We must have the space to accommodate the types of graphs
1010
//! that we are likely to encounter in applications.
1111
//! - We want to develop time-efficient implementations of Graph
12-
//! instance meth- ods—the basic methods that we need to develop
13-
//! graph-processing clients.
12+
//! instance methods the basic methods that we need to develop
13+
//! graph processing clients.
1414
//!
1515
//! These requirements are a bit vague, but they are still helpful
1616
//! in choosing among the three data structures that immediately

src/sort/bubble.rs

-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
//! 顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会
1010
//! 上浮到顶端一样,故名“冒泡排序”。
1111
//!
12-
//! 若初始状态有序,时间复杂度 O(n)
13-
//! 若初始状态反序,时间复杂度 O(n^2)
14-
//! 稳定排序算法
1512
1613
pub fn sort<T>(a: &mut [T])
1714
where

src/sort/insert.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ where
99
T: Ord,
1010
{
1111
let len = a.len();
12-
// 注意起始索引
12+
// i begins with `1`
1313
for i in 1..len {
14-
// 将a[i]插入到a[i-1],a[i-2],a[i-3]……之中
14+
// insert a[i] into a[0..i-1]
1515
let mut j = i;
1616
while j > 0 && a[j] < a[j - 1] {
1717
a.swap(j, j - 1);
@@ -21,11 +21,13 @@ where
2121
}
2222

2323
/// insertion sort a[lo..=hi], starting at d-th character
24+
/// lo & hi, is inclusive
2425
pub fn sort_dth<T>(a: &mut [T], lo: usize, hi: usize, d: usize)
2526
where
2627
T: AsRef<str>,
2728
{
28-
for i in lo..=hi {
29+
// i begin with `lo + 1`
30+
for i in lo + 1..=hi {
2931
let mut j = i;
3032
while j > lo && is_less(a[j].as_ref(), a[j - 1].as_ref(), d) {
3133
a.swap(j, j - 1);

src/sort/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ pub mod quick;
66
pub mod selection;
77
pub mod shell;
88
pub mod tree_selection;
9-
pub mod util;

src/sort/quick.rs

-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
//! 其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按
66
//! 此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,
77
//! 以此达到整个数据变成有序序列
8-
//!
9-
//! 理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,
10-
//! 经过log2(n)趟划分,便可得到长度为1的子表。这样,整个算法
11-
//! 的时间复杂度为O(n * log2(n))
128
139
pub fn sort<T>(a: &mut [T])
1410
where

0 commit comments

Comments
 (0)