#tree #tree-node #node-tree #tree-structure #data #traits

tree-rizzen-yazston

A Simple Tree Library using the Any trait for data

1 unstable release

0.4.0 Apr 8, 2023

#2409 in Data structures

Download history 6/week @ 2024-07-26 2/week @ 2024-08-02 10/week @ 2024-09-20 9/week @ 2024-09-27 36/week @ 2024-10-04 25/week @ 2024-10-11 3/week @ 2024-10-18 4/week @ 2024-10-25 47/week @ 2024-11-01

87 downloads per month
Used in 2 crates

BSD-3-Clause

52KB
526 lines

Tree

Rizzen Yazston

Welcome to the Tree project.

A simple tree structure containing data nodes. The tree crate provides the Tree struct, which can store any data that implements the Any trait. Methods are provided for the manipulation of the tree structure, and obtaining information regarding the tree structure and its nodes. Manipulating the data of the nodes is done via one method data_mut, which simply provides a mutable reference to the vector containing the data. The data_ref method is just an immutable reference if reading is only required.

Internally the tree makes use of a node struct that contains information about the node in the tree. The information consists of: the immediate parent node, a vector containing children nodes, the node's features, the node type, the data type, and a vector containing data. All the node struct fields are optional except for the node's features (determines how the node will behave in the tree).

The node's features are specified at the time of the node creation as a parameter features of insert and insert_at methods by passing an union of selected features. Currently the tree supports two features:

  • ALLOW_CHILDREN: indicates if the node can have children,

  • ALLOW_DATA: indicates if the node can have data.

At the time of creating the nodes, the node_type and data_type parameters are passed to specify the node and data types. These fields are read only once they are set. The node type is normally used for indicating what the node is, especially when the node type can't be determined from the node's data, or the node lacks any data (such as structure information). The data type is generally used when the data of the entire tree is of different types. The data type is normally specified to aid in determining how to correctly downcast the data to its actual type. As the node can support multiple data instances, it is recommended that all the data instances within the node are of the same type, due to there being only one data type field for the node. Though it is possible to use an elaborate string than a simple enum to indicate all the data types used in the node.

NOTE: Once core::error::Error is no longer experimental, this library will then only depend on the core, thus will be suitable for no_std environments.

The repository contains only the tree crate.

NOTE: The crate on crates.io has its name appended with the suffix -rizzen-yazston to distinguish them from other tree creates by other authors.

Acknowledgements

Stefano Angeleri for advice on various design aspects of implementing a tree of nodes, and also providing the Italian translation of error message strings.

Usage

Simply include the tree-rizzen-yazston crate in the Cargo.toml to make it available to the application or library. Due to its simple design there is no configuration required at the time of creating the empty tree. Nodes are configured at the time of inserting the nodes into the tree.

Cargo.toml

[dependencies]
tree-rizzen-yazston = "0.4.0"

Examples

This example uses the String as the data type for all the nodes that have data, thus the parameter data_type is None to indicate it is not used. A string "String" could have be used to explicitly indicate the data is of type String. Alternative a simple enum could be used if all the data types are known at compile time to indicate the data type.

Due the data being strings, that carry little structure information (not all nodes contains data), a good choice is to use an enum to indicate the node type. As with data_type, strings could have also be used for the node_type.

use tree::{Tree, ALLOW_CHILDREN, ALLOW_DATA};

enum Nodes {
    Root,
    Statement,
    Equal,
    Divide,
    Add,
    Leaf,
}

let mut tree = Tree::new();
let no_data = ALLOW_CHILDREN;
let variable = ALLOW_DATA;

// Build tree of one statement: z = (x + y) / 2
// Just ignoring the `Result` using .ok() as this is a trivial example.
let mut index = tree.insert( 300, no_data.clone(), Some( Box::new( Nodes::Root ) ), None ).unwrap();
tree.insert( index, no_data.clone(), Some( Box::new( Nodes::Statement ) ), None ).ok();
tree.insert( 1, no_data.clone(), Some( Box::new( Nodes::Equal ) ), None ).ok();
index = tree.insert( 2, variable.clone(), Some( Box::new( Nodes::Leaf ) ), None ).unwrap();
tree.data_mut( index ).unwrap().push( Box::new( "z".to_string() ) );
tree.insert( 2, no_data.clone(), Some( Box::new( Nodes::Divide ) ), None ).ok();
tree.insert( 4, no_data.clone(), Some( Box::new( Nodes::Add ) ), None ).ok();
index = tree.insert( 5, variable.clone(), Some( Box::new( Nodes::Leaf ) ), None ).unwrap();
tree.data_mut( index ).unwrap().push( Box::new( "x".to_string() ) );
index = tree.insert( 5, variable.clone(), Some( Box::new( Nodes::Leaf ) ), None ).unwrap();
tree.data_mut( index ).unwrap().push( Box::new( "y".to_string() ) );
index = tree.insert( 4, variable.clone(), Some( Box::new( Nodes::Leaf ) ), None ).unwrap();
tree.data_mut( index ).unwrap().push( Box::new( "2".to_string() ) );
assert_eq!( tree.count(), 9, "9 nodes are present." );

No runtime deps