Rust实现二叉树、字典树、并查集
二叉树
使用Option<Box<T>>
实现。Box是智能指针,分配在堆上,专门用于这种“无限”大小的数据类型。LeetCode上采用Option<Rc<RefCell<T>>>
实现,非常臃肿。。
#[derive(PartialEq)]
enum TreeDir{
LEFT, RIGHT
}
#[derive(Default)]
struct TreeNode{
val:i32,
left:Option<Box<TreeNode>>, //Box是智能指针,分配在堆上,专门用于这种“无限”大小的数据类型
right:Option<Box<TreeNode>>,
}
impl TreeNode {
pub fn new () -> Self{ //新建树
Self { val: 0, left: None, right: None }
}
pub fn new_val (num:i32) -> Self{ //新建树并设定值
Self { val: num, left: None, right: None }
}
pub fn insert_tree (&mut self, node:TreeNode, dir:TreeDir){ //插入树
if dir == TreeDir::LEFT{
self.left = Some(Box::new(node));
}else{
self.right = Some(Box::new(node));
}
}
pub fn remove_tree (&mut self, dir:TreeDir){
match dir{
//直接设为None即可,智能指针会自动释放空间。
TreeDir::LEFT => {self.left = None;},
TreeDir::RIGHT => {self.right = None;},
}
}
pub fn traverse_preorder(&self){ //前序遍历
println!("{}", self.val);
if let Some(ref left) = self.left {
left.traverse_preorder();
}
if let Some(ref right) = self.right {
right.traverse_preorder();
}
}
}
fn main() {
let mut t = TreeNode::new();
t.insert_tree(TreeNode::new_val(10), TreeDir::LEFT);
if let Some(ref mut t_left) = t.left{
t_left.insert_tree(TreeNode::new_val(20), TreeDir::RIGHT);
}
t.traverse_preorder();
let p = t.left.as_ref().unwrap().right.as_ref().unwrap();
println!("释放前:{}", p.val);
t.remove_tree(TreeDir::LEFT);
t.insert_tree(TreeNode::new_val(12), TreeDir::RIGHT);
// println!("释放后:{}", p.val); //无法输出 p.val, 编译器报错
}
字典树
使用HashMap<char, Self>
实现。
use std::collections::HashMap;
#[derive(Default, Debug)]
struct TrieNode {
is_end_of_word: bool,
children: HashMap<char, TrieNode>,
}
#[derive(Default, Debug)]
pub struct Trie {
root: TrieNode,
}
impl Trie {
pub fn new() -> Self {
Trie {
root: TrieNode::default(),
}
}
pub fn insert(&mut self, word: &str) {
let mut current_node = &mut self.root;
for c in word.chars() {
current_node = current_node.children.entry(c).or_default();
}
current_node.is_end_of_word = true;
}
pub fn contains(&self, word: &str) -> bool {
let mut current_node = &self.root;
for c in word.chars() {
match current_node.children.get(&c) {
Some(node) => current_node = node,
None => return false,
}
}
current_node.is_end_of_word
}
}
fn main() {
let mut trie = Trie::new();
trie.insert("hello");
trie.insert("hi");
trie.insert("hey");
trie.insert("world");
//println!("{trie:#?}");
println!("hiiii? {}", trie.contains("hiiii"));
}
如果把开头几行换成这个更快:
use std::collections::HashMap;
use fxhash::FxBuildHasher;
type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
#[derive(Default)]
struct TrieNode {
is_end_of_word: bool,
children: FxHashMap<char, TrieNode>,
}
因为它采用了更简单的哈希函数。
并查集
use std::collections::HashMap;
struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
//新建大小为n的并查集
pub fn new(n: usize) -> Self {
UnionFind {
parent: (0..n).collect(),
}
}
// 并查集中不同集合的数量
pub fn count(&self) -> usize {
let mut c = 0;
for i in 0..self.parent.len() {
if self.parent[i] == i {
c += 1;
}
}
c
}
//以Vec形式获得所有不同集合
pub fn get_vec(&mut self) -> Vec<Vec<usize>> {
let mut map: HashMap<usize, Vec<usize>> = HashMap::new();
for i in 0..self.parent.len() {
map.entry(self.find(i)).or_insert(Vec::new()).push(i);
}
map.into_values().collect()
}
pub fn find(&mut self, idx: usize) -> usize {
if idx != self.parent[idx] {
self.parent[idx] = self.find(self.parent[idx]);
}
self.parent[idx]
}
//连接点
pub fn union(&mut self, idx1: usize, idx2: usize) {
let (x, y) = (self.find(idx1), self.find(idx2));
if x != y {
self.parent[x] = y;
}
}
//判断两点是否连接
pub fn connected(&mut self, i: usize, j: usize) -> bool {
self.find(i) == self.find(j)
}
}
fn main() {
let n = 5;
let pair = vec![vec![0, 3],vec![0, 2]];
let mut uf = UnionFind::new(n);
for p in pair {
uf.union(p[0], p[1]);
}
println!("不同集合的数量:{}", uf.count()); //输出:不同集合的数量:3
println!("不同的集合:{:?}", uf.get_vec()); //输出:不同的集合:[[0, 2, 3], [4], [1]]
}
本文来自博客园,作者:mariocanfly,转载请注明原文链接:https://www.cnblogs.com/mariocanfly/p/17896368.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话