diff --git a/sort/benches/bubble_sort.rs b/sort/benches/bubble_sort.rs index f2a038ed..76128546 100644 --- a/sort/benches/bubble_sort.rs +++ b/sort/benches/bubble_sort.rs @@ -11,7 +11,7 @@ fn criterion_benchmark(c: &mut Criterion) { for exp in 1..5 { let len: usize = 2 * 10_usize.pow(exp); let arr = random_ints(len).expect("Failed to generate random integers"); - let title1 = format!("std_sort {len}"); + let title1 = format!("std_sort_for_bubble_sort {len}"); let title2 = format!("bubble_sort {len}"); let title3 = format!("bubble_sort_recursive {len}"); let mut arr_sorted = arr.clone(); diff --git a/sort/benches/insertion_sort.rs b/sort/benches/insertion_sort.rs index a0fc6957..f16d9822 100644 --- a/sort/benches/insertion_sort.rs +++ b/sort/benches/insertion_sort.rs @@ -11,7 +11,7 @@ fn criterion_benchmark(c: &mut Criterion) { for exp in 1..5 { let len: usize = 2 * 10_usize.pow(exp); let arr = random_ints(len).expect("Failed to generate random integers"); - let title1 = format!("std_sort {len}"); + let title1 = format!("std_sort_for_insertion_sort {len}"); let title2 = format!("insertion_sort {len}"); c.bench_function(&title1, |b| b.iter(|| { diff --git a/sort/benches/selection_sort.rs b/sort/benches/selection_sort.rs index c594fe53..66fbb4f5 100644 --- a/sort/benches/selection_sort.rs +++ b/sort/benches/selection_sort.rs @@ -11,7 +11,7 @@ fn criterion_benchmark(c: &mut Criterion) { for exp in 1..5 { let len: usize = 2 * 10_usize.pow(exp); let arr = random_ints(len).expect("Failed to generate random integers"); - let title1 = format!("std_sort {len}"); + let title1 = format!("std_sort_for_selection_sort {len}"); let title2 = format!("selection_sort {len}"); let title3 = format!("selection_sort_recursive {len}"); let title4 = format!("selection_sort_min_max {len}"); diff --git a/sort/src/insertion_sort.rs b/sort/src/insertion_sort.rs index 4f36ec6b..ad17d58a 100644 --- a/sort/src/insertion_sort.rs +++ b/sort/src/insertion_sort.rs @@ -2,14 +2,7 @@ // Use of this source is governed by General Public License that can be // found in the LICENSE file. -/// Place one element at a time, inserting each into its proper place. -/// -/// The elements to the left of the current index are in sorted order during -/// the sort, but they are not in their final positions, as they may have to -/// be moved to make room for smaller elements later. -/// -/// 其思路是, 先将前 i 个元素调整为增序的, 随着 i 从 0 增大到 n, 整个序列 -/// 就变得是增序了. +/// 其思路是, 先将前 i 个元素调整为增序的, 随着 i 从 0 增大到 n, 整个序列就变得是增序了. pub fn insertion_sort(list: &mut [T]) where T: PartialOrd, diff --git a/src/SUMMARY.md b/src/SUMMARY.md index eb414b81..bb91b0bd 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -38,6 +38,7 @@ - [双链表](list/double.md) - [链表排序 Sort](list/sort/index.md) - [冒泡排序 Bubble Sort](list/sort/bubble-sort.md) + - [插入排序 Insertion Sort](list/sort/insertion-sort.md) - [选择排序 Selection Sort](list/sort/selection-sort.md) - [标准库中 List 的实现](list/impl-oflist.md) - [跳跃表 SkipList](list/skiplist/index.md) diff --git a/src/array/sort/assets/insertion-sort-pass1.drawio b/src/array/sort/assets/insertion-sort-pass1.drawio new file mode 100644 index 00000000..fe3b6420 --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass1.drawio @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/array/sort/assets/insertion-sort-pass1.svg b/src/array/sort/assets/insertion-sort-pass1.svg new file mode 100644 index 00000000..1c990e49 --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass1.svg @@ -0,0 +1,3 @@ + + +
9
4
1
7
4
9
1
7
\ No newline at end of file diff --git a/src/array/sort/assets/insertion-sort-pass2.drawio b/src/array/sort/assets/insertion-sort-pass2.drawio new file mode 100644 index 00000000..b75c343f --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass2.drawio @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/array/sort/assets/insertion-sort-pass2.svg b/src/array/sort/assets/insertion-sort-pass2.svg new file mode 100644 index 00000000..56f66345 --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass2.svg @@ -0,0 +1,3 @@ + + +
4
9
1
7
4
1
9
7
1
4
9
7
\ No newline at end of file diff --git a/src/array/sort/assets/insertion-sort-pass3.drawio b/src/array/sort/assets/insertion-sort-pass3.drawio new file mode 100644 index 00000000..105a1347 --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass3.drawio @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/array/sort/assets/insertion-sort-pass3.svg b/src/array/sort/assets/insertion-sort-pass3.svg new file mode 100644 index 00000000..67e84ad2 --- /dev/null +++ b/src/array/sort/assets/insertion-sort-pass3.svg @@ -0,0 +1,3 @@ + + +
1
4
9
7
1
4
7
9
\ No newline at end of file diff --git a/src/array/sort/assets/insertion_sort.rs b/src/array/sort/assets/insertion_sort.rs new file mode 120000 index 00000000..3942cb43 --- /dev/null +++ b/src/array/sort/assets/insertion_sort.rs @@ -0,0 +1 @@ +../../../../sort/src/insertion_sort.rs \ No newline at end of file diff --git a/src/array/sort/bubble-sort.md b/src/array/sort/bubble-sort.md index 6aa3fb70..46a3cf81 100644 --- a/src/array/sort/bubble-sort.md +++ b/src/array/sort/bubble-sort.md @@ -38,6 +38,8 @@ 2. 将最大的元素移到数组最右侧 3. 递归调用冒泡排序, 但忽略数组的最右侧元素 +递归形式的冒泡排序算法需要额外占用 `O(n)` 的内存空间, 用于递归函数调用栈. + ```rust {{#include assets/bubble_sort.rs:29:55}} ``` diff --git a/src/array/sort/insertion-sort.md b/src/array/sort/insertion-sort.md index 16e34356..021d88dc 100644 --- a/src/array/sort/insertion-sort.md +++ b/src/array/sort/insertion-sort.md @@ -1,16 +1,42 @@ # 插入排序 Insertion Sort +插入排序实现方法比较简单. +它一次排序一个元素, 将数组分成两部分, 左侧部分是有序的, 右侧部分是待排序的. + ## 插入排序的步骤 +1. 从第二个元素开始遍历数组, 因为数组中的第一个元素是有序的 +2. 将第二个元素与第一个元素比较, 如果比第一个元素小, 就交换两者的位置 +3. 将第三个元素与第二个位置的元素比较, 如果比它小, 就交换位置, 并重复第2步 +4. 继续以上的步骤, 将无序元素与前面的有序的元素进行比较以及交换位置 +5. 重复操作, 直到整个数组都是有序的 + +第一阶段, 将第二个元素 `4` 与第一个元素 `9` 进行比较, 并交换位置: + +![insertion sort pass 1](assets/insertion-sort-pass1.svg) + +第二阶段, 将第三个元素 `1` 与前面的元素比较, 并交换位置: + +![insertion sort pass 2](assets/insertion-sort-pass2.svg) + +第三阶段, 将第四个元素 `7` 与前面的元素比较并交换位置: + +![insertion sort pass 3](assets/insertion-sort-pass3.svg) + ## 插入排序的实现 +```rust +{{#include assets/insertion_sort.rs:5:20}} +``` + ## 插入排序的特点 - 时间复杂度是 `O(N^2)`, 空间复杂度是 `O(1)` - 如果传入的数据是增序排好的, 那么只需要 N-1 次的比较, 以及 0 次的交换 - 如果传入的数据是降序排好的, 那么需要 N^2/2 次的比较, 以及 N^2/2 次的交换 - 如果是乱序的, 大概需要 N^2/4 次的比较, 以及 N^2/4 次的交换 -- 插入排序是稳定排序 +- 插入排序是稳定排序 (stable sort) +- 它是原地排序 in-place sort - 插入排序比较适合元素较少的数组 - 插入排序适合基本已排序好的数组 - 插入排序常用于组合排序算法中, 用于排序较少元素的部分数组; 比如 cpp 里面的 `std::sort()` 以及 python diff --git a/src/list/sort/insertion-sort.md b/src/list/sort/insertion-sort.md new file mode 100644 index 00000000..46a18acb --- /dev/null +++ b/src/list/sort/insertion-sort.md @@ -0,0 +1 @@ +# 插入排序 Insertion Sort \ No newline at end of file