【问题标题】:Writing Bubble Sort using Foldl or Foldr in SML在 SML 中使用 Foldl 或 Foldr 编写冒泡排序
【发布时间】:2023-11-09 09:04:01
【问题描述】:

有没有办法使用 SML 中可用的 Foldl 或 Foldr 方法来实现冒泡排序?任何指导都会有所帮助。

【问题讨论】:

  • 我相信你可以。使用 foldl 可能需要您在每次遍历它时反转列表的顺序,因此您必须跟踪它的方向,以便在必要时可以最后一次反转它。
  • 您在“carry value”中携带的状态将必须跟踪累积的排序元素和标记您是否已在此通行证上更改列表的标志。 (并且,如前所述,可能在此过程中列表是否颠倒。)

标签: sorting functional-programming sml bubble-sort smlnj


【解决方案1】:

我刚刚在 OCaml 中编写了一个实现来展示我自己满意的技术。

我将排序过程分为两部分。一个是通过 fold_left (foldl) 调用的比较和交换函数。该函数具有以下类型(bool 是本次扫描中是否发生交换):

bool * 'a list -> 'a -> bool * 'a list

每次运行时,它都会在适当的情况下进行交换,在其结果中构建一个新列表,该列表以与输入相反的顺序组成。 (这是必要的,因为 foldl 的从左到右的尾递归行为。)它还跟踪在此列表扫描中是否进行了任何交换(这是必要的,因此我们知道何时停止排序)。

另一个函数是递归的,只是不断调用扫描,直到没有进行任何更改。此函数还有一个布尔值,它会在每次调用时切换以跟踪列表当前是否反转。当它发现在最近一次扫描中没有进行交换时,它会返回结果列表。如果列表当前被反转,则在返回之前最后一次反转它。

这是第二个函数的类型(这里的布尔值是列表当前是否反转):

bool -> 'a list -> 'a list

应该同样可以编写使用 foldr 的冒泡排序。它不会是尾递归的(因为 foldr 不是),并且由于它从右到左扫描列表,因此您不必处理 foldl 遇到的反转问题。

【讨论】:

  • 您几乎正在编写两个函数,一个跟踪是否发生交换并进行交换,另一个调用该交换和一个布尔值以查看是否发生交换。如果没有发生交换,则返回列表。您还确定Foldl 是从左到右的吗,从文档看来它是从右到左的,而Foldr 是从左到右的。这可能只是我分析它的错误。这是:List Structure SML Reference
  • @Rootkit32:我想这取决于你对“从左到右”的定义。我可以肯定的是 foldl 在尾部之前处理列表的头部。 Foldr 首先处理尾部,然后返回头部。实际上,我有三个函数:有一个“主”函数,它只接受一个列表作为参数,它所做的只是在我的答案中使用适当的起始参数调用函数 #2。
【解决方案2】:

我知道现在回答您的问题为时已晚,但希望这会有所帮助:

fun bsort [] = []
|   bsort [x] = [x]
|   bsort (x::y::xs) =   
                    if(y<x) then
                        y::bsort(x::xs)
                    else
                        x::bsort(y::xs);

fun bubblesort [] = []
|   bubblesort (x::xs) = bsort(x::(bubblesort(xs)));

记住,我们必须进行冒泡排序,直到列表完全排序。

【讨论】:

    最近更新 更多