在函数式编程语言中排序

Rya*_* Li 19 sorting functional-programming

我已经学习了一段时间的函数式编程,但我还没有读过有关使用函数式编程语言进行排序的内容.

我知道基于价值交换的排序算法很难用功能性的想法实现,但我想知道有没有用于函数式编程的排序算法?这些是什么?

谢谢.

650*_*502 23

在函数式语言中,您编写一个函数,给定一个列表返回一个排序列表,而不是接触(当然)输入.

考虑例如合并排序...首先你编写一个函数,给定两个已经排序的列表返回一个单独的排序列表,其中包含两个元素.例如:

def merge(a, b):
    if len(a) == 0:
        return b
    elif len(b) == 0:
        return a
    elif a[0] < b[0]:
        return [a[0]] + merge(a[1:], b)
    else:
        return [b[0]] + merge(a, b[1:])
Run Code Online (Sandbox Code Playgroud)

然后你可以编写一个函数,通过合并列表的第一和第二半的结果来对列表进行排序.

def mergesort(x):
    if len(x) < 2:
        return x
    else:
        h = len(x) // 2
        return merge(mergesort(x[:h]), mergesort(x[h:]))
Run Code Online (Sandbox Code Playgroud)

关于Python语法:

  • L[0] 是列表的第一个元素 L
  • L[1:] 是所有剩余元素的列表
  • 更一般地说,L[:n]是第n个元素的列表,L[n:]其余的
  • A + Bif AB是两个列表是通过串联获得的列表
  • [x] 是一个只包含单个元素的列表 x

PS:注意上面的python代码只是为了展示概念...在Python中这不是一个合理的方法.我使用Python是因为我认为如果你知道任何其他常见的命令式语言,它是最容易阅读的.

  • 这是一个比拉斯曼更好的解决方案:不要使用快速排序,使用合并排序。 (2认同)

Nöm*_*mik 11

以下是Haskell中实现的排序算法的一些链接:

合并排序通常是排序链表的最佳选择.功能语言通常在列表上运行,尽管我对大多数函数式语言如何实现列表知之甚少.在Common Lisp中,它们被实现为链表,我认为大多数函数式语言也是如此.

虽然可以为链表创建快速排序,但由于随机访问,它将受到不良的枢轴选择的影响.虽然这对完全随机输入无关紧要,但在部分或完全分类的输入枢轴选择变得非常重要.其他排序算法也可能受到链表的慢随机访问性能的影响.

另一方面,合并排序适用于链表,并且可以实现该算法,使得它仅需要链接列表的一些额外空间常量.


Fre*_*Foo 5

这是Haskell中的经典(伪 - ?)快速排序:

sort []      =   []
sort (p:xs)  =   sort [x | x<- xs, x <= p]
              ++ [p]
              ++ sort [x | x <- xs, x > p]
Run Code Online (Sandbox Code Playgroud)

参见,例如,c2.comLiteratePrograms.org.合并排序并不难写,在实践中更可靠.在Scheme中也可以这样做:

(define (sort xs)
  (if (null? xs)
    '()
    (let* ((p (car xs)) (xs (cdr xs)))
      (call-with-values (lambda () (partition (lambda (x) (<= x p)) xs))
                        (lambda (l r)
                          (append (sort l) (list p) (sort r)))))))
Run Code Online (Sandbox Code Playgroud)

partition从SRFI-1 (未测试的代码).另见R6RS库的第4章.

  • 关于这个版本的Quicksort算法,Andrei Alexandrescu在他的文章["On Iteration"](http://www.informit.com/articles/printerfriendly.aspx?p=1407357)中有一些有趣的内容.基本上,它不是真正的Quicksort,因为它不能就地工作; 第二,它对枢轴元件的选择不是最佳的.推荐阅读. (4认同)
  • 这不是快速排序:http://www.informit.com/articles/printerfriendly.aspx?p = 1407357它不是就地的,并且*通常会退化为二次复杂性:不要使用! (3认同)
  • 不是.请注意,输入列表通过模式匹配分为"p"和"xs".(当然,在'xs`中可能有等于'p`的值.) (2认同)
  • @Eamon:我不是建议OP应该*使用*这个算法,它是如何在FP中实现排序的*示例*.OP应该在他们语言的标准库中使用该算法.话虽这么说,我更新了我的回答,提到了Alexandrescu的有趣文章,所以我希望你会收回-1. (2认同)