Dafny插入排序代码报错求助:while循环及序列赋值问题
解决Dafny插入排序中的两个常见错误
刚上手Dafny的时候,碰到这类语法细节坑太正常了,我来帮你把这两个问题捋清楚:
1. 修复while循环的“invalid logical expression”错误
你这里踩了个Dafny语法的小坑:|input|是用来计算集合/多重集合的元素数量的,不能用来获取序列或数组的长度。对于序列(Sequence)或者数组(Array),正确的长度获取方式是用.Length属性。
把你的循环条件从:
while(i < |input|)
改成:
while(i < input.Length)
不管input是序列还是数组,这个写法都适用。
2. 修复序列赋值的“expected method call, found expression”错误
这个问题的核心是Dafny的序列是不可变类型——你写的input[j := b]其实是返回一个新的序列(原序列完全没变化),而Dafny不允许把这种表达式单独当作语句执行(只有方法调用能单独当语句)。
根据你的需求,有两种解决方式:
方式一:改用数组实现(推荐插入排序场景)
插入排序通常需要原地修改元素,所以用数组(可变类型)更合适。把input声明为array<int>,然后用数组的赋值语法替换你的交换代码:
input[j] := b; input[j-1] := a;
数组支持直接修改指定索引的元素,这样的语句是完全合法的。
方式二:继续用序列实现(不可变场景)
如果一定要用序列,你需要把更新后的新序列重新赋值给input,还要注意更新顺序(先改索引小的会被后改的覆盖,所以先处理大索引):
input := input[j-1 := a][j := b];
或者拆成两步写更清晰:
var updatedSeq := input[j-1 := a]; input := updatedSeq[j := b];
给你一个修正后的插入排序示例(数组版本)
method InsertionSort(input: array<int>) modifies input ensures forall k, m :: 0 <= k < m < input.Length ==> input[k] <= input[m] { var i := 1; while(i < input.Length) invariant 0 <= i <= input.Length invariant forall k, m :: 0 <= k < m < i ==> input[k] <= input[m] { var key := input[i]; var j := i; while(j > 0 && input[j-1] > key) invariant 0 <= j <= i invariant forall k, m :: 0 <= k < m < j ==> input[k] <= input[m] invariant forall k :: j <= k < i ==> input[k] >= key { input[j] := input[j-1]; j := j - 1; } input[j] := key; i := i + 1; } }
内容的提问来源于stack exchange,提问作者Amir-Mousavi
相关产品推荐
相关产品推荐

