You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用make_contiguous()的情况下对Rust的VecDeque排序或反转?

在Rust 1.42.0中对VecDeque进行原地反转和排序

由于Rust 1.42.0尚未提供make_contiguous(),我们可以通过unsafe代码直接操作VecDeque的内部结构来实现高效的原地反转和排序,避免转换为Vec的开销。

原地反转

VecDeque的底层是环形缓冲区,反转的核心是交换环形中对称位置的元素。我们可以通过unsafe访问其私有字段(buf、head、tail),直接操作内存中的元素:

use std::collections::VecDeque;

unsafe fn reverse_vec_deque<T>(dq: &mut VecDeque<T>) {
    let len = dq.len();
    if len <= 1 {
        return;
    }

    // 定义与1.42.0版本VecDeque内部结构匹配的私有结构体
    #[repr(C)]
    struct VecDequePrivate<T> {
        buf: Vec<T>,
        head: usize,
        tail: usize,
    }

    // 转换为私有结构体指针以访问内部字段
    let private = dq.as_mut_ptr().cast::<VecDequePrivate<T>>();
    let head = (*private).head;
    let buf_ptr = (*private).buf.as_mut_ptr();
    let cap = (*private).buf.capacity();

    // 交换环形中对称位置的元素
    for i in 0..len / 2 {
        let left_idx = (head + i) % cap;
        let right_idx = (head + len - 1 - i) % cap;
        std::ptr::swap(buf_ptr.add(left_idx), buf_ptr.add(right_idx));
    }
}

使用示例:

let mut dq = VecDeque::from(vec![3, 4, 1, 2]);
unsafe { reverse_vec_deque(&mut dq) };
assert_eq!(dq, VecDeque::from(vec![2, 1, 4, 3]));

原地排序

排序需要随机访问连续的内存区域,我们可以手动实现make_contiguous()的核心逻辑:将环形缓冲区中的元素移动到内存起始位置使其连续,再调用切片的sort()方法:

use std::collections::VecDeque;

unsafe fn make_contiguous_142<T>(dq: &mut VecDeque<T>) -> &mut [T] {
    #[repr(C)]
    struct VecDequePrivate<T> {
        buf: Vec<T>,
        head: usize,
        tail: usize,
    }

    let private = dq.as_mut_ptr().cast::<VecDequePrivate<T>>();
    let head = (*private).head;
    let tail = (*private).tail;
    let buf = &mut (*private).buf;
    let len = dq.len();

    // 元素已经连续,直接返回切片
    if head == 0 {
        return &mut buf[0..len];
    }

    let cap = buf.capacity();
    if head < tail {
        // 元素是连续的一段,直接移动到缓冲区起始位置
        buf.copy_within(head..tail, 0);
    } else {
        // 元素分为两段,先将后半段移到缓冲区末尾,再将前半段移到起始位置
        buf.copy_within(0..tail, cap - tail);
        buf.copy_within(head..cap, 0);
    }

    // 更新head和tail,指向连续的元素范围
    (*private).head = 0;
    (*private).tail = len;

    &mut buf[0..len]
}

unsafe fn sort_vec_deque<T: Ord>(dq: &mut VecDeque<T>) {
    let contiguous_slice = make_contiguous_142(dq);
    contiguous_slice.sort();
}

使用示例:

let mut dq = VecDeque::from(vec![3, 4, 1, 2]);
unsafe { sort_vec_deque(&mut dq) };
assert_eq!(dq, VecDeque::from(vec![1, 2, 3, 4]));

说明

  • 代码依赖1.42.0版本VecDeque的内部结构,若版本结构变化会失效,但完全符合题目版本限制。
  • 使用#[repr(C)]保证结构体布局与标准库VecDeque一致,确保unsafe访问的安全性。
  • 所有操作均在原地完成,无额外内存分配,效率与1.48+版本的make_contiguous()方案一致。

内容的提问来源于stack exchange,提问作者ynn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:01:11