binary-tree: Update.

pull/13/head
Jim Blandy 3 years ago
parent fd7632bb9b
commit 88dbb7c344

@ -4,14 +4,25 @@
name = "binary-tree"
version = "0.1.0"
dependencies = [
"rand 0.3.23",
"rand",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
@ -20,70 +31,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "rand"
version = "0.3.23"
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
dependencies = [
"libc",
"rand 0.4.6",
]
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
version = "0.4.6"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_core"
version = "0.3.1"
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"rand_core 0.4.2",
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rdrand"
version = "0.4.0"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"rand_core 0.3.1",
"getrandom",
]
[[package]]
name = "winapi"
version = "0.3.9"
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
"rand_core",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"

@ -2,6 +2,7 @@
name = "binary-tree"
version = "0.1.0"
authors = ["You <you@example.com>"]
edition = "2018"
[dependencies]
rand = "0.3.14"
rand = "0.8"

@ -1,18 +1,16 @@
#![allow(dead_code)]
extern crate rand;
// An ordered collection of `T`s.
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>)
NonEmpty(Box<TreeNode<T>>),
}
// A part of a BinaryTree.
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>
right: BinaryTree<T>,
}
#[test]
@ -26,37 +24,42 @@ fn binary_tree_size() {
}
#[test]
fn test_hand_building_tree_of_planets() {
fn build_binary_tree() {
use self::BinaryTree::*;
let jupiter_tree = NonEmpty(Box::new(TreeNode {
element: "Jupiter",
left: Empty,
right: Empty
right: Empty,
}));
let mercury_tree = NonEmpty(Box::new(TreeNode {
element: "Mercury",
left: Empty,
right: Empty
right: Empty,
}));
let mars_tree = NonEmpty(Box::new(TreeNode {
element: "Mars",
left: jupiter_tree,
right: mercury_tree
right: mercury_tree,
}));
let venus_tree = NonEmpty(Box::new(TreeNode {
element: "Venus",
left: Empty,
right: Empty
right: Empty,
}));
let uranus_tree = NonEmpty(Box::new(TreeNode {
element: "Uranus",
left: Empty,
right: venus_tree
right: venus_tree,
}));
let tree = NonEmpty(Box::new(TreeNode {
element: "Saturn",
left: mars_tree,
right: uranus_tree
right: uranus_tree,
}));
assert_eq!(tree.walk(),
@ -80,18 +83,20 @@ impl<T: Clone> BinaryTree<T> {
impl<T: Ord> BinaryTree<T> {
fn add(&mut self, value: T) {
match *self {
BinaryTree::Empty =>
BinaryTree::Empty => {
*self = BinaryTree::NonEmpty(Box::new(TreeNode {
element: value,
left: BinaryTree::Empty,
right: BinaryTree::Empty
})),
BinaryTree::NonEmpty(ref mut node) =>
right: BinaryTree::Empty,
}))
}
BinaryTree::NonEmpty(ref mut node) => {
if value <= node.element {
node.left.add(value);
} else {
node.right.add(value);
}
}
}
}
}
@ -113,18 +118,22 @@ fn test_add_method_2() {
let mut tree = BinaryTree::Empty;
tree.add("Mercury");
tree.add("Venus");
for planet in vec!["Mars", "Jupiter", "Saturn", "Uranus"] {
for planet in vec!["Mars", "Jupiter", "Saturn", "Uranus"] {
tree.add(planet);
}
assert_eq!(tree.walk(),
vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]);
assert_eq!(
tree.walk(),
vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]
);
}
// From chapter 15: Iterators
use self::BinaryTree::*;
// The state of an in-order traversal of a `BinaryTree`.
struct TreeIter<'a, T: 'a> {
struct TreeIter<'a, T> {
// A stack of references to tree nodes. Since we use `Vec`'s
// `push` and `pop` methods, the top of the stack is the end of the
// vector.
@ -164,14 +173,13 @@ impl<'a, T> Iterator for TreeIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
// Find the node this iteration must produce,
// or finish the iteration.
let node = match self.unvisited.pop() {
None => return None,
Some(n) => n
};
// The next node after this one is the leftmost child of
// this node's right child, so push the path from here down.
// or finish the iteration. (Use the `?` operator
// to return immediately if it's `None`.)
let node = self.unvisited.pop()?;
// After `node`, the next thing we produce must be the leftmost
// child in `node`'s right subtree, so push the path from here
// down. Our helper method turns out to be just what we need.
self.push_left_edge(&node.right);
// Produce a reference to this node's value.
@ -188,24 +196,40 @@ fn external_iterator() {
}
// Build a small tree.
let subtree_l = make_node(Empty, "mecha", Empty);
let subtree_rl = make_node(Empty, "droid", Empty);
let subtree_r = make_node(subtree_rl, "robot", Empty);
let tree = make_node(subtree_l, "Jaeger", subtree_r);
let mut tree = BinaryTree::Empty;
tree.add("jaeger");
tree.add("robot");
tree.add("droid");
tree.add("mecha");
// Iterate over it.
let mut v = Vec::new();
for kind in &tree {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
assert_eq!(v, ["droid", "jaeger", "mecha", "robot"]);
assert_eq!(tree.iter()
.map(|name| format!("mega-{}", name))
.collect::<Vec<_>>(),
vec!["mega-droid", "mega-jaeger",
"mega-mecha", "mega-robot"]);
let mut iterator = (&tree).into_iter();
assert_eq!(iterator.next(), Some(&"droid"));
assert_eq!(iterator.next(), Some(&"jaeger"));
assert_eq!(iterator.next(), Some(&"mecha"));
assert_eq!(iterator.next(), Some(&"robot"));
assert_eq!(iterator.next(), None);
// Construct a tree by hand.
let left_subtree = make_node(Empty, "mecha", Empty);
let right_subtree = make_node(make_node(Empty, "droid", Empty),
"robot",
Empty);
let tree = make_node(left_subtree, "Jaeger", right_subtree);
// Try initializing the iterator ourselves and see if it runs.
let mut v = Vec::new();
let mut iter = TreeIter { unvisited: vec![] };
iter.push_left_edge(&tree);
@ -214,33 +238,23 @@ fn external_iterator() {
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
// Iterate by shared reference.
let mut v = Vec::new();
for kind in &tree {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
// Iterate, taking ownership.
let mut v = Vec::new();
let mut state = tree.into_iter();
while let Some(kind) = state.next() {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
assert_eq!(tree.iter()
.map(|name| format!("mega-{}", name))
.collect::<Vec<_>>(),
vec!["mega-mecha", "mega-Jaeger",
"mega-droid", "mega-robot"]);
let mut iterator = tree.into_iter();
assert_eq!(iterator.next(), Some(&"mecha"));
assert_eq!(iterator.next(), Some(&"Jaeger"));
assert_eq!(iterator.next(), Some(&"droid"));
assert_eq!(iterator.next(), Some(&"robot"));
assert_eq!(iterator.next(), None);
}
#[test]
fn other_cloned() {
use std::collections::BTreeSet;
@ -257,13 +271,12 @@ fn other_cloned() {
#[test]
fn fuzz() {
fn make_random_tree(p: f32) -> BinaryTree<i32> {
use rand::{ThreadRng, thread_rng};
use rand::distributions::range::Range;
use rand::distributions::Sample;
use rand::prelude::*;
use rand::thread_rng;
use rand::rngs::ThreadRng;
fn make(p: f32, next: &mut i32, rng: &mut ThreadRng) -> BinaryTree<i32> {
let mut range = Range::new(0.0, 1.0);
if range.sample(rng) > p {
if rng.gen_range(0.0 .. 1.0) > p {
Empty
} else {
let left = make(p * p, next, rng);

Loading…
Cancel
Save