我想在Rust中创建一个就地的heapsort函数。在标准库中,我发现std::collections::BinaryHeap
看起来很有前景。我可以使用它来创建一个消耗其参数的函数:
use std::collections::BinaryHeap;
fn heapsort<T: Ord>(list: Vec<T>) -> Vec<T> {
let heap = BinaryHeap::from(list);
heap.into_sorted_vec()
}
文档声明“将向量转换为二进制堆可以就地完成”,但是我在创建一个可以在引用上工作并且可以就地执行(heapsort<T: Ord>(list: &mut Vec<T>)
)时遇到问题。我可以仅使用std::collections::BinaryHeap
来实现吗?
答案 0 :(得分:3)
您可以mem::replace
使用&#34;移动&#34; &mut
引用后面的内容:
use std::collections::BinaryHeap;
use std::mem;
fn heapsort<T: Ord>(list: &mut Vec<T>) {
let tmp = mem::replace(list, Vec::new());
let heap = BinaryHeap::from(tmp);
*list = heap.into_sorted_vec();
}
因此,在短时间内*list
等于空向量。在这种情况下,没关系,因为创建和删除空的Vec
非常便宜。
*mutref
值,而不会在借用期间就地使用虚拟值。但我现在无法找到它。它看起来像这样:
fn heapsort<T: Ord>(list: &mut Vec<T>) {
borrow_by_value(list, |tmp| {
BinaryHeap::from(tmp).into_sorted_vec()
});
}
其中borrow_by_value
使用一些不安全的代码(可能是ptr::read
)来按行提供Vec
,并将Vec
带回*list
更不安全的代码(可能是ptr::write
)。实际的实现可能会有点复杂,以保护您不要以某种方式恐慌。我不知道。如果没有,你可能应该避免使用它。
答案 1 :(得分:1)
我无法创建一个可以在引用上工作的内容并且可以就地执行
BinaryHeap
is built on top of Vec
。从Vec
创建新堆时,必须为其提供完整的所有权。然后它将确保向量处于良好状态以充当堆。
由于BinaryHeap
不是建立在&mut Vec
之上(大多数情况下会出现可怕的人体工程学),所以你不能这样做。
目前还不清楚为什么不在向量上使用slice::sort
。
文档声明“将矢量转换为二进制堆可以就地完成”
为了澄清,文档是正确的 - 有no extra memory allocation needed,因此它就位。重要的方面是BinaryHeap
拥有其数据,并不会将所有内部信息公开给全世界。
您要求的是能够在用户提供的向量上调用rebuild
。对我而言,这具有可疑的用处,但您可以随时提交RFC以公开它。