【问题标题】:Why my merge sort implementation in Scheme is so slow?为什么我在 Scheme 中的合并排序实现这么慢?
【发布时间】:2011-07-06 05:48:35
【问题描述】:

我知道Racket's stdlib,但我想自己实现一个排序功能作为练习。我决定使用归并排序算法,因为它自然地以递归术语定义。很快我就想出了可以工作的代码,但是它的工作速度太慢了。在我看来,运行时间是列表大小的指数,尽管理论上它应该是O(n·log n)

这是我的代码:

#lang 球拍

(define (pair x y) (list x y))

(定义(分割输入) (条件 [(empty?input) (pair null null)] [(empty?(rest input)) (pair input null)] [别的 (让 [(tail (cddr 输入))] (pair (cons (first input)) (first (split tail))) (cons (第二个输入) (second (split tail)))))]))

(定义(合并输入1输入2) (如果(或映射为空?(列表输入 1 输入 2)) (追加输入1输入2) (如果(

(定义(排序输入) (条件 [(空?输入)空] [(空?(剩余输入))输入] [别的 (let [(halfs (split input))] (合并(排序(前半部分))(排序(后半部分))))]))

(定义(排序?输入) (条件 [(空?输入)#t] [(空?(剩余输入))#t] [别的 (和(

似乎我使用了一些“原子”操作,它不会像我想象的那样在恒定时间内运行,但是我不知道是哪个。 30 个随机项目的排序是瞬时的,40 个项目在几秒钟内处理,50 个项目需要半分钟。所以我想知道,障碍在哪里?

【问题讨论】:

  • PS:欢迎对风格、未满足的约定等发表任何评论。我是 Scheme 的新手,我将不胜感激。
  • 风格方面,你为什么要写一个函数pair来创建列表?您可能希望查看从函数返回多个值(values 函数和 let-values Racket 形式)。
  • 想过从排序 n/2 部分开始并继续向上合并吗?。
  • @Jeremiah,感谢您注意到这一点,我有点困惑 (cons list list) 并没有 print 很好,所以用两个元素列表替换了原生对。现在在this question 中有一些很好的方法可以返回多个结果; values 在其中。
  • @Zimbabao,本质上,这就是它的工作方式。这些方法之间确实发生了一些重新排序,但我认为这在性能方面并不重要。内存占用似乎也相等。

标签: performance sorting lisp scheme racket


【解决方案1】:

split 中,您调用(split tail) 两次,而不是使用let 运行一次并将结果存储到变量中。这可能会使split 花费指数级时间。

【讨论】:

  • 我知道这很容易。现在它可以在几秒钟内对 100000 个项目进行排序。谢谢。
猜你喜欢
  • 2021-12-04
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 2011-06-02
  • 2015-06-25
  • 2021-04-23
相关资源
最近更新 更多