循环不变式-以求最大值和插入排序为例

循环不变式(loop invariants)不只是一种计算机科学的思想,准确地说是一种数学思想。在数学上阐述了通过循环(迭代、递归)去计算一个累计的目标值的正确性,属于基础数学的范畴,而且在计算机上也应用广泛。利用循环不变式可以帮助我们理解算法的正确性。

1、循环不变式的三条性质

初始化:循环的第一次迭代之前,它为真。
保持:如果循环的每次迭代之前它为真,那么下次迭代之前它仍为真。
终止:在循环终止时,不变式为我们提供一个有用的性质,该性质有助于证明算法是正确的。

2、案例1-求数组中的最大值

max = array[n];			
while(n--) {
	if(array[n] > max) 
		max = array[n];
}

循环不变式可以表述为以下形式,当n = 0时循环结束。
m a x = m a x i m u m ( a r r a y [ n : n 0 ) ) , n 0 = n max = maximum(array[n : n_0)) , n_0 = n max=maximum(array[n:n0)),n0=n

  • 初始化:刚开始 n = n 0 n = n_0 n=n0,区间内只有一个元素,循环不变式成立。
  • 保持:当n递减后,由于区间 [ n , n 0 ) [n,n_0) [n,n0)包含索引为n的元素,这个元素有可能会大于max,在if语句执行后,不变式被重新建立。
  • 终止:当n=0时,循环结束。

3、案例2-插入排序(伪代码)

ps:数组下标从1开始。更详细的描述请参考《算法导论》插入排序。

INSERTION-SORT(A)
for j = 2 to A.length
	key = A[j]
	//Insert A[j] into the sorted sequence A[1..j-1]
	i = j - 1
	while i > 0 and A[i] > key
		A[i + 1] = A[i]
		i = i - 1
	A[i + 1] = key
  • 初始化:在第一次循环迭代之前(当j=2)时,子数组A[1…j-1]仅由单个元素A[1]组成,所以子数组是排序好的,这表明第一次循环之前循环不变式成立
  • 保持:for循环将所有大于key的元素向右移动一个位置,直到找到A[j]的适当位置然后插入。一次循环结束时A[1…j]的元素已经是有序的状态。这时,j = j + 1使得进入下一次迭代时循环不变式保持不变。
  • 终止:有前面的分析可知,每次循环结束时的状态是这样的:j指向下一个待排序的元素,A[1…j-1]为有序状态。当j = A.length + 1时循环结束,整个数组已排序,因此算法正确。

4、关于循环不变式的一些思考

正如开头说的,循环不变式在数学上阐述了通过循环(迭代、递归)去计算一个累计的目标值的正确性,重点就在“累计”这两个字上,以用迭代和递归两种方法求最大值来看,他们不断的扩张正确域,当正确域和问题域一样大时得出最终答案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值