如何在 Rust 中使用 Arc<Mutex> 从向量构造链表

问题描述 投票:0回答:1

任务很简单:从向量构造一个链表。链接列表应支持多线程。

我的第一次尝试是迭代向量,设置一个指向链表末尾的指针,在每个步骤中创建新节点并根据需要进行链接。然而 Rust 的借用检查器让它变得非常麻烦。

这是代码:

// dummy struct for simplicity
struct LinkedList {
    next: Option<Arc<Mutex<LinkedList>>>,
    val: u32,
}

fn main() {
    let vec_int: Vec<u32> = vec![1, 2, 3, 4, 5];

    let normal_res = LinkedList { next: None, val: 0 };
    // head pointer
    let mut head = Arc::new(Mutex::new(normal_res));
    for (i, val) in vec_int.iter().enumerate() {
        // the first one is different: fill in the created LinkedList
        if i == 0 {
            (*head).lock().unwrap().val = *val;
            continue;
        }

        // create new LinkedList and link it
        let next = LinkedList {
            next: None,
            val: *val,
        };
        (*head).lock().unwrap().next = Some(Arc::new(Mutex::new(next)));

        // make head into the pointer to the proper child, but it will not work

        // error: use of moved value
        head = Arc::new(Mutex::new(next));

        // error: can not assign to head because it is borrowed
        head = (*head).lock().unwrap().next.as_ref().unwrap().clone();
        // I have tried many more ways of manipulating the pointers, all failed
    }
}

我的第二次尝试有效,但不是最佳选择,因为它必须反转向量。

fn main(){
    let mut reversed = Arc::new(Mutex::new(LinkedList { next: None, val: 0 }));
    for (i, val) in vec_int.iter().rev().enumerate() {
        if i == 0 {
            (*reversed).lock().unwrap().val = *val;
            continue;
        }
        // assign the next
        reversed = Arc::new(Mutex::new(LinkedList {
            next: Some(reversed.clone()),
            val: *val,
        }));
    }
}

我找到了同一主题的几个答案和教程,但他们的方法似乎不适用于

Arc<Mutex>

答案1:无法分配给变量,因为它是借用的

答案 2:从 Vec 创建 ListNode,并引用第一个节点

非常感谢任何帮助。

rust data-structures linked-list
1个回答
0
投票

当您使用

Arc
时,大多数所有权问题都可以通过使用
Arc::clone(&)
来规避。

这是代码

fn main() {
    let vec_int: Vec<u32> = vec![1, 2, 3, 4, 5];

    let normal_res = LinkedList { next: None, val: 0 };
    // head pointer
    let mut head = Arc::new(Mutex::new(normal_res));
    let normal_res = Arc::clone(&head);
    for (i, val) in vec_int.iter().enumerate() {
        // the first one is different: fill in the created LinkedList
        if i == 0 {
            (*head).lock().unwrap().val = *val;
            continue;
        }

        // create new LinkedList and link it
        let next = LinkedList {
            next: None,
            val: *val,
        };
        // use clone to circumvent ownership problem
        let next = Arc::new(Mutex::new(next));
        (*head).lock().unwrap().next = Some(Arc::clone(&next));

        head = next;
    }
}

如果你想循环遍历链表,方法如下:

    let mut head = normal_res;
    loop {
        let dummy_head = Arc::clone(&head);
        let dummy_head = dummy_head.lock().unwrap();
        println!("val: {}", dummy_head.val);
        if dummy_head.next.is_none(){
            break;
        }
        head = Arc::clone(&dummy_head.next.as_ref().unwrap());
    }
© www.soinside.com 2019 - 2024. All rights reserved.