循环不变式的一个例子(向量唯一化)
输入:
向量A,A中包含n个元素,A={a0,a1,…an-1}, 可能按任意顺序排列,n可能为0,即元素为空
输出:
唯一化后的向量A, A中包含m个元素,m满足m<=n, A={a0,a1,…am-1}, A中的任意元素满足 ai != aj (i!=j 且 i,j 属于 0~m-1)
步骤
uniq(A){
for(i=0, k=0; i<A.length; ){
hasRe=false;
for( j=i-1; j>=0; j--)
if(A[j]==A[i) hasRe=true;
if(hasRe)
A.remove(i);
else
i++;
利用循环不变式证明算法正确性:
循环不变式:需满足,A[0…i-1]中无重复元素。且A[0…i-1]中包含原序列A[0…i-1]中的所有元素。
- 初始化:i为0,i-1为-1,A[0…i-1]为空,其中自然无重复元素,空集也自然包含空集。这表明第一次迭代之前循环不变式成立。
- 保持:若每次迭代前,A[0…i-1]无重复元素,且包含原序列A[0…i-1]中的所有元素。那么每次迭代时:若A[0…i-1]中存在A[i], 则舍去A[i],此时,A[0…i-1]中仍无重复元素,且仍包含原序列A[0…i-1]中的所有元素;若A[0…i-1]中不存在A[i], 则令i自增1,此时,A[0…i-1]仍无重复元素,且仍包含原序列A[0…i-1]中的所有元素。这表明若循环迭代式某次循环之前为真,则下次迭代前它仍为真。
- 终止:for循环的终止条件是 i=A.length, 此时,A[0…i-1]即A[0…length-1]已包含了A中的所有元素,且其中无重复元素,我们推断出序列A已经完成唯一化。因此算法正确。