- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想实现一个 trie对于整数索引序列。为了提高效率,节点的子节点通过索引序列而不是某种映射与节点相关联很重要。为了说明基本思想,这里是 Ruby 中的一个实现:
require 'virtus'
class TrieNode
include Virtus.model
attribute :terminal, Boolean, default: false
attribute :children, Array, default: []
def add(i, vec)
if i == vec.length
terminal = true
else
( children[vec[i]] ||= TrieNode.new ).add i + 1, vec
end
end
end
这是 Perl 中的相同内容:
package TrieNode;
use Moo;
has terminal => ( is => 'rw' );
has children => ( is => 'ro', default => sub { [] } );
sub add {
my ( $self, $i, $vec ) = @_;
if ( $i == @$vec ) {
$self->terminal(1);
}
else {
( $self->children->[ $vec->[$i] ] //= TrieNode->new )->add( ++$i, $vec );
}
}
'wheee!!!';
这是我在 Rust 中实现它的各种尝试之一:
struct TrieNode {
children: Vec<Option<TrieNode>>,
terminal: bool
}
impl TrieNode {
fn new() -> TrieNode { TrieNode { children: vec![], terminal: false } }
fn add(&mut self, i: usize, s: &Vec<usize>) {
if s.len() == i {
self.terminal = true;
} else {
let j = s[i];
let k = j - 1;
let ref mut c = self.children;
while c.len() < k {
c.push(None);
}
if c.len() < j {
let mut n = TrieNode::new();
n.add( i + 1, s );
c.push(Some(n));
} else {
let ref o = c[j];
match o {
Some(ref mut n) => {
n.add( i + 1, s );
},
None => {
let mut n = TrieNode::new();
n.add( i + 1, s );
c.remove(j);
c.insert(j, Some(n));
}
}
}
}
}
}
对于它的值(value),这里是该尝试的编译错误:
file_toy (master #) $ cargo build
Compiling file_toy v0.1.0 (file:///Users/houghton/playground/file_toy)
src/main.rs:27:21: 27:36 error: mismatched types:
expected `&_`,
found `core::option::Option<_>`
(expected &-ptr,
found enum `core::option::Option`) [E0308]
src/main.rs:27 Some(ref mut n) => {
^~~~~~~~~~~~~~~
src/main.rs:27:21: 27:36 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:30:21: 30:25 error: mismatched types:
expected `&_`,
found `core::option::Option<_>`
(expected &-ptr,
found enum `core::option::Option`) [E0308]
src/main.rs:30 None => {
^~~~
src/main.rs:30:21: 30:25 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:28:27: 28:30 error: the type of this value must be known in this context
src/main.rs:28 n.add( i + 1, s );
^~~
error: aborting due to 3 previous errors
error: Could not compile `file_toy`.
它的预期用途是 this 的 Rust 实现.这个 trie,一旦被序列填满,将是不可变的,并将在程序的整个生命周期内存在。我这样做是为了学习 Rust,所以我的愚蠢越多越好。谢谢!
最佳答案
你的控制流程有点绕,而且有很多嵌套。通过减少嵌套和展开控制流,我们可以得到一些更可口的东西。我也希望避免所有冗余。
#[derive(Clone, Debug, Default)]
struct TrieNode {
children: Vec<Option<TrieNode>>,
terminal: bool
}
impl TrieNode {
pub fn add(&mut self, element: &[usize]) {
if element.len() == 0 {
self.terminal = true;
return;
}
let ref mut c = self.children;
let value = element[0];
// Ensure there is at least "value" children
if c.len() < value { c.resize(value, None); }
// Ensure the "value"th child is a full TrieNode
if c[value - 1].is_none() {
c[value - 1] = Some(TrieNode::default());
}
c[value - 1].as_mut().unwrap().add(&element[1..]);
}
}
fn main() {
let mut t = TrieNode::default();
t.add(&[1, 2]);
println!("{:?}", t);
}
烦人的是 add
的后 6 行。 match
在概念上更优雅,但是您不能在 match
期间借用 c[value - 1]
并在 中修改它code>None
分支,因为借用检查不是“路径感知”的,而只是“范围感知的”( future 可能会取消的限制,但我们现在必须应对)。
建议:
Vec::resize
而不是 while
循环可以更准确地传达意图。new()
不带参数时,最好实现 Default
特征(打开更多门);此外,Default
可以定期派生,因此您甚至不必输入它!String
/Vec
的所有权时使用切片。除了使代码更通用(任何可对切片取消引用的类型都可以工作)之外,我们还受益于索引符号 [1..]
以廉价地切断第一个元素,从而避免携带额外的索引。所有这些都使代码更短,更少的代码通常意味着更少的错误出现的机会。尤其是在避免重复的情况下。
另一方面,如果您愿意为 child 使用 HashMap
或 BTreeMap
,您可以获得免费的“稀疏”和更简单的添加方法。例如,修改为 use std::collections::HashMap
的 add
方法:
impl TrieNode {
pub fn add(&mut self, element: &[usize]) {
if element.len() == 0 {
self.terminal = true;
return;
}
self.children
.entry(element[0])
.or_insert(TrieNode::default())
.add(&element[1..]);
}
}
很多,很多,更简单,不是吗?
关于rust - 你如何在 Rust 中实现这个简单的 trie 节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36957286/
我正在努力实现以下目标, 假设我有字符串: ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ) ) ) ) ) 我想编写一个正则
给定: 1 2 3 4 5 6
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
大家好,我卡颂。 Svelte问世很久了,一直想写一篇好懂的原理分析文章,拖了这么久终于写了。 本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一
身份证为15位或者18位,15位的全为数字,18位的前17位为数字,最后一位为数字或者大写字母”X“。 与之匹配的正则表达式: ?
我们先来最简单的,网页的登录窗口; 不过开始之前,大家先下载jquery的插件 本人习惯用了vs2008来做网页了,先添加一个空白页 这是最简单的的做法。。。先在body里面插入 <
1、MySQL自带的压力测试工具 Mysqlslap mysqlslap是mysql自带的基准测试工具,该工具查询数据,语法简单,灵活容易使用.该工具可以模拟多个客户端同时并发的向服务器发出
前言 今天大姚给大家分享一款.NET开源(MIT License)、免费、简单、实用的数据库文档(字典)生成工具,该工具支持CHM、Word、Excel、PDF、Html、XML、Markdown等
Go语言语法类似于C语言,因此熟悉C语言及其派生语言( C++、 C#、Objective-C 等)的人都会迅速熟悉这门语言。 C语言的有些语法会让代码可读性降低甚至发生歧义。Go语言在C语言的
我正在使用快速将 mkv 转换为 mp4 ffmpeg 命令 ffmpeg -i test.mkv -vcodec copy -acodec copy new.mp4 但不适用于任何 mkv 文件,当
我想计算我的工作簿中的工作表数量,然后从总数中减去特定的工作表。我错过了什么?这给了我一个对象错误: wsCount = ThisWorkbook.Sheets.Count - ThisWorkboo
我有一个 perl 文件,用于查看文件夹中是否存在 ini。如果是,它会从中读取,如果不是,它会根据我为它制作的模板创建一个。 我在 ini 部分使用 Config::Simple。 我的问题是,如果
尝试让一个 ViewController 通过标准 Cocoa 通知与另一个 ViewController 进行通信。 编写了一个简单的测试用例。在我最初的 VC 中,我将以下内容添加到 viewDi
我正在绘制高程剖面图,显示沿路径的高程增益/损失,类似于下面的: Sample Elevation Profile with hand-placed labels http://img38.image
嗨,所以我需要做的是最终让 regStart 和 regPage 根据点击事件交替可见性,我不太担心编写 JavaScript 函数,但我根本无法让我的 regPage 首先隐藏。这是我的代码。请简单
我有一个非常简单的程序来测量一个函数花费了多少时间。 #include #include #include struct Foo { void addSample(uint64_t s)
我需要为 JavaScript 制作简单的 C# BitConverter。我做了一个简单的BitConverter class BitConverter{ constructor(){} GetBy
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我是 Simple.Data 的新手。但我很难找到如何进行“分组依据”。 我想要的是非常基本的。 表格看起来像: +________+ | cards | +________+ | id |
我现在正在开发一个 JS UDF,它看起来遵循编码。 通常情况下,由于循环计数为 2,Alert Msg 会出现两次。我想要的是即使循环计数为 3,Alert Msg 也只会出现一次。任何想法都
我是一名优秀的程序员,十分优秀!