- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是我在 Scala 中实现的合并排序:
object FuncSort {
def merge(l: Stream[Int], r: Stream[Int]) : Stream[Int] = {
(l, r) match {
case (h #:: t, Empty) => l
case (Empty, h #:: t) => r
case (x #:: xs, y #:: ys) => if(x < y ) x #:: merge(xs, r) else y #:: merge(l, ys)
}
}
def sort(xs: Stream[Int]) : Stream[Int] = {
if(xs.length == 1) xs
else {
val m = xs.length / 2
val (l, r) = xs.splitAt(m)
merge(sort(l), sort(r))
}
}
}
它工作正常,似乎渐近地它也很好,但它比这里的 Java 实现慢得多(大约 10 倍)http://algs4.cs.princeton.edu/22mergesort/Merge.java.html并使用大量内存。是否有更快的功能性合并排序实现?显然,可以逐行移植 Java 版本,但这不是我想要的。
UPD:我已将 Stream
更改为 List
并将 #::
更改为 ::
和排序例程变得更快,只比 Java 版本慢三到四倍。但是我不明白为什么它不会因堆栈溢出而崩溃? merge
不是尾递归的,所有参数都经过严格评估...这怎么可能?
最佳答案
您提出了多个问题。我尽量按逻辑顺序回答:
你并没有真正问这个问题,但它导致了一些有趣的观察。
在 Stream 版本中,您在 merge
函数内使用 #::merge(...)
。通常这是一个递归调用,可能会导致足够大的输入数据堆栈溢出。但在这种情况下不是。运算符 #::(a,b)
在 class ConsWrapper[A]
中实现(存在隐式转换)并且是 cons.apply 的同义词[A](hd: A, tl: ⇒ Stream[A]): Cons[A]
。如您所见,第二个参数是按名称调用的,这意味着它是延迟计算的。
这意味着 merge
返回一个新创建的类型为 cons
的对象,它最终会再次调用 merge。换句话说:递归不是发生在栈上,而是发生在堆上。通常你有足够的堆。
使用堆进行递归是处理非常深的递归的好方法。但它比使用堆栈要慢得多。所以你用速度换取了递归深度。这就是使用 Stream
如此缓慢的主要原因。
第二个原因是,为了获得Stream
的长度,Scala必须具体化整个Stream
。但是在对 Stream
进行排序期间,它无论如何都必须具体化每个元素,所以这不会造成太大伤害。
当你把 Stream 换成 List 的时候,你确实是在用栈来递归。现在可能会发生堆栈溢出。但是对于排序,您通常具有 log(size)
的递归深度,通常是以 2
为底的对数。因此,要对 40 亿个输入项目进行排序,您需要大约 32 个堆栈框架。默认堆栈大小至少为 320k(在 Windows 上,其他系统具有更大的默认值),这为大量递归留出了空间,因此为大量输入数据进行了排序。
这取决于:-)
你应该使用栈,而不是堆来进行递归。你应该根据输入数据决定你的策略:
不要使用交换并使用你的缓存。如果可以,请使用可变数据结构并就地排序。我认为功能排序和快速排序不能很好地协同工作。要真正快速地进行排序,您将必须使用有状态操作(例如,可变数组上的就地合并排序)。
我通常在我的所有程序中尝试这样做:尽可能使用纯函数式风格,但在可行的情况下对小部分使用有状态操作(例如,因为它具有更好的性能,或者代码只需要处理很多状态并且变得很多当我使用 var
而不是 val
时,可读性更好。
关于algorithm - 快速函数归并排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18944524/
本文实例汇总了Java各种排序算法。分享给大家供大家参考,具体如下: 1. 冒泡排序: ?
1.冒泡排序 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。 算法步
前言 平时用惯了高级语言高级工具高级算法,难免对一些基础算法感到生疏。但最基础的排序算法中实则蕴含着相当丰富的优化思维,熟练运用可起到举一反三之功效。 选择排序 选择排序几乎是
我是一名优秀的程序员,十分优秀!