Recursion 递归地比较两个集合是否相等?

Recursion 递归地比较两个集合是否相等?,recursion,scheme,set,racket,equality,Recursion,Scheme,Set,Racket,Equality,一般来说,我对编程相当陌生,我正在尝试构造一个函数,该函数将以两个集合作为输入,这两个集合可以包含其他集合(a(bc)dee(fg(h)),(abc(def))例如,和返回它们是否相等。如果有帮助,我正在使用scheme,但我真的在尝试想象我可以如何做。提前感谢您的帮助一个简单的递归方法是选择集合A中的一个元素并在集合B中查找相等的元素。如果找到了一个元素,则从A和B中删除这两个元素和递归。如果两个集合都为空,则停止成功;如果恰好有一个为空,或者如果从A中选择的元素在B中没有对应的元素,则停止失

一般来说,我对编程相当陌生,我正在尝试构造一个函数,该函数将以两个集合作为输入,这两个集合可以包含其他集合(a(bc)dee(fg(h)),(abc(def))例如,和返回它们是否相等。如果有帮助,我正在使用scheme,但我真的在尝试想象我可以如何做。提前感谢您的帮助

一个简单的递归方法是选择集合A中的一个元素并在集合B中查找相等的元素。如果找到了一个元素,则从A和B中删除这两个元素和递归。如果两个集合都为空,则停止成功;如果恰好有一个为空,或者如果从A中选择的元素在B中没有对应的元素,则停止失败。

某些语言具有内置的集合类型,包括Racket。因此,唯一的问题是转换列表(可能包含其他列表)比如:(警告-完全未测试的代码)

基本上,我们不使用原子,而是在递归转换的元素上使用内置的
list->set
函数构建列表集。

两个关键点: (a) 单个部件的匹配类型相同性试验 (b) 当您到达“核心”元素值时,测试匹配值

无论您使用哪种编程语言,如果我们查看列表的一部分,例如,(a(bc)…)和(abc…),在看到“a”之后,我们会注意到每个列表都是不同的类型。第一个列表在“a”之后有一个列表,而第二个列表在a之后有另一个非列表元素。语言可能会失败(发出某种错误的信号)或者允许您类似地考虑这些不同类型,但通常提供一种查询类型的方法。 在scheme(我记不清了)中,第一个列表的car值是a,cdr值是list((bc)…)。第二个列表的car值是a,但cdr返回list(bc…)。这两个值不能相同,除非该语言提供了不同的“相同性”视图

这种对象类型测试将是查看列表是否相同的第一步

接下来,我们在已经验证的相同结构中的相应位置测试基本元素值。我们必须以正确的方式遍历结构(即,取决于结构细节)

遍历的算法细节取决于编程语言。一些语言在避免错误和测试相同性方面比其他语言提供更多帮助

我们可以使用递归或迭代的方法。对于scheme,从概念上讲,递归更自然

示例伪代码,其中类型和值都由组合测试处理=

function f (l1, l2):
(=? car(l1) car(l2))
and
(f cdr(l1) cdr(l2))
我们注意到递归。它的作用是,如果你得到一个简单的元素,它会测试等式并返回该值。如果该函数是直接调用的,那么这就是最终的答案,如果它是递归调用的,那么它会将该答案发送回函数调用链,并进行一些嵌套(f cdr(l1)cdr(l2))返回false或true,最终进行最高级别的调用也会返回false或可能仍然能够返回true(请注意“and”要求及其工作方式。只有当每个部分都为true时,true才会出现,而如果任何部分为false时,false就会出现)。同样,如果函数得到一个列表,则它会测试汽车部件和“and”当它在列表的其余部分上再次递归调用自己时,它会将这个t/f值与它所得到的任何值一起处理。因此,这个函数在您提供给它的子列表的任何复杂结构中处理列表和非列表。[记住,我们假设=?同时管理类型和值检查,例如,=?b'(b))将是#f]

[另外,请参阅您可能用于测试等效性的内容。]

听起来非常非常O(n²)。有一些摊销O(n)的方法可以解决OP的问题。这是否为O(n*n)取决于如何实现“拾取和元素”和“查找相等元素”。如果集合是可排序的,则在排序后,“查找相等元素”(或失败)如果将“pick an element”实现为“pick the first element”,则可以在O(1)中实现。但对于排序来说,这是O(n lg n)。我不知道有什么递归方法可以做得更好。
function f (l1, l2):
(=? car(l1) car(l2))
and
(f cdr(l1) cdr(l2))