MCPcopy Create free account
hub / github.com/QMHTMY/RustBook / merge_collapse

Method merge_collapse

publication/code/chapter07/tim_sort.rs:577–616  ·  view source on GitHub ↗

合并 run 使得 A > B + C、B > C 如果 A <= B + C,则 A 和 C 中较小的和 B 合并 如果只有 A、B,则 A <= B 时 A 和 B 合并

(&mut self)

Source from the content-addressed store, hash-verified

575 // 如果 A <= B + C,则 A 和 C 中较小的和 B 合并
576 // 如果只有 A、B,则 A <= B 时 A 和 B 合并
577 fn merge_collapse(&mut self) {
578 let runs = &mut self.runs;
579 while runs.len() > 1 {
580 let n = runs.len() - 2;
581
582 // 判断 A、B、C、D 的关系,加入 D 是为了防止特殊情况的 Bug
583 // A <= B + C || D <= A + B
584 if (n >= 1 && runs[n - 1].len <= runs[n].len + runs[n + 1].len)
585 || (n >= 2 && runs[n - 2].len <= runs[n].len + runs[n - 1].len)
586 {
587 // 三个连续的 run: A、B、C,判断其长度关系并进行合并
588 // n - 1 对应 A、 n 对应 B、n + 1 对应 C
589 let (pos1, pos2) = if runs[n - 1].len < runs[n + 1].len {
590 (n - 1, n) // A B 合并
591 } else {
592 (n, n + 1) // B C 合并
593 };
594
595 // 取出待合并的 run1 和 run2
596 let (run1, run2) = (runs[pos1], runs[pos2]);
597 debug_assert_eq!(run1.pos + run1.len, run2.pos);
598
599 // 合并 run1 和 run2 到 run1,其实就是更新 run1 的参数并删除 run2,
600 // run1 下标不变,但合并后长度是 run1 和 run2 长度之和
601 runs.remove(pos2);
602 runs[pos1] = Run {
603 pos: run1.pos,
604 len: run1.len + run2.len,
605 };
606
607 // 取出合并后的 run1 去进行归并排序
608 let new_list = self.list
609 .split_at_mut(run1.pos).1
610 .split_at_mut(run1.len + run2.len).0;
611 merge_sort(new_list, run1.len);
612 } else {
613 break;
614 }
615 }
616 }
617
618 // 集合处理完了就强制合并剩余的 run 到只剩下一个 run
619 fn merge_force_collapse(&mut self) {

Callers 1

sortMethod · 0.45

Calls 3

merge_sortFunction · 0.70
lenMethod · 0.45
removeMethod · 0.45

Tested by

no test coverage detected