如何在Scala中实现尾递归快速排序

2024-05-09

我写了一个递归版本:

def quickSort[T](xs: List[T])(p: (T, T) => Boolean): List[T] = xs match{
    case Nil => Nil
    case _ => 
         val x = xs.head
         val (left, right) = xs.tail.partition(p(_, x))
         val left_sorted = quickSort(left)(p)
         val right_sorted = quickSort(right)(p)
         left_sorted ::: (x :: right_sorted)
}

但我不知道如何将其更改为尾递归。谁能给我一个建议吗?


任何递归函数都可以转换为使用堆(而不是堆栈)来跟踪上下文。该过程称为trampolining http://en.wikipedia.org/wiki/Tail_recursion#Through_trampolining.

以下是如何使用 Scalaz 实现它。

object TrampolineUsage extends App {

  import scalaz._, Scalaz._, Free._

  def quickSort[T: Order](xs: List[T]): Trampoline[List[T]] = {
    assert(Thread.currentThread().getStackTrace.count(_.getMethodName == "quickSort") == 1)
    xs match {
      case Nil =>
        return_ {
          Nil
        }
      case x :: tail =>
        val (left, right) = tail.partition(_ < x)
        suspend {
          for {
            ls <- quickSort(left)
            rs <- quickSort(right)
          } yield ls ::: (x :: rs)
        }
    }
  }

  val xs = List.fill(32)(util.Random.nextInt())
  val sorted = quickSort(xs).run
  println(sorted)

  val (steps, sorted1) = quickSort(xs).foldRun(0)((i, f) => (i + 1, f()))
  println("sort took %d steps".format(steps))
}

当然,您需要一个非常大的结构或一个非常小的堆栈才能解决非尾递归分而治之算法的实际问题,因为您可以处理堆栈深度为 N 的 2^N 个元素。

http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html

UPDATE

scalaz.Trampoline是(更)更通用的结构的一个特例,Free。它定义为type Trampoline[+A] = Free[Function0, A]。其实可以这样写quickSort更一般地,因此它由中使用的类型构造函数参数化Free。此示例展示了如何完成此操作,以及如何使用相同的代码使用堆栈、堆或并发进行绑定。

