1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use ManuallyDrop;
use ptr;
/// Sorts a slice in place using bubble sort.
///
/// Each pass walks the unsorted prefix from left to right, carrying the largest element
/// seen so far towards the end until it meets an element that is not smaller than it.
/// After a pass, everything from the position of the last move onwards is in its final
/// place, so the next pass stops there; a pass that moves nothing ends the sort.
///
/// Two refinements keep the algorithm as cheap as bubble sort can be:
///
/// * **Last-move tracking.** The next pass scans only up to the last element that moved,
/// so already-sorted input finishes after a single pass of `n - 1` comparisons and
/// partially sorted tails are never rescanned.
/// * **Hole shifting instead of swapping.** An element travelling `k` slots to the right is
/// read once, the `k` smaller elements are each shifted left by one, and the element is
/// written once into its final slot: `k + 1` moves instead of the `3k` moves of `k` swaps.
///
/// The number of comparisons is exactly that of classic bubble sort with early exit.
///
/// # Properties
///
/// * **Stable**: equal elements keep their relative order (only strictly smaller elements
/// are overtaken).
/// * **In place**: `O(1)` auxiliary memory, no allocation.
/// * **Adaptive**: the cost grows with how far elements are from their sorted positions.
///
/// | Case | Comparisons | Moves |
/// |---------------------------|-------------|--------|
/// | Best (already sorted) | `O(n)` | `0` |
/// | Average | `O(n²)` | `O(n²)`|
/// | Worst (reverse sorted) | `O(n²)` | `O(n²)`|
///
/// Bubble sort is quadratic and is mainly of educational value; prefer
/// [`slice::sort`] for real workloads.
///
/// # Panics
///
/// Does not panic by itself. If the [`Ord`] implementation of `T` panics, the panic is
/// propagated and `arr` is left in an unspecified order, but it still holds every original
/// element exactly once: nothing is dropped twice or leaked.
///
/// # Examples
///
/// ```
/// use a::sort::bubble;
///
/// let mut v = [5, 1, 4, 2, 8, 0];
/// bubble(&mut v);
/// assert_eq!(v, [0, 1, 2, 4, 5, 8]);
///
/// let mut words = vec!["pear", "apple", "fig"];
/// bubble(&mut words);
/// assert_eq!(words, ["apple", "fig", "pear"]);
/// ```
/// An element temporarily moved out of a slice, plus the slot it will be written back to.
///
/// Writing back on drop is what keeps [`bubble`] panic-safe: the slice is whole again even
/// if a comparison unwinds while the element is out.