Sorting 函数式编程语言中的排序

Sorting 函数式编程语言中的排序,sorting,functional-programming,Sorting,Functional Programming,我学习函数式编程已经有一段时间了,但我还并没有读过关于函数式编程语言排序的书 我知道基于值交换的排序算法很难用函数思想实现,但我想知道,有没有用于函数编程的排序算法?它们是什么 谢谢。以下是Haskell中的经典()快速排序: sort [] = [] sort (p:xs) = sort [x | x<- xs, x <= p] ++ [p] ++ sort [x | x <- xs, x >

我学习函数式编程已经有一段时间了,但我还并没有读过关于函数式编程语言排序的书

我知道基于值交换的排序算法很难用函数思想实现,但我想知道,有没有用于函数编程的排序算法?它们是什么

谢谢。

以下是Haskell中的经典()快速排序:

sort []      =   []
sort (p:xs)  =   sort [x | x<- xs, x <= p]
              ++ [p]
              ++ sort [x | x <- xs, x > p]
排序[]=[]

sort(p:xs)=sort[x | x这里有一些链接指向Haskell中实现的排序算法:

sort []      =   []
sort (p:xs)  =   sort [x | x<- xs, x <= p]
              ++ [p]
              ++ sort [x | x <- xs, x > p]
合并排序通常是对链表进行排序的最佳选择。函数式语言通常在列表上运行,尽管我对大多数函数式语言如何实现列表知之甚少。在常见的Lisp中,它们是作为链表实现的,我认为大多数函数式语言也会这样做

虽然可以为链表编写快速排序,但由于随机访问,数据透视选择较差。虽然这对于完全随机输入并不重要,但对于部分或完全排序的输入,数据透视选择变得非常重要。其他排序算法也可能因链表的缓慢随机访问性能而受到影响


另一方面,合并排序可以很好地用于链表,并且可以实现该算法,这样它只需要链表中的一些常量额外空间。

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

例如,考虑合并排序…首先编写一个函数,给定两个已排序的列表,该函数返回一个已排序的列表,其中包含这两个列表的元素。例如:

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:])
def合并(a,b):
如果len(a)==0:
返回b
elif len(b)==0:
归还
如果a[0]
然后,您可以编写一个函数,通过合并排序列表前半部分和后半部分的结果来对列表进行排序

def mergesort(x):
    if len(x) < 2:
        return x
    else:
        h = len(x) // 2
        return merge(mergesort(x[:h]), mergesort(x[h:]))
def合并排序(x):
如果len(x)<2:
返回x
其他:
h=len(x)//2
返回merge(mergesort(x[:h]),mergesort(x[h:]))
关于Python语法:

  • L[0]
    是列表的第一个元素
    L
  • L[1:][/code>是所有剩余元素的列表
  • 更一般地说,
    L[:n]
    是第n个元素的列表,
    L[n:][/code>其余元素的列表
  • A+B
    如果
    A
    B
    都是列表,则通过串联获得列表
  • [x]
    是仅包含单个元素的列表
    x

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

您当然可以在函数式语言中实现命令式排序算法


我已经实现了一种排序算法,它在一种叫做ATS的函数式编程语言中运行;所有的变异都是由线性类型处理的。如果你对这种事情感兴趣,请给我写信。

我可能是从坟墓里提这个问题,但我认为全局比较方法可能对某些人有用(例如,如果我们没有对数字进行排序)。以下是使用ES6的TypeScript版本:

TL;DR

type Comparator=(itemA:T,itemB:T)=>number;
const mergeSort=(列表:T[],比较:Comparator):T[]=>{
if(list.length){
如果(listA.length==0)返回listB;
如果(listB.length==0)返回listA;

return compare(listA[0],listB[0])我所知道的唯一问题是不能使用不可变结构实现就地算法。@Goran Jovic:谢谢你的观点。我仍然在以过程的方式思考。:-)不客气。顺便说一句,在命令式语言中也不能使用不可变的就地排序。只是命令式语言通常有默认的可变结构库。只要“复制”,就可以对不可变的数据结构进行就地排序在每一步中,编译器都可以证明以前的值从未被使用过:即使用monad。然而,这并不简单:(免责声明:Jon Harrop确实有一把斧子要与haskell一起磨)。在我看来,这将潜入额外的值,因为枢轴将包含在左侧子列表中。事实并非如此。请注意,输入列表通过模式匹配分为
p
xs
。(当然,
xs
中可能有等于
p
的值。)关于这个版本的快速排序算法,Andrei Alexandrescu在他的文章中说了一些有趣的事情。基本上,它不是真正的快速排序,因为它不在适当的位置工作;其次,它对枢轴元素的选择不是最佳的。推荐阅读。这不是快速排序:它不在适当的位置,通常会被忽略e生成二次复杂度:不要使用!@Eamon:我不是建议OP应该使用这个算法,这是一个如何在FP中实现排序的示例。OP应该使用他们语言的标准库中的算法。也就是说,我更新了我的答案,参考了Alexandrescu有趣的文章,所以我希望你能收回这篇文章-1.您应该指出,其中一个函数式排序比函数式世界中的所有其他函数式排序都要好。@Eamon,我以前没有听说过函数式语言使用的算法是合并排序。不过,我已经添加了一些解释,解释了为什么会这样。如果您特别提到什么,我已经给出了这是拉斯曼提出的更好的解决方案:不要使用快速排序,使用合并排序。h=len(x)应该是m=len(x)/2,但ve