我正在尝试学习C中的循环不变量。我有一个代码,我有循环不变量,但我不完全理解为什么。这是代码:
/* 0 ≤ m < n < ASIZE AND A[m] ≥ A[m+1] ≥ ... ≥ A[n] */
void ReverseArray(int A[], int m, int n)
{
int temp;
while (m < n)
{
temp = A[m]; A[m] = A[n]; A[n] = temp;
m++;
n--;
/* loop invariant: 0 < m < n < ASIZE OR m == n OR m == n+1 */
}
}
/* for the initial values of m and n, A[m] ≤ A[m+1] ≤ ... ≤ A[n] */
循环不变量为:0&lt; m&lt; n&lt; ASIZE OR m == n OR m == n + 1
我想我明白了0&lt; m&lt; n&lt; A大小。这将是因为while循环并且它表示m不能为0但它必须小于n。并且n必须小于数组大小。
但我不明白为什么m == n和m == n + 1。
有什么想法吗?
答案 0 :(得分:1)
但我不明白为什么m == n和m == n + 1。
在找到循环不变量时,此表达式(循环不变)保证为真:
0 < m < n < ASIZE OR m == n OR m == n+1
但是,这个(“你理解的部分”)不总是如此:
0 < m < n < ASIZE
为什么呢?由于m
递增,n
会递减,因此m < n
可能不再为真。
这就是为什么你需要“放大”循环不变量以使它始终为真,包括这些情况,m == n
和m == n+1
,这可能在正常情况下出现执行循环。
所以,如果你说不变量就是“你理解的部分”,你就错了 - 你的循环不变会失败,这是(根据定义)一个禁忌。
答案 1 :(得分:1)
记下2个程序的例子 - 对于偶数和奇数长度的数组。例如,在itera之前创建一个包含迭代次数,数组和值m
和n
的表。我相信最简单的方法就是自己动手并逐行执行代码(表本身对于理解整个问题可能没那么有用)。
PS。不变量似乎太弱而不能建立后置条件。
答案 2 :(得分:1)
如果在循环体之前,就是m + 1 == n
的情况,那么在循环结束时,m
将递增,n
将递减。那时,m == n + 1
。
例如,当m
的值为2时,n
的值为3.然后m++; n--;
后,m
的值为3,{{1} }具有值2.
如果在循环体之前,则是n
,然后是循环体m + 2 == n
之后的情况。例如,如果m == n
的值为2且m
的值为4,那么n
为3,m
为3。
对于在循环体之后结果为n
或m == n
的情况中的任何一种情况,循环控制将为假,因此该情况将导致循环停止。