循环不变式的理解应用
数学归纳法
-
第一数学归纳法:
验证 n = 1 n=1 n=1命题成立,假设 n = k n=k n=k命题成立,证明 n = k + 1 n=k+1 n=k+1命题成立那么推得对任意正整数情况成立;
-
第二数学归纳法:
验证 n = 1 , n = 2 n=1,n=2 n=1,n=2命题成立,假设 n < k n<k n<k命题成立,证明 n = k n=k n=k命题成立那么推得对任意正整数情况成立;
总体来说两类方法均采用递归演绎推理命题的方式将结论延伸到整个正整数集合中。
循环不变式
很多算法的正确性采用循环不变式的方法论证或者说帮助理解过程,其内容如下:
- 初始化:循环第一次迭代之前为真
- 保持:循环的某次迭代之前为真,那么下次迭代之前仍为真
- 终止:循环终止时提供一个有助于证明算法正确性的性质
相比之下终止条件将循环不变式和数学归纳法区分开来,换句话说循环不变式中的保持
解释了数学归纳法中的递归推理,但同时结合算法是解决问题的工具的特性,终止条件尤为重要。
其中循环并不是朴素意义的循环结构,而是解决问题的子结构,排序算法的每次交换前后的状态集合、二叉平衡树的任何动态操作前后的状态集合、图算法基于任意一个点开始搜索的循环集合等等算法问题构成的子结构集合称之为循环结构。
但事实上循环不变式子的主题思想还是基于数学归纳法的,用典型的例子回顾算法并实际分析:
插入排序:
简单理解为:集合 A [ 1.. n ] A[1..n] A[1..n]被分为 A [ 1.. j − 1 ] A[1..j-1] A[1..j−1]和 A [ j . . n ] A[j..n] A[j..n]两部分,前者是已经排好序的数据,后者表示需要将 A [ j ] A[j] A[j]插入前者合理的位置中,保持上述循环直到后者集合为空。所以插入排序维护的循环不变式性质为: A [ 1... j − 1 ] A[1...j-1] A[1...j−1]集合在整个算法过程都是排好顺序的。
- 初始化:最初集合只有一个元素组成循环不变式成立;
- 保持:在当前 A [ 1.. j − 1 ] A[1..j-1] A[1..j−1]和 A [ j . . n ] A[j..n] A[j..n]状态下前者集合保持有序性的性质后,将 A [ j ] A[j] A[j]插入序列中合理位置并将原先该位置到 A [ j − 1 ] A[j-1] A[j−1]的所有元素向右移一位,这样集合变为了 A [ 1.. j ] A[1..j] A[1..j]和 A [ j + 1.. n ] A[j+1..n] A[j+1..n]两部分,且前者集合仍然保持有序性。
- 终止:当循环结束时后者的集合为空,前者集合满足起初定义的性质。
红黑树动态插入调整颜色:
红黑树的五条性质进行简要回顾:
- 每个节点颜色有红黑两种;
- 根节点为黑色;
- 每个叶子节点都为黑色;
- 若当前节点为红色,那么其两个子节点为黑色;
- 任意节点从自身到达叶子节点路径上经过的黑色节点数目是相等的。
上述排序中维护的是插入数据后整个集合的有序性被破坏后重建有序性的性质,该处循环不变式所要维护的是动态插入过程调整颜色过程中可能会被破坏的性质:
首先分析叶子节点都为NIL
不可能违反性质3,且插入中不含节点有多重颜色的情况所以不可能违反性质1,插入节点均为红色所以不可能能违反性质5(这里强调的是初始化状态红色并不影响路径的黑高问题)。
所以调整颜色过程中所要维护的性质有以下说明:
-
初始化:
- 待修复指针节点为红色;
- z . p z.p z.p是根节点时其根节点必须为黑色;
- 调用函数时性质135均保持不变
-
保持:
若上一过程均成立,那么根据所定义的六种方法(对称后显示三种不完全独立的处理情况),会将问题处理为下一个状态,这里描述左子树:
- 叔节点为红色,已知父节点为红色,使得两节点变黑跳转到祖父节点赋红色;
- 叔节点为黑色,已知父节点为红色,右旋之后使得情况转化使得节点颜色依旧为红色;
那么待修复节点颜色为红色,若当前父节点为根节点,那么在情况1中没有改变其颜色,情况2,3中改变颜色后遵循父节点为黑色,且性质13不变,性质5验证会发现依旧不变。
-
终止:
终止条件为父节点为黑色所以此处维护的性质2成立,待修复指针仍为红色可验证,性质135和
保持
阶段类似同理。唯一可能违反的时根节点为红色,所以最终结束时做颜色赋值。
上述过程没有提到违反红黑树性质24是分别因为:
- 性质2:确实没有做到维护所以后续伪代码16行中进行修复;
- 性质4:在左旋右旋过程中已经被维护,但初始化时刻此性质无效。
小结
在第一个例子中所维护的性质恰恰是被插入的数据所破坏的有序性,这里虽然在算法中定义了按照顺序插入,但依旧是和证明款搜的正确性一样,这里的性质被破坏是定义级别的破坏而不是真是破坏,经过循环不变式的检验后才可严谨的推得算法操作上的结果可以等同于定义级别上的性质不变;
依旧是和证明款搜的正确性一样,这里的性质被破坏是定义级别的破坏而不是真是破坏,经过循环不变式的检验后才可严谨的推得算法操作上的结果可以等同于定义级别上的性质不变;
相反第二个例子中没有把算法在过程中所可能破坏的性质4作为维护性质,主要原因为初始化状态下性质4是有可能不成立的,但是在循环终止时除性质2外都是成立的,所以得证插入颜色调整方法前后红黑树性质不变。