我目前正在对Coursera斯卡拉当然工作后,我的空闲时间,企图最后给一个尝试函数式编程。 我目前的工作在哪里,我们都应该为“计算”的包含一些对象两套工会的任务。 我有意忽略的细节,因为它不是什么我想在这里问真的很重要。 什么是相关的,但是,是在集被定义为二进制树,含有元素的每个节点,和两个子树。
既然如此; 的例子中union
在演讲如下:
def union(other:BTSet) :BTSet = ((left union right) union other) incl element
问题1:坦率地说,即使在看了相关的常见问题等论坛主题,我还是不明白如何以及为什么此功能。 绝对没有任何“动作”在这里做工会执行除了会增加(在incl
调用)在头节点的元素,它只是自称一遍又一遍。 我会很感激的一些解释...
问题2:该课程论坛包含了许多帖子,指出这个解决方案不是有效的一切,这是不够好。 眼看我不明白它是如何与我开始不明白为什么这还不够好。
请注意,我不以任何方式,询问分配解决方案扰流板。 我更愿意以“为等级做的工作”以上,但我根本不明白我应该在这里做。 我不相信在使用过程中提供的说明和指导,足以环绕函数式编程的怪癖你的头,所以我欢迎任何的意见/,解决怎么想的权利 ,而不是如何编写正确的答案。
A
/ \ union D
B C
((B union C) union D) incl A
^^^^^^^^^......................................assume it works
( B )
( \ union D ) incl A
( C )
(((0 union C) union D) incl B) incl A
^^^^^^^^^.....................................just C
(((C union D) incl B) incl A
^^^^^^^^^.....................................expand
((((0 union 0) union D) incl C) incl B) incl A
^^^^^^^^^....................................just 0
(((0 union D) incl C) incl B) incl A
^^^^^^^^^.....................................just D
((D incl C) incl B) incl A
^^^^^^^^^^^^^^^^^^^^^^^^^^.......................all incl now
只是把它写出来一步一步来。 现在你看到工会降低了一堆应用到右手的说法含语句。
我推测, incl
插入一个元素现有的一组? 如果是这样,这就是所有的实际工作中发生的事情。
工会的定义是包括在任一输入集中的所有设定。 由于两套存储为二进制树,如果你把第一组与第二的分支工会,在任何可能的结果会丢失的唯一因素是在第二树的根节点元素,因此,如果你插入你有两个输入集合的并集该元素。
这只是从两个组,每个组元素插入一个新的一套开始是空的非常低效的方式。 据推测重复被丢弃incl
,所以结果是两个输入的结合。
也许这将有助于忽略的树结构的那一刻; 它不是必要的算法非常重要。 假设我们有抽象的数学套。 鉴于输入与未知元素设定,我们可以做两分事情的事情:
- 元素添加到它(这什么也不做,如果元素已经存在)
- 检查组是否非空,如果是这样,它分解成一个单一的元素,两个不相交的子集。
为了利用两套{1,2}和{2,3}的联合,我们开始通过分解所述第一组到元件1和子集{}和{2}。 我们递归采取的{},{2},并使用相同的工艺{2,3},然后插入1联合到结果。
在每个步骤中,问题是从一个联合操作减少到较小输入的两个联合操作; 标准分而治之算法。 当到达一个单集{X}和空集{}的并集,工会是平凡{X},然后将其返回备份链。
树形结构只是用来都允许的情况下分析/分解成更小的集合,并且使插入更有效。 同样可以使用其他数据结构,诸如被分成两半用于分解,并用插入由一个详尽检查唯一完成列表来完成。 要采取有效的联合需要一个算法,更聪明一点,并采取用于存储元件结构的优势。
因此,基于以上所有的答复,我认为真正的主力是incl
和调用的递归的方式union
仅仅是通过集合所有元素去。
我想出了以下实现联盟,这是更好?
def union(other:BTSet) :BTSet = right union (left union (other incl element))
2
/ \ union 4
1 3
((1 union 3) union 4) incl 2
^^^^^^^^^......................................assume it works
(((E union E) union 3 incl 1) union 4) incl 2
^^^^^^^^^.....................................still E
(E union E) union 3 incl 1 = E union 3 incl 1 = 3 incl 1
以下子树应该是3 含 1
( 3 )
( \ union D ) incl 2
( 1 )
(((1 union E) union 4) incl 3) incl 2
^^^^^^^^^.......................................expand
(((( (E union E) union E) incl 1) union 4) incl 3) incl 2
^^^^^^^^^^^^^^^^^^^^^^^^^^..................still 1
((1 union 4) incl 3) incl 2
^^^^^^^^......................................continue
((((E union E) union 4) incl 1) incl 3) incl 2
^^^^^^^^^^^^^^^^^^^^^^^^^^^^..........expand 1 union 4
((4 incl 1) incl 3) incl 2
^^^^^^^^^^^^^^^^^^^^^^^^^............Final union result
由于@Rex克尔引出的步骤。 我代替与实际运行时的步骤,其可以得到的Scala的更清楚的描述在第二步骤union
功能。
除非你看看基本情况你可以不理解递归算法。 事实上,通常情况下,理解的关键在于首先了解基本情况。 由于没有显示基本情况(可能是因为你没有注意到有一个摆在首位)没有理解可能。
我在做相同的课程,和上述实施union
也变成是非常低效的。
我想出了以下不那么实用的解决方案,以创造二叉树集的结合,这是远远更有效率:
def union(that: BTSet): BTSet = {
var result:BTSet = this
that.foreach(element => result = result.incl(element))
result
}