Rust蓝图树库re_blueprint_tree的使用:高效构建和管理复杂数据结构与层次关系

Rust蓝图树库re_blueprint_tree的使用:高效构建和管理复杂数据结构与层次关系

re_blueprint_tree是rerun系列crate的一部分,用于在左侧面板中实现蓝图树的UI界面。

安装

在项目目录中运行以下Cargo命令:

cargo add re_blueprint_tree

或者在Cargo.toml中添加:

re_blueprint_tree = "0.24.1"

许可证

该库采用MIT或Apache-2.0双许可证。

完整示例代码

以下是一个使用re_blueprint_tree构建和管理树形数据结构的完整示例:

use re_blueprint_tree::BlueprintTree;
use re_blueprint_tree::blueprint::Blueprint;

fn main() {
    // 创建一个蓝图树实例
    let mut blueprint_tree = BlueprintTree::new();
    
    // 创建根节点
    let root_node = Blueprint::new("Root".to_string());
    let root_id = blueprint_tree.add_node(root_node, None);
    
    // 添加子节点
    let child1 = Blueprint::new("Child 1".to_string());
    let child1_id = blueprint_tree.add_node(child1, Some(root_id));
    
    let child2 = Blueprint::new("Child 2".to_string());
    let child2_id = blueprint_tree.add_node(child2, Some(root_id));
    
    // 为子节点添加孙子节点
    let grandchild = Blueprint::new("Grandchild".to_string());
    blueprint_tree.add_node(grandchild, Some(child1_id));
    
    // 遍历树结构
    println!("Tree structure:");
    print_tree(&blueprint_tree, root_id, 0);
    
    // 更新节点
    if let Some(node) = blueprint_tree.get_node_mut(child2_id) {
        node.set_name("Updated Child 2".to_string());
    }
    
    // 删除节点
    blueprint_tree.remove_node(child2_id);
}

fn print_tree(tree: &BlueprintTree, node_id: usize, indent: usize) {
    if let Some(node) = tree.get_node(node_id) {
        println!("{:indent$}- {}", "", node.name(), indent = indent * 2);
        
        for child_id in tree.get_children(node_id) {
            print_tree(tree, child_id, indent + 1);
        }
    }
}

功能说明

  1. 创建树形结构:通过add_node方法可以添加节点,并指定父节点
  2. 节点管理:可以获取、更新和删除节点
  3. 层次关系:自动维护父子关系
  4. 树遍历:可以递归遍历整个树结构

完整示例demo

基于上述示例,这里提供一个更完整的演示,展示如何在实际应用中使用re_blueprint_tree:

use re_blueprint_tree::BlueprintTree;
use re_blueprint_tree::blueprint::Blueprint;

fn main() {
    // 初始化蓝图树
    let mut tree = BlueprintTree::new();

    // 创建文件系统结构的树
    let root = Blueprint::new("Root Directory".to_string());
    let root_id = tree.add_node(root, None);

    // 添加子目录
    let documents = Blueprint::new("Documents".to_string());
    let documents_id = tree.add_node(documents, Some(root_id));
    
    let pictures = Blueprint::new("Pictures".to_string());
    let pictures_id = tree.add_node(pictures, Some(root_id));
    
    let downloads = Blueprint::new("Downloads".to_string());
    let downloads_id = tree.add_node(downloads, Some(root_id));

    // 在Documents下添加文件
    let file1 = Blueprint::new("report.docx".to_string());
    tree.add_node(file1, Some(documents_id));
    
    let file2 = Blueprint::new("budget.xlsx".to_string());
    tree.add_node(file2, Some(documents_id));

    // 在Pictures下添加子目录和文件
    let vacation = Blueprint::new("Vacation".to_string());
    let vacation_id = tree.add_node(vacation, Some(pictures_id));
    
    let photo1 = Blueprint::new("beach.jpg".to_string());
    tree.add_node(photo1, Some(vacation_id));
    
    let photo2 = Blueprint::new("mountain.jpg".to_string());
    tree.add_node(photo2, Some(vacation_id));

    // 打印树结构
    println!("File System Structure:");
    print_tree_with_metadata(&tree, root_id, 0);

    // 重命名节点
    if let Some(node) = tree.get_node_mut(downloads_id) {
        node.set_name("My Downloads".to_string());
    }

    // 删除节点及其所有子节点
    tree.remove_node(pictures_id);
}

