I am trying to implement the quick sort algorithm for an array of i32. My question is about an apparent inconsistency in the use of &mut when passing in arrays to functions. My code:
fn main() {
let mut my_array = [5, 2, 8, 7];
let high = my_array.len() - 1;
quick_sort(&mut my_array, 0, high);
print!("{:?}", my_array);
}
fn quick_sort(array: &mut [i32], low: usize, high: usize) {
let pivot_idx = partition(array, low, high);
// Separately sort elements before partition and after partition
if pivot_idx > low {
quick_sort(array, low, pivot_idx - 1);
}
if pivot_idx < high {
quick_sort(array, pivot_idx + 1, high);
}
}
fn partition(array: &mut [i32], low: usize, high: usize) -> usize {
let pivot = array[high]; // pivot
let mut i = low;
for j in low..high {
// If current element is less than or equal to pivot
if array[j] <= pivot {
let swapper_variable = array[i];
array[i] = array[j];
array[j] = swapper_variable;
i += 1; // increment index of smaller element
}
}
let swapper_variable = array[i];
array[i] = array[high];
array[high] = swapper_variable;
return i;
}
My code works, but should it? In main I call quick_sort with quick_sort(&mut my_array, 0, high)
, but the recursive call within quick_sort is quick_sort(array, low, pivot_idx - 1)
, without the &mut.
Furthermore, also within quick_sort, I call partition with partition(array, low, high)
, but partition takes a mutable array as an argument and I haven't specified &mut in the call! If I do try to put &mut in the partition function call, the code will not compile:
error[E0596]: cannot borrow `array` as mutable, as it is not declared as mutable
--> src/main.rs:9:31
|
8 | fn quick_sort(array: &mut [i32], low: usize, high: usize) {
| ----- help: consider changing this to be mutable: `mut array`
9 | let pivot_idx = partition(&mut array, low, high);
| ^^^^^^^^^^ cannot borrow as mutable
So it seems there's some confusion as to what's mutable, the array itself or the pointer(?) to the array. But it seems to me that I should be able to call functions within quick_sort in the same manner that I called quick_sort originally from main. As far as I know, the point of forcing &mut to be explicitly placed in the function call is that doing so makes it easy to see that the called function might modify the argument, but the calls within quick_sort give no indication that they modify the array.
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=62813cd1bd23d8b1a36d6126d4305800