【问题标题】:Non-destructive sort in lisp?lisp中的非破坏性排序?
【发布时间】:2016-03-06 02:14:14
【问题描述】:

我的任务是创建一个程序,在其中我需要一个函数来返回一个排序列表(按字母顺序)。但是,我无法使用“非功能性”功能,例如“set,setq”等......其中包括内置的排序功能(因为它具有破坏性)。所以,我想知道是否有办法在 lisp 中构建非破坏性排序?

【问题讨论】:

  • 这是作业吗?否则,这种限制听起来像是纯粹的煽动。不,您在 Common Lisp 中没有非破坏性排序。务实一点,只需创建一个复制序列的函数,在副本上运行sort 并返回sort 的结果。然后,您可以假设或假装这个新功能是非破坏性的。不要误会我的意思,我喜欢纯函数式代码,只要它与非函数式方法一样快,并且它不会强迫我跳过障碍。如果你被催促跳转,你必须自己实现一个函数排序。
  • 我认为普通 lisp 的典型做法是对列表的新副本使用破坏性排序。这满足了“功能性”api,因为调用者无法观察任何副作用,并且相同的输入总是得到相同的输出。

标签: sorting lisp


【解决方案1】:

最简单的方法是在排序前复制一份:

(sort (copy-seq input) predicate)

或者你自己写一个排序函数,例如快速排序:

(defun qsort (input predicate)
  (if input
    (let* ((pivot (first input))
           (rest (rest input))
           (lesser (remove-if-not #'(lambda (x)
                                      (funcall predicate x pivot))
                                  rest))
           (greater (remove-if-not #'(lambda (x)
                                       (not (funcall predicate x pivot)))
                                   rest)))
      (append (qsort lesser predicate)
              (list pivot)
              (qsort greater predicate)))
    nil))

(Demo)

请注意,可以对此进行优化以检测列表中已排序的其余部分,从而在未排序列表和已排序列表之间实现结构共享。

【讨论】:

    【解决方案2】:

    如果您的破坏性排序执行类似交换两个相邻元素的操作,这些相邻元素被您保持不变的元素包围,那么一种非破坏性方法是创建一个新列表,该列表由交换的这两个元素组成,并被其他元素包围。然后,您使用该新列表作为后续排序操作的基础。

    破坏性地,您的工作列表从头到尾都是相同的,您可以通过将一个“地方”中的值替换为另一个“地方”中的值来修改它。非破坏性地,在每个步骤中,您都会创建一个成为工作列表的新列表。

    我将把实现留给你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多