我的CS作业需要一些帮助。我需要编写一个排序例程,在最坏的情况下使用7次比较对长度为5的数组进行排序(我已经证明,由于决策树的高度,需要7个。)
我考虑使用决策树“硬编码”,但这意味着算法非常复杂,并且我的导师暗示这不是它应该完成的方式。
我检查了快速排序,合并排序,堆排序,d-ary堆排序,插入排序,选择排序,都没有回答要求,这让我相信需要一个长度数组的特定算法5。
真的希望得到一些正确方向的提示。
答案 0 :(得分:19)
Donald Knuth的计算机编程艺术,第3卷有一个关于这个主题的部分。我没有这里的书,但我很确定Knuth提出了5个元素的算法。正如您所怀疑的那样,没有一种通用算法能够为许多大小提供最少量的比较,但是在这种算法中使用了许多常用技巧。
从模糊的回忆中,我重构了5个元素的算法,可以在7个比较中完成。首先,取两个单独的对,在其中进行比较,并比较每对中较小的一对。然后,将剩余的一个与其中较大的一个进行比较。现在根据剩余元素是小还是大来分为两种情况,但在所有情况下都可以在仍然可用的三种比较中完成。
我建议您绘制图片来帮助您。 Knuth的照片是这样的:
o---o / o---o
显示了前三次比较后的结果(据我记得,这种图片出现在许多最小比较分类中)。一条线连接我们知道的两个元素。拥有这样的图片可以帮助您确定要比较的元素,因为您希望进行比较以获得最大量的信息。
附录:由于实际代码有一个可接受的答案,我想完成这些图表没有任何害处,它们可能是答案的有用补充。因此,从上面的一个开始,将缺少的元素与左上角的元素进行比较。如果它更大,这将导致
/--o o / \--o o \--o
现在,比较右上角的两个大元素,最后得到
o---o---o / o---o
现在,通过首先将右下角元素与顶部的中间元素进行比较,然后将其与所属的一侧进行比较,我们使用剩余的两个比较正确地放置它。
如果初始比较导致剩余元素变小,则图表变为
o---o---o / o---o
现在,比较两个还没有比它们小的东西。一个选项是上面的最后一个图,它可以通过剩余的两个比较来解决。另一种情况是
o---o / o---o---o
再次,与其他人不一致的那个可以通过两次比较正确放置。
答案 1 :(得分:13)
是的,这是在Knuth第3卷第185页(第5.3.1节)中。这是首次在博士论文中记录,所以你的教授对你很难!没有真正简单优雅的方法;你必须将它作为一个部分有序的树来跟踪。
这是在lisp中。测试好了(Linux上的SBCL)
(defun small-sort (a)
"Sort a vector A of length 5"
(if (> (aref a 0) (aref a 1))
(rotatef (aref a 0) (aref a 1)))
(if (> (aref a 2) (aref a 3))
(rotatef (aref a 2) (aref a 3)))
(if (> (aref a 0) (aref a 2))
(progn
(rotatef (aref a 0) (aref a 2))
(rotatef (aref a 1) (aref a 3))))
(if (> (aref a 4) (aref a 2))
(if (> (aref a 4) (aref a 3))
(progn)
(rotatef (aref a 3) (aref a 4)))
(if (> (aref a 4) (aref a 0))
(rotatef (aref a 2) (aref a 4) (aref a 3))
(rotatef (aref a 0) (aref a 4) (aref a 3) (aref a 2))))
(if (> (aref a 1) (aref a 3))
(if (> (aref a 1) (aref a 4))
(rotatef (aref a 1) (aref a 2) (aref a 3) (aref a 4))
(rotatef (aref a 1) (aref a 2) (aref a 3)))
(if (> (aref a 1) (aref a 2))
(rotatef (aref a 1) (aref a 2))
(progn)))
a)
(defun check-sorted (a)
(do ((i 0 (1+ i)))
((>= i (1- (array-dimension a 0))))
;;(format t "~S ~S~%" (aref a i) (aref a (+ 1 i)))
(assert (<= (aref a i) (aref a (+ 1 i))))))
(defun rr ()
(dotimes (i 100000)
(let ((a (make-array 5 :initial-contents (list (random 1.0) (random 1.0) (random 1.0) (random 1.0) (random 1.0) ))))
;;(format t "A=~S~%" a)
(let ((res (small-sort a)))
(check-sorted res)
;;(format t "Res=~S~%" res)
))))
答案 2 :(得分:0)
看一下桶排序。
答案 3 :(得分:0)
7听起来也可能shell排序。
答案 4 :(得分:0)
我认为硬编码解决方案不需要那么复杂:
这将始终使用7次比较。
编辑:
我不认为这会起作用:第4步被打破,可能需要进行第8次比较。考虑:
Index | 1 | 2 | 3 | 4 | 5 |
Value | 2 | 3 | 4 | 5 | 1 |
第4步:
答案 5 :(得分:0)
存储桶排序可以实现为比较算法,如下所示:
拿一个元素。
将它与所有存储桶进行比较。
将其放入匹配的存储桶中。 &lt; - 需要比较。
如果找不到存储桶,请创建一个新存储桶。
因此,它是我刚刚描述的动态桶排序算法。
我过去已经在新闻组上发明过/描述了这个。