Performance 如何在Rust中合并列表的两个元素?

Performance 如何在Rust中合并列表的两个元素?,performance,optimization,rust,Performance,Optimization,Rust,我一直在努力优化我的代码的一部分,我发现我可以利用一些社区智慧。我实际上是在尝试合并一个列表的两个元素,而不移动列表中的元素(通过两个删除和一个插入),因为就我所知,在一个向量中这样做需要O(n)个时间 请看一下捕获问题本质的代码: 使用std::cell::RefCell; 使用std::rc::rc; 使用std::collections::BinaryHeap; #[推导(PartialOrd、Ord、PartialEq、Eq)] 发布结构数{ pub num:usize } impl N

我一直在努力优化我的代码的一部分,我发现我可以利用一些社区智慧。我实际上是在尝试合并一个列表的两个元素,而不移动列表中的元素(通过两个删除和一个插入),因为就我所知,在一个向量中这样做需要O(n)个时间

请看一下捕获问题本质的代码:

使用std::cell::RefCell;
使用std::rc::rc;
使用std::collections::BinaryHeap;
#[推导(PartialOrd、Ord、PartialEq、Eq)]
发布结构数{
pub num:usize
}
impl Num{
pub fn new(num:usize)->num{
Num{
号码
}
}
}
fn main(){
设mut a=vec![];
因为我在0..10{
a、 推送(Rc::new(RefCell::new(Num::new(i)));
}
设mut b=binarycheap::with_capacity(a.len());
对于0..a.len()-1中的i{
b、 推送(i,Rc::clone(&a[i]),Rc::clone(&a[i+1]);
}
下降(a);
while!b.是空的(){
设c=b.pop().unwrap();
设first=c.1;
设next=c.2;
println!(“c:c.0:{}”,c.0);
println!(({}之前的c:first.num),RefCell::borrow(&first.num);
println!(({}之前的c:next.num),RefCell::borrow(&next.num);
//在这里,我想替换在first和next中引用的两个结构
//使用第一个和下一个都指向的单个新结构。

//例如,首先->新建数量我对您的需求的理解是,您需要
Vec
能够保存作为值或对另一个项目的引用的项目,同时保持与您提供的结构类似的结构

我们可以通过将您的项目类型更改为
枚举
,对其进行建模,该枚举可以保存一个值或对另一个项目的引用:

pub enum Num {
    Raw(usize),
    Ref(Rc<RefCell<Num>>),
}
您可以在其他节点中引用它,如下所示:

let new_num = Rc::new(RefCell::new(Num::new(100)));
*first.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
*next.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::BinaryHeap;

#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub enum Num {
    Raw(usize),
    Ref(Rc<RefCell<Num>>),
}

impl Num {
    pub fn new(num: usize) -> Num {
        Num::Raw(num)
    }

    pub fn new_ref(other: Rc<RefCell<Num>>) -> Num {
        Num::Ref(other)    
    }

    pub fn get_num(&self) -> usize {
        match &self {
            Num::Raw(n) => *n,
            Num::Ref(r) => r.borrow().get_num()
        }
    }
}

fn main() {
    let mut a = vec![];
    for i in 0..10 {
        a.push(Rc::new(RefCell::new(Num::new(i))));
    }
    let mut b = BinaryHeap::with_capacity(a.len());
    for i in 0..a.len() - 1 {
        b.push((i, Rc::clone(&a[i]), Rc::clone(&a[i + 1])));
    }

    drop(a);

    let new_num = Rc::new(RefCell::new(Num::new(100)));

    while !b.is_empty() {
        let c = b.pop().unwrap();
        let first = c.1;
        let next = c.2;
        println!("c: c.0: {}", c.0);
        println!("c: first.num before: {}", RefCell::borrow(&first).get_num());
        println!("c: next.num before: {}", RefCell::borrow(&next).get_num());

        *first.borrow_mut() = Num::new_ref(Rc::clone(&new_num))
        *next.borrow_mut() = Num::new_ref(Rc::clone(&new_num))

        println!("c: first.num after: {}", RefCell::borrow(&first).get_num());
        println!("c: next.num after: {}", RefCell::borrow(&next).get_num());
        assert_eq!(RefCell::borrow(&first).get_num(), RefCell::borrow(&next).get_num());
    }
}
完整代码如下所示:

let new_num = Rc::new(RefCell::new(Num::new(100)));
*first.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
*next.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::BinaryHeap;

#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub enum Num {
    Raw(usize),
    Ref(Rc<RefCell<Num>>),
}

impl Num {
    pub fn new(num: usize) -> Num {
        Num::Raw(num)
    }

    pub fn new_ref(other: Rc<RefCell<Num>>) -> Num {
        Num::Ref(other)    
    }

    pub fn get_num(&self) -> usize {
        match &self {
            Num::Raw(n) => *n,
            Num::Ref(r) => r.borrow().get_num()
        }
    }
}

fn main() {
    let mut a = vec![];
    for i in 0..10 {
        a.push(Rc::new(RefCell::new(Num::new(i))));
    }
    let mut b = BinaryHeap::with_capacity(a.len());
    for i in 0..a.len() - 1 {
        b.push((i, Rc::clone(&a[i]), Rc::clone(&a[i + 1])));
    }

    drop(a);

    let new_num = Rc::new(RefCell::new(Num::new(100)));

    while !b.is_empty() {
        let c = b.pop().unwrap();
        let first = c.1;
        let next = c.2;
        println!("c: c.0: {}", c.0);
        println!("c: first.num before: {}", RefCell::borrow(&first).get_num());
        println!("c: next.num before: {}", RefCell::borrow(&next).get_num());

        *first.borrow_mut() = Num::new_ref(Rc::clone(&new_num))
        *next.borrow_mut() = Num::new_ref(Rc::clone(&new_num))

        println!("c: first.num after: {}", RefCell::borrow(&first).get_num());
        println!("c: next.num after: {}", RefCell::borrow(&next).get_num());
        assert_eq!(RefCell::borrow(&first).get_num(), RefCell::borrow(&next).get_num());
    }
}
使用std::cell::RefCell;
使用std::rc::rc;
使用std::collections::BinaryHeap;
#[推导(PartialOrd、Ord、PartialEq、Eq)]
发布枚举数{
原始(使用),
参考文献(Rc),
}
impl Num{
pub fn new(num:usize)->num{
Num::Raw(Num)
}
发布fn新参考(其他:Rc)->Num{
Num::Ref(其他)
}
pub fn get_num(&self)->usize{
匹配与自我{
Num::原始(n)=>*n,
Num::Ref(r)=>r.borrow().get_Num()
}
}
}
fn main(){
设mut a=vec![];
因为我在0..10{
a、 推送(Rc::new(RefCell::new(Num::new(i)));
}
设mut b=binarycheap::with_capacity(a.len());
对于0..a.len()-1中的i{
b、 推送(i,Rc::clone(&a[i]),Rc::clone(&a[i+1]);
}
下降(a);
让new_num=Rc::new(RefCell::new(num::new(100));
while!b.是空的(){
设c=b.pop().unwrap();
设first=c.1;
设next=c.2;
println!(“c:c.0:{}”,c.0);
println!(({}之前的c:first.num),RefCell::borrow(&first).get_num());
println!(({}之前的c:next.num),RefCell::borrow(&next).get_num());
*first.borrow_mut()=Num::new_ref(Rc::clone(&new_Num))
*next.borrow_mut()=Num::new_ref(Rc::clone(&new_Num))
println!(({}之后的c:first.num),RefCell::borrow(&first).get_num());
println!(({}之后的c:next.num),RefCell::borrow(&next).get_num());
assert_eq!(RefCell::borrow(&first).get_num(),RefCell::borrow(&next).get_num());
}
}


至于这是否会证明比另一种方法的性能更好,很难说。您的起点似乎相当复杂,如果您可以简化这一点并使用不同的底层数据结构,那么您应该尝试使用它并进行基准测试。O(n)的实际速度经常让我感到惊讶在
Vec
上的操作,即使其大小约为1000项或更多。

您可能考虑过多,使其变得比需要的复杂得多。要准确地查看您要查找的内容有点困难,但可能您只需要一个不同的数据结构,例如
VecDeque
。类似这样的东西?为什么
Vec
BinaryHeap
都涉及吗?当你说你想编辑列表中的元素时,你是指
Vec
还是
BinaryHeap
?这让我很困惑。在
中,while
循环
first
next
不再是任何列表的成员,因为
a
已经被删除了删除并从
b
中弹出它们。因此,如果需要,您可以重新分配它们(
first=new\u num;next=new\u num;
)测试将通过。但听起来你想对其他未显示的数据结构产生副作用?或者你想对堆中的其他元素产生副作用?我不明白。我投票结束你的问题,因为昨天我就不清楚了,我不明白。请毫不犹豫地澄清你的问题。它应该是be注意到,虽然在本例中它似乎过于复杂,但它代表了在create_tree中找到的一段更为精细的代码。我一直在对结果进行基准测试,到目前为止,通过朝这个方向前进,速度提高了约30%。感谢您简洁的回答。@ChosunOne好的,很公平!听起来像是进步。