Catalyst

Rust 笔记(七)Collections

刷题用到的 Collections 下的类型笔记,将之前的哈希表也搬过来了。

HashMap

//哈希表
use std::collections::HashMap;
fn main() {
    let field_name = String::from("Blue");
    let field_value = String::from("蓝色");

    let mut map = HashMap::new();
    //插入数据
    map.insert(field_name, field_value);
  • 读取数据
    //读取数据
    let _fav_color = map.get(&String::from("Blue"));

    //打印哈希表结构,如果在结构体中打开这种格式化需要打开 debug(#[derive(Debug)])
    println!("{:?}", map);
    //{"Blue": "蓝色"}
  • 更新数据
    //更新数据,覆盖
    map.insert(String::from("Blue"), String::from("总之是蓝色"));

    //更新数据(如果没有和该键相关联的值)
    map.entry(String::from("Red"))
        .or_insert(String::from("红色"));
    map.entry(String::from("Blue"))
        .or_insert(String::from("不会被覆盖"));

    map.entry(String::from("Yellow")).or_default(); //插入 default

    println!("{:?}", map);
    //{"Blue": "总之是蓝色", "Red": "红色", "Yellow": ""}
    // 基于原数据添加
    let mut map2: HashMap<i32, i32> = HashMap::new();
    map2.insert(1, 3);
    *map2.entry(1).or_insert(0) += 1;
    println!("{:?}", map2);
    // {1: 4}
  • 删除数据
    //删除数据
    let blue = map.remove(&String::from("Blue")); //返回值
    let red = map.remove_entry(&String::from("Red")); //返回键和值
    println!("{:?}", blue); //Some("总之是蓝色")
    println!("{:?}", red); //Some(("Red", "红色"))
  • 遍历数据
    //遍历
    for (key, value) in &map {
        println!("-- {}:{},", key, value);
    }
}

BinaryHeap

用二进制堆实现的优先队列(最大堆)。

use std::collections::BinaryHeap;

fn main() {
    let mut heap: BinaryHeap<i32> = BinaryHeap::new();
    for i in [2, 1, 4, 5, 3].iter() {
        // 用 push 添加数据
        heap.push(*i);
    }

    // 使用 peek 查找最大值
    let k: Option<&i32> = heap.peek(); // 这里返回的是引用
    println!("max: {:?}", k); //max: Some(5)

    // 用 pop 从最大依次弹出
    for _i in 0..3 {
        let m: Option<i32> = heap.pop(); // 返回的不是引用
        println!("pop: {:?}", m);
    }
    // pop: Some(5)
    // pop: Some(4)
    // pop: Some(3)

    // 用 clear 清空堆
    heap.clear();
    println!("heap: {:?}", heap); // heap: []

    // 用 is_empty 判断是否为空
    println!("is empty: {}", heap.is_empty()); //is empty: true
}

自定义排序

BinaryHeap 里的类型需要实现Ord特性,其需要类型同时具有PartialOrdEq(要求PartialEq)。也需要定义一个cmp的继承。

这些特性的关系:

参考 how can I implement Ord

use std::cmp::Ordering;
use std::collections::BinaryHeap;

#[derive(Eq,Debug)]
struct Item {
    val: i32,
}

impl Ord for Item {
    fn cmp(&self, other: &Self) -> Ordering {
        self.val.cmp(&other.val)
    }
}

impl PartialOrd for Item {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Item {
    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}

fn main() {
    let mut heap: BinaryHeap<Item> = BinaryHeap::new();
    for i in [1,2,3,4,5].iter() {
        // 用 push 添加数据
        heap.push(Item { val: *i });
    }

    for _i in 0..heap.len(){
        println!("pop:{:?}", heap.pop());
    }
    // pop:Some(Item { val: 5 })
    // pop:Some(Item { val: 4 })
    // pop:Some(Item { val: 3 })
    // pop:Some(Item { val: 2 })
    // pop:Some(Item { val: 1 })
}

HashSet

文档

HashSet 要求包括的元素实现EqHash特性。(常用#[derive(PartialEq, Eq, Hash)]可解决)

use std::collections::HashSet;

fn main() {
    let mut nums = HashSet::new();

    // 添加数据
    nums.insert(1);
    nums.insert(2);
    nums.insert(3);

    // 如果数据存在返回 false,否则 true
    assert_eq!(nums.insert(3), false);

    // 取出并删除数据(如果数据存在)
    assert_eq!(nums.take(&2), Some(2));

    // 消耗并将返回一个包含所有元素的迭代器,顺序任意
    // .iter() 同顺序任意
    for i in nums.drain() {
        println!("{}", i);
    }

    // set 被消耗变空
    assert_eq!(nums.is_empty(), true);
}

VecDeque

双向队列,文档

use std::collections::VecDeque;

fn main() {
    // 可从 vec 初始化
    let mut deq: VecDeque<i32> = VecDeque::from(vec![1, 2, 3]);

    // 通常的加入新项目:push_back
    deq.push_back(4);
    // 从第一位加入:
    deq.push_front(0);
    assert_eq!(deq, [0, 1, 2, 3, 4]);

    // 返回第一个元素的 ref , 另有 front_mut
    assert_eq!(deq.front(), Some(&0));
    // 返回最后一个元素的 ref,另有 back_mut
    assert_eq!(deq.back(), Some(&4));

    // 移除并返回元素
    assert_eq!(deq.remove(0), Some(0));
    assert_eq!(deq, [1, 2, 3, 4]);

    //在指定位置插入元素
    deq.insert(1, 100);
    assert_eq!(deq, [1, 100, 2, 3, 4]);

    // 按顺序遍历一遍并选择保留的元素 (保留原顺序)
    deq.retain(|&x| x < 5);
    assert_eq!(deq, [1, 2, 3, 4]);
}

BTreeMap

可排序的集合,文档

use std::collections::BTreeMap;

fn main() {
    let mut treemap = BTreeMap::new();

    // 插入一些数据
    treemap.insert(222, "A");
    treemap.insert(1, "B");

    // 获取数据
    assert_eq!(treemap[&222], "A");
    assert_eq!(treemap.get(&222), Some(&"A"));

    // entry 用法和 hashmap 差不多
    treemap.entry(20).or_insert("C");

    // 获取元素数量
    assert_eq!(treemap.len(), 3);

    // 按 key 顺序迭代
    for (key, value) in treemap.iter() {
        println!("({},{})", key, value);
    }
    // (1,B)
    // (20,C)
    // (222,A)

    // 移除元素
    treemap.remove(&1);
    assert_eq!(treemap.contains_key(&1), false);
}
参考资料