https://github.com/scalaz/scalaz/blob/scalaz-7/example/src/main/scala/scalaz/example/TrampolineUsage.scala https://github.com/scalaz/scalaz/blob/scalaz-seven/example/src/main/scala/scalaz/example/TrampolineUsage.scala

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Scala中实现尾递归快速排序 的相关文章

  • Spark Streaming 中是否需要检查点

    我注意到 Spark 流示例也有检查点代码 我的问题是检查点有多重要 如果是为了容错 那么在此类流应用程序中发生故障的频率是多少 这一切都取决于您的用例 假设您正在运行一个流作业 它仅从 Kafka 读取数据并计算记录数 如果您的应用程序在
  • 如何以最小化每个分区总和的最大值的方式对整数数组进行分区?

    输入是正整数或空整数的数组 A 和另一个整数 K 我们应该将 A 划分为 K 个连续元素块 我所说的 划分 是指 A 的每个元素都属于某个块 并且 2 个不同的块不包含任何共同元素 我们将块的总和定义为该块的元素的总和 目标是在 K 个块中
  • 模式识别算法

    过去我必须开发一个充当规则评估器的程序 你有一个先行词和一些后续词 动作 所以如果先行词评估为真 则执行的动作 当时我用的是修改版RETE算法 http en wikipedia org wiki Rete algorithm RETE 有
  • 寻找 5 字节 PRNG 的种子

    这是一个古老的想法 但从那时起我就无法找到一些相当好的方法来解决它提出的问题 所以我 发明 了 见下文 一个非常紧凑的 在我看来 性能相当好的 PRNG 但我无法找出算法来为其在大位深度上构建合适的种子值 我当前的解决方案只是暴力破解 它的
  • 如何设置 jacoco4sbt 来处理 Play 中主模块和子模块中的类?

    我有一些问题要解决雅可可4sbt https github com sbt jacoco4sbt正在使用我的 Play 2 3 4 项目 我的项目由 3 个子模块组成 common api and frontend并且没有代码app根文件夹
  • Scala 将递归有界类型参数(F 界)转换为类型成员

    我将如何转换 trait Foo A lt Foo A 给类型成员 也就是说 我想要以下内容 trait Foo type A lt Foo type A 但我遇到了困难 因为名称 A 已在类型细化中使用 这个问题是类似的 并衍生自 通过类
  • 理解 scala 的 _ 与 Any/Nothing

    如果一个类具有协变类型参数 例如Iterable A http www scala lang org archives downloads distrib files nightly docs 2 10 1 library index ht
  • 错误:无法在 scala 中找到或加载主类

    安装 eclipse scala 插件和 eclipse maven scala 插件后 我是 scala 新手 所以我尝试确保在测试 scala hello world 项目后环境正常工作 它按预期工作 但我在尝试执行我从公司存储库中签出
  • 二进制堆中的删除

    我只是想学习二进制堆 并对在二进制堆中执行删除操作有疑问 我读到我们可以从二进制堆中删除一个元素 并且需要重新堆化它 但在下面的链接中却显示不可用 http en wikibooks org wiki Data Structures Tra
  • 地形/山地算法未按预期工作

    我想使用一个非常基本的原理创建一个上面有山的地形 如以下高度图所示 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0
  • 线性问题和非线性问题之间的区别?点积和核技巧的本质

    核技巧将非线性问题映射为线性问题 我的问题是 1 线性问题和非线性问题的主要区别是什么 这两类问题的差异背后的直觉是什么 核技巧如何帮助在非线性问题上使用线性分类器 2 为什么点积在这两种情况下如此重要 Thanks 当人们说到分类问题的线
  • 二分查找问题? [复制]

    这个问题在这里已经有答案了 可能的重复 实施二分查找有哪些陷阱 https stackoverflow com questions 504335 what are the pitfalls in implementing binary se
  • 承诺的反面是什么?

    承诺代表将来可能可用 或无法实现 的值 我正在寻找的是一种数据类型 它表示将来可能变得不可用的可用值 可能是由于错误 Promise a b TransitionFromTo
  • Scala 2.8 中 <:<、<%< 和 =:= 的含义是什么?它们的文档在哪里?

    我可以在 API 文档中看到Predef https scala lang org files archive api 2 8 2 scala Predef 24 html它们是通用函数类型 From gt To 的子类 但仅此而已 嗯什么
  • Scala 中用于阻止调用的 Future

    The Akka文档说 you may be tempted to just wrap the blocking call inside a Future and work with that instead but this strate
  • SBT插件——编译前执行自定义任务

    我刚刚编写了我的第一个 SBT 自动插件 它有一个生成设置文件的自定义任务 如果该文件尚不存在 当显式调用任务时 一切都会按预期工作 但我希望在使用插件编译项目之前自动调用它 无需项目修改其 build sbt 文件 有没有办法实现这一点
  • Scala 隐式转换范围问题

    采取这个代码 class Register var value Int 0 def getZeroFlag Boolean value 0x80 0 object Register implicit def reg2int r Regist
  • Java中获取集合的幂集

    的幂集为 1 2 3 is 2 3 2 3 1 2 1 3 1 2 3 1 假设我有一个Set在爪哇中 Set
  • 在 Scala 中创建任意类作为 monad 实例

    为了使任何东西都可以在 monad 上下文中操作 如果使用 Haskell 我只需在任何地方为给定类型添加类 Monad 的实现 所以我根本不接触数据类型定义的来源 像 人造的东西 data Z a MyZLeft a MyZRight a
  • 期望最大化算法的数值示例[重复]

    这个问题在这里已经有答案了 由于我不确定给出的公式 有人可以提供 EM 算法的简单数字示例吗 一个非常简单的具有 4 或 5 个笛卡尔坐标的坐标就可以了 那这个呢 http en wikibooks org wiki Data Mining

