Lisp 比较集合的函数;有助于提高效率

Lisp 比较集合的函数;有助于提高效率,lisp,common-lisp,Lisp,Common Lisp,我试图编写一个函数,比较两个列表,看看它们是否代表同一个集合。也就是说,‘abcdd’和‘dcbdad’代表同一个集合。元素可以是任意顺序 这就是我所拥有的,有效的: (defun samesetp (list1 list2) (cond ((null list1) (null list2)) ((eq list2 (remove (car list1) list2 :count 1)) nil) (t (samesetP (cdr list1) (remove (c

我试图编写一个函数,比较两个列表,看看它们是否代表同一个集合。也就是说,‘abcdd’和‘dcbdad’代表同一个集合。元素可以是任意顺序

这就是我所拥有的,有效的:

(defun samesetp (list1 list2)
  (cond
    ((null list1) (null list2))
    ((eq list2 (remove (car list1) list2 :count 1)) nil)
    (t (samesetP (cdr list1) (remove (car list1) list2 :count 1))))))
我不喜欢这样做的原因是remove car list1 list2:count 1被计算了两次——一次是测试remove操作是否真正删除了任何内容,一次是递归地测试该元素的其余列表

有人能提出一种不使用不同算法的改进方法吗

(defun samesetp (list1 list2)
    (cond
        ((null list1) (null list2))
        ((eq list2 (remove (car list1) list2 :count 1)) nil)
        (t (samesetP (cdr list1) (remove (car list1) list2 :count 1))))
    )
)
首先,让我们正确格式化它:

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        ((eq list2 (remove (car list1) list2 :count 1)) nil)
        (t (samesetP (cdr list1) (remove (car list1) list2 :count 1)))))
如果您两次使用一个表单并且想要更改它,那么您需要存储一个值。让我们来解释一下。如果它不适合一个条件,那么你需要第二个条件

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        (t (let ((list3 (remove (car list1) list2 :count 1)))
             (cond ((eq list2 list3) nil)
                   (t (samesetP (cdr list1) list3)))))))
现在,EQ不能用于比较列表。平等使用

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        (t (let ((list3 (remove (car list1) list2 :count 1)))
             (cond ((equal list2 list3) nil)
                   (t (samesetP (cdr list1) list3)))))))
此处的条件过高,请在以下情况下使用:

(defun samesetp (list1 list2)
  (if (null list1)
      (null list2)
    (let ((list3 (remove (car list1) list2 :count 1)))
      (if (equal list2 list3)
          nil
        (samesetP (cdr list1) list3)))))
现在,你只需要让函数做作业中要求的事情。但无论如何,这是你的家庭作业

首先,让我们正确格式化它:

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        ((eq list2 (remove (car list1) list2 :count 1)) nil)
        (t (samesetP (cdr list1) (remove (car list1) list2 :count 1)))))
如果您两次使用一个表单并且想要更改它,那么您需要存储一个值。让我们来解释一下。如果它不适合一个条件,那么你需要第二个条件

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        (t (let ((list3 (remove (car list1) list2 :count 1)))
             (cond ((eq list2 list3) nil)
                   (t (samesetP (cdr list1) list3)))))))
现在,EQ不能用于比较列表。平等使用

(defun samesetp (list1 list2)
  (cond ((null list1) (null list2))
        (t (let ((list3 (remove (car list1) list2 :count 1)))
             (cond ((equal list2 list3) nil)
                   (t (samesetP (cdr list1) list3)))))))
此处的条件过高,请在以下情况下使用:

(defun samesetp (list1 list2)
  (if (null list1)
      (null list2)
    (let ((list3 (remove (car list1) list2 :count 1)))
      (if (equal list2 list3)
          nil
        (samesetP (cdr list1) list3)))))

现在,你只需要让函数做作业中要求的事情。但这毕竟是你的家庭作业。

我想你不允许使用内置函数来解决问题,但请注意有一个:

(set-difference list1 list2)

我猜您不允许使用内置函数来解决问题,但请注意有一个:

(set-difference list1 list2)

您应该使用哈希表,这会将复杂性从^2降低到^2。我很困惑。你正在使用一个糟糕的算法,并且想要改进,只要它们不涉及修复坏的算法。为什么?正如@leppie所说的,使用哈希表。或者对两个列表进行排序,并并行遍历它们。更好的算法会比你关心的微观优化产生更大的影响。伙计们,冷静点,我们不允许使用哈希表。这是家庭作业问题的一部分。如果你能想出一个更有效的算法,它可以包含在大约10行代码中,请告诉我。不要在它们自己的代码行中使用后面的括号。Lisp不是C或Java。为了支持Rainer的评论-请看,您应该使用哈希表,这将使复杂性从^2降低到^2。我感到困惑。你正在使用一个糟糕的算法,并且想要改进,只要它们不涉及修复坏的算法。为什么?正如@leppie所说的,使用哈希表。或者对两个列表进行排序,并并行遍历它们。更好的算法会比你关心的微观优化产生更大的影响。伙计们,冷静点,我们不允许使用哈希表。这是家庭作业问题的一部分。如果你能想出一个更有效的算法,它可以包含在大约10行代码中,请告诉我。不要在它们自己的代码行中使用后面的括号。Lisp不是C或Java。为了支持Rainer的评论,请参阅“谢谢”。我明白了,这才是真正有帮助的。如果这对你有帮助的话,你应该把雷纳的回答标记为接受。我要补充的是,这是一个很好的答案,所以+1。是的,我做了标记。谢谢雷纳,我真的很感谢你的帮助!谢谢我明白了,这才是真正有帮助的。如果这对你有帮助的话,你应该把雷纳的回答标记为接受。我要补充的是,这是一个很好的答案,所以+1。是的,我做了标记。谢谢雷纳,我真的很感谢你的帮助!ITYM设置为独占或。对于集合差,参数的顺序很重要。ITYM set exclusive or。对于集合差,参数的顺序很重要。