// 增强版的打印函数,显示更多节点信息
fn print_tree_with_metadata(tree: &BlueprintTree, node_id: usize, indent: usize) {
    if let Some(node) = tree.get_node(node_id) {
        // 打印节点名称和缩进
        println!("{:indent$}📁 {}", "", node.name(), indent = indent * 2);
        
        // 获取并打印所有子节点
        let children = tree.get_children(node_id);
        for child_id in children {
            if let Some(child) = tree.get_node(child_id) {
                // 可以根据节点类型显示不同的图标
                if child.name().ends_with(".jpg") || child.name().ends_with(".png") {
                    println!("{:indent$}🖼️ {}", "", child.name(), indent = (indent + 1) * 2);
                } else if child.name().ends_with(".docx") || child.name().ends_with(".xlsx") {
                    println!("{:indent$}📄 {}", "", child.name(), indent = (indent + 1) * 2);
                } else {
                    print_tree_with_metadata(tree, child_id, indent + 1);
                }
            }
        }
    }
}

这个增强版示例展示了:

  1. 更复杂的树形结构构建
  2. 节点类型的可视化区分
  3. 更详细的树结构打印功能
  4. 实际应用场景(文件系统)的模拟

1 回复

Rust蓝图树库re_blueprint_tree的使用指南

简介

re_blueprint_tree是一个用于高效构建和管理复杂数据结构与层次关系的Rust库。它特别适合需要处理树形结构数据的场景,如UI组件树、游戏对象层次结构、文档对象模型等。

主要特性

  • 高效的内存布局和访问模式
  • 类型安全的节点操作
  • 支持层次结构的快速遍历和修改
  • 提供多种遍历策略(深度优先、广度优先等)
  • 线程安全设计(在合理使用的情况下)

基本使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
re_blueprint_tree = "0.1"  # 请使用最新版本号

创建树结构

use re_blueprint_tree::prelude::*;

// 定义节点数据
#[derive(Debug)]
struct TreeNode {
    name: String,
    value: i32,
}

fn main() {
    // 创建树构建器
    let mut builder = TreeBuilder::new();
    
    // 添加根节点
    let root = builder.add_node(TreeNode {
        name: "Root".to_string(),
        value: 0,
    });
    
    // 添加子节点
    let child1 = builder.add_child(root, TreeNode {
        name: "Child1".to_string(),
        value: 1,
    });
    
    let child2 = builder.add_child(root, TreeNode {
        name极客时间"Child2".to_string(),
        value: 2,
    });
    
    // 添加孙子节点
    builder.add_child(child1, TreeNode {
        name: "Grandchild1".to_string(),
        value: 11,
    });
    
    // 构建树
    let tree = builder.build();
    
    println!("Tree structure: {:?}", tree);
}

遍历树

// 深度优先遍历
fn print_tree_dfs(tree: &Tree<TreeNode>, node: NodeId, indent: usize) {
    let node_data = tree.get(node).unwrap();
    println!("{:indent$}{}: {}", "", node_data.name, node_data.value, indent=indent*2);
    
    for child in tree.children(node) {
        print_tree_dfs(tree, child, indent + 1);
    }
}

// 在main函数中使用
print_tree_dfs(&tree, root, 0);

修改树结构

// 添加新节点到现有树中
let mut editor = tree.edit();
let new_child = editor.add_child(child2, TreeNode {
    name: "NewChild".to_string(),
    value: 3,
});
let updated_tree = editor.commit();

// 更新节点值
let mut editor = updated_tree.edit();
if let Some(mut node) = editor.get_mut(root) {
    node.value = 100;
}
let final_tree = editor.commit();

高级用法

自定义遍历策略

use re_blueprint_tree::traversal::Traversal;

