Haskell中选择排序的功能性非尾递归版本

时间:2019-05-13 12:19:24

标签: haskell selection-sort

我正在寻找Haskell中以下selection sort代码的非尾递归版本:

import Data.List (minimum, delete)

ssort :: Ord t => [t] -> [t]
ssort [] = []
ssort xs = let { x = minimum xs } in  x : ssort (delete x xs)

能否请您提供选择排序的非尾递归版本?

我知道更改原始代码不是一个好主意,但是我需要该版本才能进行实验。

2 个答案:

答案 0 :(得分:5)

简短答案:代码不是递归的

  

能否请您提供选择排序的非尾递归版本?

代码不是不是尾递归。它是"tail recursive modulo cons" [wiki],但不是尾递归。

Haskell wiki显示了如何确定函数是否为尾递归:

  

这是“尾递归”的正式定义。 “ f发生在t中”   表示ft的自由变量。

     

将函数定义为(在let或顶层)时:

f = t
     

其中f是名称,t是lambda项,f是尾递归   如果ft中以递归方式出现在尾部。 f递归出现在   t仅当f出现在t中且具有以下任一条件时:

     
      
  • t是可变的;
  •   
  • t\var -> t0,并且f在t0中以递归方式出现在尾部;
  •   
  • tt0 t1,并且f在t0中以递归方式出现在尾部,而在t1中则不出现;
  •   
  • tlet bs in t0,并且ft0中以递归方式出现在尾部,并且对于var = t1中的每个活页夹bsft1中不会发生;
  •   
  • tcase t0 of bsf中没有t0b中的每个分支bsf才不是   在b中出现或以递归方式出现在尾部;      
        
    • 当我们说“发生在   b”,b的格式为D vars -> t1(其中D是一些数据构造函数,   vars是一系列名称),我们正在考虑   拉姆达抽象\vars -> t1而非b
    •   
  •   

表达式t\xs -> let x = minimum xs in x : ssort (delete x xs),所以我们可以在这里取第二项,但是ssort必须在let ... in ...语句中为尾递归,这是第四种情况。

但是第四种情况要求ssortlet ... in ...表达式的“ body”中是尾递归的。此表达式为((:) x) (ssort delete xs)。因此,这是第三种情况。

在第三种情况下,表达式的形状为t0 t1,此处为t0 = (:) xt1 = ssort delete xs。由于ssort中没有出现t0,因此这里没有尾递归。

答案 1 :(得分:3)

由于您调用: cons函数,因此显示的代码不是尾部递归的。所有递归调用将保留在内存堆栈上,等待对ssort (delete x xs)的求值完成。尾递归版本可能如下所示:

import Data.List (minimum, delete)

ssort :: Ord t => [t] -> [t] -> [t]
ssort [] acc = reverse acc
ssort xs acc = let { x = minimum xs } in ssort (delete x xs) (x : acc)