随机推荐

  • 如何顺序运行 golang 测试?

    当我跑步时go test 我的输出 FAIL TestGETSearchSuccess 0 00s Location drivers api test go 283 Error Not equal 200 expected 204 actu
  • Rust 中为什么有 mod 关键字?

    看完之后this https doc rust lang org book crates and modules html 我想知道为什么有一个mod关键字和mod rs 我假设目录层次结构也可以描述模块 必须显式声明模块有几个原因 模块可
  • XAML - 将单元格的行和列索引绑定到自动化 ID

    我正在为 WPF 数据网格中的各个单元格提供自动化 ID 但遇到了一些障碍 我决定尝试根据单元格在网格中的位置 行索引和列索引 来命名单元格 使用 UI 检查器并突出显示有问题的 DataGridCell 之一会显示以下属性 GridIte
  • 如何获取当前/活动 TFS 用户的列表?

    我可以使用 TFSCONFIG IDENTITIES 查看 TFS 中的所有用户 但是 这会调出已有多年历史且不再与 AD 帐户绑定的帐户 我想将搜索限制为仅拥有 AD 帐户的用户 这可能吗 我确实在下面找到了博客 但在尝试之前 我想看看是
  • WaitForSingleObject 是否充当内存屏障?

    昨天一个关于双重检查锁定的问题引发了一系列的想法 让我对一个简单的情况感到不确定 在下面的代码中 是否可以点击printf 不再同步 在这个简单的示例中 这些值可能位于同一缓存行上 因此我认为这种可能性较小 假设一开始可能性 gt 0 如果
  • Liquibase 从 JPA 实体生成变更日志

    我有一个 Spring boot spring data jpa 项目 带有一个父模块和三个子模块 我的模块之一负责我的 JPA 实体 我需要使用该实体的 liquibase 生成一个 xml 变更日志 在我的 liquibase prop
  • 需要 python 接口将机器移动到另一个文件夹

    我正在尝试寻找代码支持python为了在数据中心的文件夹之间移动机器但没有成功 我看到pysphere您可以在克隆阶段定义文件夹 而不是在机器克隆之后定义文件夹 This https jackiechen org 2011 11 01 mo
  • Android Activity 和 Service 关系 - 暂停后、停止后

    假设创建了 Activity A 然后 A 启动了一个 Service S 并将其自身绑定到 S S 通知 A 更新 这将导致 A 的状态发生变化 Android 暂停或停止 A 后 A 和 S 会发生什么 例如 暂停 A 是否会自动解除它
  • 在android中以编程方式创建布局 - 问题

    我正在使用以下代码动态创建 FrameLayout mylayout java FrameLayout layout new FrameLayout this FrameLayout LayoutParams layoutparams ne
  • 添加UITabBarController并且没有NavigationController

    由于我是 Xamarin IOS 的新手 我想问一个问题 我已经关注了这个例子 https developer xamarin com guides ios user interface controls creating tabbed a
  • 在 GTK+ (gtkD) 中处理按键

    我正在玩gtkD http www dsource org projects gtkd GTK 的 D 绑定 我有一个window对象 实例gtk MainWindow 我想处理它的按键 How 如何处理特殊键 例如箭头键 pgup pgd
  • 如何使用 Twitter Api 在单个请求中获取 20 多个列表成员?

    我想让超过 20 个用户在单个请求中使用 twitter api 有什么参数可以指定吗 我正在使用这个APIhttp api twitter com 1 Barelyme Politics members xml cursor 1 http
  • 具有自定义尺寸的线性渐变

    我有这样的设计 它已经用 html css 创建 但我需要删除 1 和 5 的额外线条 这是通过添加绝对位置元素来创建灰线来实现的 但容器点的大小是响应式的 我的想法是为每个容器创建一个背景线性渐变 如下所示 for all backgro
  • Spotify 中的 Facebook 个人资料图片

    我想在我的 Spotify 应用程序中显示 Facebook 个人资料图片 但我应该在清单文件中允许哪些 URL 我知道我可以通过 http graph facebook com user id picture 检索图像 但这只是到实际图像
  • PHP DOM 获取节点值 html? (不剥离标签)

    我正在尝试使用nodeValue获取文件中div标签的innerhtml 但是此代码仅输出纯文本 并且似乎从div内部删除了所有html标签 我如何更改此代码以输出 div 的 HTML 内容而不是纯文本 并且还输出包装其子元素的主 div
  • CodeIgniter Active Record - 组 OR 语句

    这是我的问题 MySQL 或 条件 https stackoverflow com questions 8604380 mysql or condition 解决方案是将 OR 语句分组 但我正在使用 CodeIgniters Active
  • 上传统一块的正确顺序是什么?

    在示例页面中https www lighthouse3d com tutorials glsl tutorial uniform b locks https www lighthouse3d com tutorials glsl tutor
  • PHP:从 array_values() 内的值中去除标签

    我想在用选项卡爆炸之前将标签从 array values 内的值中剥离出来 我尝试使用下面的这一行 但出现错误 output implode t strip tags array keys item 理想情况下 我想从值中去掉换行符 双空格
  • 无法解析配置“:app:debugRuntimeClasspath”的所有文件。问题

    我的 android studio 遇到了下一个问题 导致 org gradle api internal artifacts ivyservice DefaultLenientConfiguration ArtifactResolveEx
  • 如何在Scala中实现尾递归快速排序

    我写了一个递归版本 def quickSort T xs List T p T T gt Boolean List T xs match case Nil gt Nil case gt val x xs head val left righ