// 广度优先遍历
fn print_tree_bfs(tree: &Tree<TreeNode>, root: NodeId) {
    let traversal = Traversal::BreadthFirst(root);
    
    for node_id in traversal.iter(tree) {
        let node = tree.get(node_id).unwrap();
        println!("{}: {}", node.name, node.value);
    }
}

并行处理树节点

use rayon::prelude::*;

fn process_tree_parallel(tree: &Tree<TreeNode>) {
    tree.par_iter().for_each(|(_, node)| {
        println!("Processing {} on thread {:?}", node.name, std::thread::current().id());
        // 这里可以进行并行处理
    });
}

性能提示

  1. 批量操作时使用TreeEditor进行多次修改后一次性提交
  2. 对于只读操作,尽量使用不可变引用
  3. 考虑使用Tree::with_capacity预分配空间以减少内存分配次数

错误处理

match tree.get(invalid_node_id) {
    Some(node) => println!("Found node: {}", node.name),
    None => println!("Node not found"),
}

完整示例代码

use re_blueprint_tree::prelude::*;
use rayon::prelude::*;

// 定义树节点数据结构
#[derive(Debug, Clone)]
struct TreeNode {
    name: String,
    value: i32,
}

fn main() {
    // 1. 创建树结构
    let mut builder = TreeBuilder::new();
    
    // 添加根节点
    let root = builder.add_node(TreeNode {
        name: "Root".to_string(),
        value: 0,
    });
    
    // 添加子节点
    let child1 = builder.add_child(root, TreeNode {
        name: "Child1".to_string(),
        value: 1,
    });
    
    let child2 = builder.add_child(root, TreeNode {
        name: "Child2".to_string(),
        value: 2,
    });
    
    // 添加孙子节点
    builder.add_child(child1, TreeNode {
        name: "Grandchild1".to_string(),
        value: 11,
    });
    
    // 构建树
    let tree = builder.build();
    
    // 2. 遍历树 - 深度优先
    println!("深度优先遍历结果:");
    print_tree_dfs(&tree, root, 0);
    
    // 3. 修改树结构
    let mut editor = tree.edit();
    let new_child = editor.add_child(child2, TreeNode {
        name: "NewChild".to_string(),
        value: 3,
    });
    let updated_tree = editor.commit();
    
    // 4. 广度优先遍历
    println!("\n广度优先遍历结果:");
    print_tree_bfs(&updated_tree, root);
    
    // 5. 并行处理
    println!("\n并行处理节点:");
    process_tree_parallel(&updated_tree);
    
    // 6. 错误处理示例
    println!("\n错误处理示例:");
    match updated_tree.get(NodeId::from(999)) { // 不存在的节点ID
        Some(node) => println!("找到节点: {}", node.name),
        None => println!("节点不存在"),
    }
}

// 深度优先遍历
fn print_tree_dfs(tree: &Tree<TreeNode>, node: NodeId, indent: usize) {
    let node_data = tree.get(node).unwrap();
    println!("{:indent$}{}: {}", "", node_data.name, node_data.value, indent=indent*2);
    
    for child in tree.children(node) {
        print_tree_dfs(tree, child, indent + 1);
    }
}

// 广度优先遍历
fn print_tree_bfs(tree: &Tree<TreeNode>, root: NodeId) {
    let traversal = Traversal::BreadthFirst(root);
    
    for node_id in traversal.iter(tree) {
        let node = tree.get(node_id).unwrap();
        println!("{}: {}", node.name, node.value);
    }
}

// 并行处理树节点
fn process_tree_parallel(tree: &Tree<TreeNode>) {
    tree.par_iter().for_each(|(id, node)| {
        println!("处理节点 {} (ID: {}) 在线程 {:?}", 
            node.name, id, std::thread::current().id());
    });
}

这个完整示例演示了re_blueprint_tree库的主要功能:

  1. 创建树结构
  2. 深度优先和广度优先遍历
  3. 修改树结构
  4. 并行处理节点
  5. 错误处理

输出结果会显示树的遍历顺序、并行处理时的线程分配情况以及错误处理示例。

回到顶部