【Rust中的容器(二)】


前言

Rust中的容器(一)中,列举了Rust中的容器以及详聊了vector和Hashmap,本章将展示后续提及的容器用法。
双端队列:VecDeque
链表:LinkedList
映射:BtreeMap
集合:HashSet,BtreeSet
其他:BinaryHeap


双端队列:VecDeque

Rust的VecDeque是使用可增长的ringbuffer实现的(即头尾相接的队列,首尾指针各自定位,可根据数据push的数量进行扩容)
使用方法:

  1. 可以使用数组转换成双端队列
use std::collections::VecDeque;

fn main() {
    
    
    let deq = VecDeque::from([-1, 0, 1]);
    println!("{:?}", deq);
}
  1. 双端队列使用方法集合:
use std::collections::VecDeque;

fn main() {
    
    
    let mut deque: VecDeque<u32> = VecDeque::new(); //初始化
    deque.push_back(1);
    let mut buf: VecDeque<u32> = VecDeque::with_capacity(10); //初始化容量大小
    buf.push_back(3);
    buf.push_back(4);
    buf.push_back(5);
    buf.push_back(6);
    assert_eq!(buf.get(1), Some(&4)); //可以通过index获取数据
    if let Some(elem) = buf.get_mut(1) {
    
    
        //可通过get_mut将内部数据更改
        *elem = 7;
    }
    assert_eq!(buf[1], 7);
    buf.swap(0, 2); //可通过swap根据index,交换数据
    assert_eq!(buf, [5, 7, 3, 6]);
    deque.reserve(10);
    assert!(deque.capacity() >= 11);

    let mut buf1 = VecDeque::new();
    buf1.push_back(5);
    buf1.push_back(3);
    buf1.push_back(4);
    let b: &[_] = &[&5, &3, &4];
    let c: Vec<&i32> = buf1.iter().collect(); //iter迭代器,可转换到vector
    assert_eq!(&c[..], b);
    assert_eq!(buf1.len(), 3); //通过len获取长度
    assert!(!buf1.is_empty());

    let mut deque: VecDeque<_> = [1, 2, 3].into();
    for v in deque.range_mut(..) {
    
    
        //使用range mut可创建范围iter,并可更新其元素
        *v *= 2;
    }
    assert_eq!(deque, [2, 4, 6]);
    deque.clear(); //使用clear清空队列
    assert!(deque.is_empty());
    deque.push_back(1);
    assert_eq!(deque.contains(&1), true); //contains查看是否包含某元素
    deque.push_back(2);
    assert_eq!(deque.front(), Some(&1)); //front 队头元素
    deque.push_back(2);
    assert_eq!(deque.back(), Some(&2)); //back队尾元素
    assert_eq!(deque.pop_front(), Some(1)); //pop_front弹出队首元素
    deque.push_back(3);
    assert_eq!(deque.pop_back(), Some(3)); //pop_back弹出队尾元素
    deque.push_front(2); //头插
    assert_eq!(deque.front(), Some(&2));
    deque.push_back(3); //尾插
    assert_eq!(3, *deque.back().unwrap());
    assert_eq!(deque.remove(1), Some(2)); //删除某元素,并返回所在index

    let mut buf: VecDeque<_> = [1, 2].into();
    let mut buf2: VecDeque<_> = [3, 4].into();
    buf.append(&mut buf2); //将数组2追加到数组1的末尾。
    assert_eq!(buf, [1, 2, 3, 4]);
}
ps: 例子来源于rust标准库,这里作收集整理。

链表 Linklist

It is almost always better to use Vec or VecDeque because array-based containers are generally faster, more memory efficient, and make better use of CPU cache.
使用动态数组和双端队列几乎总是最好的选择,他们通常更快,内存效率更高,更好的利用CPU缓存

代码如下(示例):

fn main() {
    
    
    let mut list1 = LinkedList::from(['q', 'w', 'e']); // 可以从数组初始化双向链表
    list1.push_back('a'); //后插
    println!("{:?}", list1);
    assert!(!list1.is_empty()); //是否为空
    println!("{:?}", list1.len()); //长度
    list1.clear(); //清空
    assert!(list1.is_empty());
    list1.push_front('t');
    list1.push_front('l');
    list1.push_front('a'); //前插
    assert!(list1.contains(&'a')); //是否包含某个元素
    println!("{:?}", list1.front());
    assert_eq!(list1.pop_front(), Some('a'));//弹出首部元素
    assert_eq!(list1.pop_back(), Some('t')); //弹出尾部元素
}

