当前课程知识点:数据结构(上) > 第一章 绪论(下) > (d)算法分析 > 01d-5: 正确性的证明
我们的第一个问题 关乎这个算法的有穷性
也就是说这个算法 是否必然会终止
答案首先基于这个算法所具有的这样一条不变性
可以断言 上述这个算法
在经过了K轮的外循环
也就是 K轮的扫描交换之后
全局最大的那K个元素 必然会各就各位
来看一下下面这个图
如果由上而下是构成整个这个序列
也是我们整个扫描交换的执行方向
那么 在第一趟扫描过程中
5和2 因为逆序会交换次序变成2和5
再接下来 5当遇到7以后 会停留下来
因为在这个位置是构成了一个顺序对
那么接下来的情况将是7
一旦接过这样一个控制权以后
它作为全局最大的元素
必然会在接下来的每次比较中
都大于它当时的右侧
也就是 后边的那个元素
从而 构成一个逆序紧邻对
所以 7会和接下来的邻居4
以及再接下来的新邻居6
以及再接下来的邻居3 以至1
统而言之 它的所有的后继依次交换
最终效果是7 经过若干次交换
转移至最后 而原来它的那些后继
等效于 往前平移一位
我们看到刚才这个断言
对于第一趟是对的
因为经过了K等于1 一轮的扫描交换
最大的一个元素 也就是7
确实是就位了
这不奇怪
因为7是整体的最大的元素
所以 在扫描交换的过程中
一旦它接过控制权
后面的故事都是一样的
它会胜出所有的元素 直到最终就位
那我们看看 在接下来的第二轮循环之后
又会怎么样呢?
其实故事是类似的
也就是说 在这里2和5是顺序的
所以不用交换
但是5和4经过一次交换以后 变成4和5
这都不是最关键的
我们看 最关键的是
一直这个故事发生到
当前最大的元素
也就是 全局第二大的那个元素6
接过控制权之后
它会跟刚才一样
胜出它的所有的有效的那些后继
在这个例子讲的3和1
直到它也就位
所以推而广之
后面接下来最大的元素5
也会在接下来的一轮扫描交换之后就位
同样4、3和2都会相继的就位
因此总结一下 这条不变性确实是成立的
另外呢 在这整个过程中
也蕴含了一个单调性
经过了K轮的扫描交换之后
问题的实质的等效规模
实际上就会减至n-k
在我们这个图里 已经用颜色加以了标识
所有的彩色的部分 都对应是
当前这个算法有效的问题范围
也就是说 我们还没有处理的范围
而灰色的部分都可以认为是
整个这个算法 当前的视线之外
对于算法后续的过程
以及整体的算法的效果
没有影响的部分
我们看到 如果最开始的规模是n的话
经过了一趟以后 确实缩减为n减1
再经过一趟以后 缩减为n减2
以致n减3、n减4 n减5 一直下去
所以由这两条 我们就应该可以得出结论
这个算法必然会结束
而且是正确的结束
而且在终止的时候呢
我们来考察一下这个不变性
也就是它的最后的那个边界情况
当k等于n的时候
那么 不变性就可以翻译成
经过了 n轮扫描交换之后
最大的n个元素
其实 也就是所有的n个元素
必然会各就各位
最后归纳一下 确实
这个算法经过至多n趟扫描之后
必然会终止
而且会给出正确的答案
通过挖掘 并且综合
算法所具有的不变性和单调性
进而证明正确性的方法
是算法分析中的一个基本而重要的技巧
我们希望大家能够通过这个实例融会贯通
在其它的场合能够举一反三
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验