代码直接映射到您提供的描述。
让我们举一个简单的例子来演示用法:你首先有一个空集合,比如说,e
然后你添加一个元素来获得另一个集合,比如说s1
。然后,您将拥有 2 套,e
并且s1
:
val e = Empty
e contains 42 // will be false
// create s1 from e
val s1 = e incl 1 // e does not change; it remains a reference to the Empty set.
// Now we have s1, a set that should contain (1) and nothing else.
s1 contains 1 // will be true
s1 contains 42 // will be false
我猜你很熟悉 Scala 速记,它可以让你输入
s1 incl 1
而不是s1.incl(1)
请注意,只能有一个空集,所以这同样好:
val s1 = Empty incl 1
然后假设您要添加,例如2
获取另一个s2
元素必须包含两者的集合{1, 2}
。
val s2 = s1 incl 2
s2 contains 1 // true
s2 contains 2 // true
s2 contains 3 // false
因此incl
,任何集合上的方法都接受一个元素并返回一个新集合——它不会更改集合(include
调用该方法的原始对象 ob)。
我们有两种类型的树集;空的和非空的,每个都有一个实现incl
:
// Empty
def incl(x:Int): IntSet = new NonEmpty(x, Empty, Empty)
阅读:“将一个元素添加到一个空(树)集合会产生另一个集合,它是一个非空树,只有一个具有值的根节点1
和空的左右子树。”
非空集合有一个构造函数参数elem
,它代表树的根并且对NonEmpty
.
// Non-Empty
def incl(x: Int): IntSet =
if (x < elem) new NonEmpty(elem, left incl x, right)
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this
读取:(以上述 if-else 的相反顺序):
- 将元素添加到根
x
元素为的非空集合中也会
得到相同的集合 ( )x
this
- 将元素添加到其根元素小于
x
的非空集合中
会给您另一个集合,其中:
x
- 根元素与原始集合相同
- 左子树不变 - 与原始集合相同
- 新的右子树成为
x
添加到它的原始右子树“:right incl x
- 将一个元素添加到其根元素大于
x
的非空集合中
会给您另一个集合,其中:
x
- 根元素与原始集合相同
- 右子树不变 - 与原始集合相同
- 新的左子树成为
x
添加到它的原始左子树“:left incl x
“持久性”是通过没有任何树或子树被更改的事实来实现的。在示例中
val s1 = Empty incl 1 // s1 is a tree with only a root(1) an no branches.
val s2 = s1 incl 2 // s2 is another tree with -
// - the same root(1),
// - the same left-subtree as s1, (happens to be Empty)
// - a new subtree which in turn is a tree with -
// - the root element (2)
// - no left or right brances.
s1 contains 1 // true
s1 contains 2 // false
s2 contains 1 // true
s2 contains 2 // true
val s3 = s2 incl -3 // s2.incl(-3)
// from s2 we get s3, which does not change s2's structure
// in any way.
// s3 is the new set returned by incl, whose
// - root element remains (1)
// - left subtree is a new tree that contains
// just (-3) and has empty left, right subtrees
// - right subtree is the same as s2's right subtree!
s3.contains(-3) // true; -3 is contained by s3's left subtree
s3.contains(1) // true; 1 is s3's root.
s3.contains(2) // true; 2 is contained by s3's right subtree
s3.contains(5) // false
我们仅incl
用于从其他集合派生集合(树),而不更改原始集合。这是因为在非常阶段,我们要么——
- 根据现有结构返回新的数据结构,而不是修改现有结构,或者,
- 原样返回现有结构。
contains
以同样的方式工作:Empty
有一个返回false
任何输入的实现。NonEmpty
如果给定元素与其根元素相同,或者它的左子树或右子树包含它,则快速返回 true!