循环不变量是非常简单但功能强大的技术,可以证明您的算法或一组指令是否正确。它们在迭代中工作得非常好。
我们设置了一个不变的属性,这是您希望在整个执行过程中维护的迭代中的所需属性。例如,如果你从一个正确的状态开始并在整个算法过程中保持它,那么你就知道你有一个正确的算法
所以你需要证明你有一个想要的属性,3个步骤的不变性:
我。 初始化:你能证明你在循环迭代的第一步中具有算法的不变性吗?
二。 维护:您是否在维护不变性?如果到那时为止的迭代是真的,那么下一次迭代也是真的吗?
iii.终止:当您的循环最终终止时,不变量将用于表明您编写的算法是正确的。
让我们用这些知识来证明 BuildMaxHeap 是正确的,因为它用于 HeapSort 算法。
BuildMaxHeap(A)
heap-size[A] = length[A]
for i : length[A]/2 to 1
Max-Heapify(A, i)
来源。 CLRS
例如,我们怎么知道构建最大堆实际上是构建最大堆!如果我们的 BuildMaxHeap 算法正常工作,我们可以使用它来正确排序。
根据上述直觉,我们需要决定在整个算法中维护的所需属性。 MaxHeap 中所需的属性是什么?堆[i]>= 堆[i*2]。不管你怎么弄乱堆,如果它仍然有那个属性,那么它就是一个 MaxHeap。
因此,我们需要确保用于排序的 BuildMaxHeap 算法在整个算法中保持不变。
初始化:在第一次迭代之前。一切都是叶子,所以它已经是堆了。
维护:让我们假设到目前为止我们有一个可行的解决方案。节点 i 的子节点编号高于 i。 MaxHeapify 也保留了循环不变量。我们在每一步都保持不变性。
终止:当 i 下降到 0 时终止,并且通过循环不变量,每个节点都是最大堆的根。
因此您编写的算法是正确的。
Introduction to Algorithms (CLRS) 对这种技术有很好的处理。