如何在Racket-Plait中基于操作符实现列表排序合并(升/降序)?
在Racket-Plait中实现基于操作符的列表合并排序
你不需要通过判断操作符是<还是>来分支处理,直接利用传入的操作符作为判断条件,递归合并两个已排序的列表即可。以下是修正后的完整代码:
(define (merge [op : (Number Number -> Boolean)] [int-list1 : (Listof Number)] [int-list2 : (Listof Number)]) : (Listof Number) (cond ; 其中一个列表为空时,直接返回另一个列表 [(empty? int-list1) int-list2] [(empty? int-list2) int-list1] [else (let ([first1 (first int-list1)] [rest1 (rest int-list1)] [first2 (first int-list2)] [rest2 (rest int-list2)]) ; 根据操作符判断哪个元素应该放在结果的头部 (if (op first1 first2) (cons first1 (merge op rest1 int-list2)) (cons first2 (merge op int-list1 rest2))))])) ; 测试升序合并(用<操作符:当first1小于first2时,优先放first1) (test (merge < '(1 4 6) '(2 5 8)) '(1 2 4 5 6 8)) ; 测试降序合并(用>操作符:当first1大于first2时,优先放first1) (test (merge > '(6 4 1) '(8 5 2)) '(8 6 5 4 2 1))
逻辑说明
- 递归终止条件:当任意一个输入列表为空时,直接返回另一个列表,因为空列表和任何列表合并的结果就是该列表本身。
- 递归处理:取出两个列表的第一个元素,用传入的
op判断是否应该将第一个列表的元素放在结果的最前面:- 如果
(op first1 first2)为真,就把first1加入结果,然后递归合并int-list1的剩余部分和完整的int-list2。 - 否则,把
first2加入结果,递归合并完整的int-list1和int-list2的剩余部分。
- 如果
对应你的需求
你提到>对应升序、<对应降序,这里需要注意:如果输入的两个列表本身是升序排列的,要得到升序合并结果应该用<操作符(如你的测试用例);如果输入列表是降序排列的,用>操作符会得到降序合并结果。如果需要强行用>得到升序结果,只需调整判断条件为(not (op first1 first2)),但这样不符合操作符的直观语义,更推荐保持操作符和排序逻辑的一致性。
内容的提问来源于stack exchange,提问作者Infernalissss
相关产品推荐
相关产品推荐