B树map(BTreeMap)

代码示例:(示例来源rust标准库)

use std::collections::BTreeMap;

// type inference lets us omit an explicit type signature (which
// would be `BTreeMap<&str, &str>` in this example).
let mut movie_reviews = BTreeMap::new();

// review some movies.
movie_reviews.insert("Office Space",       "Deals with real issues in the workplace.");
movie_reviews.insert("Pulp Fiction",       "Masterpiece.");
movie_reviews.insert("The Godfather",      "Very enjoyable.");
movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot.");

// check for a specific one.
if !movie_reviews.contains_key("Les Misérables") {
    
    
    println!("We've got {} reviews, but Les Misérables ain't one.",
             movie_reviews.len());
}

// oops, this review has a lot of spelling mistakes, let's delete it.
movie_reviews.remove("The Blues Brothers");

// look up the values associated with some keys.
let to_find = ["Up!", "Office Space"];
for movie in &to_find {
    
    
    match movie_reviews.get(movie) {
    
    
       Some(review) => println!("{movie}: {review}"),
       None => println!("{movie} is unreviewed.")
    }
}

// Look up the value for a key (will panic if the key is not found).
println!("Movie review: {}", movie_reviews["Office Space"]);

// iterate over everything.
for (movie, review) in &movie_reviews {
    
    
    println!("{movie}: \"{review}\"");
}

HashSet

hashset就是value为()的hashmap

代码示例:

use std::collections::HashSet;
// Type inference lets us omit an explicit type signature (which
// would be `HashSet<String>` in this example).
let mut books = HashSet::new();

// Add some books.
books.insert("A Dance With Dragons".to_string());
books.insert("To Kill a Mockingbird".to_string());
books.insert("The Odyssey".to_string());
books.insert("The Great Gatsby".to_string());

// Check for a specific one.
if !books.contains("The Winds of Winter") {
    
    
    println!("We have {} books, but The Winds of Winter ain't one.",
             books.len());
}

// Remove a book.
books.remove("The Odyssey");

// Iterate over everything.
for book in &books {
    
    
    println!("{book}");
}

BtreeSet

btreeset 既使用btree实现的有序集合。
代码示例:

use std::collections::BTreeSet;

// Type inference lets us omit an explicit type signature (which
// would be `BTreeSet<&str>` in this example).
let mut books = BTreeSet::new();

// Add some books.
books.insert("A Dance With Dragons");
books.insert("To Kill a Mockingbird");
books.insert("The Odyssey");
books.insert("The Great Gatsby");

// Check for a specific one.
if !books.contains("The Winds of Winter") {
    
    
    println!("We have {} books, but The Winds of Winter ain't one.",
             books.len());
}

// Remove a book.
books.remove("The Odyssey");

// Iterate over everything.
for book in &books {
    
    
    println!("{book}");
}

BinaryHeap

用二叉堆实现的优先队列
代码示例:

use std::collections::BinaryHeap;

// Type inference lets us omit an explicit type signature (which
// would be `BinaryHeap<i32>` in this example).
let mut heap = BinaryHeap::new();

// We can use peek to look at the next item in the heap. In this case,
// there's no items in there yet so we get None.
assert_eq!(heap.peek(), None);

// Let's add some scores...
heap.push(1);
heap.push(5);
heap.push(2);

// Now peek shows the most important item in the heap.
assert_eq!(heap.peek(), Some(&5));

// We can check the length of a heap.
assert_eq!(heap.len(), 3);

// We can iterate over the items in the heap, although they are returned in
// a random order.
for x in &heap {
    
    
    println!("{x}");
}

// If we instead pop these scores, they should come back in order.
assert_eq!(heap.pop(), Some(5));
assert_eq!(heap.pop(), Some(2));
assert_eq!(heap.pop(), Some(1));
assert_eq!(heap.pop(), None);

// We can clear the heap of any remaining items.
heap.clear();

// The heap should now be empty.
assert!(heap.is_empty())

Ps:本文示例均来源于rust标准库,后续有计划分享内部实现细节。

猜你喜欢

转载自blog.csdn.net/m0_37719524/article/details/143319684