当前课程知识点:数据结构(上) > 第三章 列表 > (e)插入排序 > 03E-7 平均性能
我们刚刚看到,insertion sort
在最好的时候只需线性的时间
但是很可惜 在最坏的时候
需要n平方的时间
那么平均而言 需要多少时间呢?
我们来对此做一概率分析
当然 首先我们要给出一个概率假设
也就是 采用最普通的概率假设
所有的元素都是在某一个范围内
按照均匀且独立的规则来取值的
那么具体来说 在这样的假设下
每一个新元素的插入
需要接受多少次比较操作呢?
为此 我们需要采用一种技术
叫作后向分析 backward analysis
也就是说 我们要把时间拉回到
此前的某一个时刻
也就是某一个元素
比如说第r个元素
刚刚完成插入的那样一个时刻
也就是说 如果在此前的
内部迭代中
有序前缀的长度为r
那么现在前缀的长度就是r+1
我们由前面那个状态
转化至后面这个状态
是因为刚刚插入了此前的L[r]这个元素
那么在这个过程中
为了插入这个元素
我们花费了多少时间?
确切地说 进行了多少次
元素的比较呢?
我们说这是随机的 不知道
我们不妨来
设想一个类似的场景
比如某一天
当老师因为某些事情的耽误
来到教室的时候 发现上课铃已经响了
同学们都已经就座了
这个时候 如果我不关心自己
反过来我关心同学
我有可能会问这么样一个问题
同学们 你们谁
是最后一个进入到这个教室的呢?
如果同学们配合
能够告诉我 那固然最好
但有可能同学会给我开玩笑
他们会说 邓老师 你猜?
没错
在这个时候 我们也需要猜
因为最后进入到这个序列中的
那个元素L[r]是谁 是不确定的
而且它插在不同的位置上
所对应的成本也是不同的
当然 按照我们刚才的那个假设
如果我要猜的话
那么我可以说
现在在场的每一位同学
都应该有均等的概率
作为最后的那个同学 来到这个课堂
也就是说 至今为止已经插入的这r+1个元素
每一个元素都有可能作为
刚刚被插入的
这个最后的那个元素
而且正因为我们采用的是
均匀独立的分布
所以不仅它们各自都有可能
而且它们的概率都是均等的
对于r+1个人来说
当然也就是r+1分之一了
好
为了估算刚过去的
这样一步迭代所需要的成本
我们不妨就将每一个元素
作为最后一个元素
插入所对应的成本累计起来
并且用我们刚才所给出的这个概率
来做加权平均
那么不难看出
如果最后那个元素是这个元素的话
那么我们所需要的比较
只需要1次
如果是接下来的这个的话
只需要2次
如果是再往下的话 是3次
一直到最终这个位置
无非就是r次
所以大致来说 所有这些情况
所对应的计算成本
构成了一个算术级数
它们的平均值与当前
这个前缀的长度
也就是r 成线性关系
这样我们就得出了
在第r步迭代中
我们所需要的计算成本
现在 我们纵观整个的计算过程
把每一步所对应的
计算成本的期望值累加起来
自然也就得到了总体的期望值
大家注意 这里我们用到了
数学期望的线性率
如果你还不是很了解
可以查一查相关的资料
扼要地讲 就是
一组随机变量总和的期望
等于它们各自期望的总和
无论它们是互不相关的
还是相关的
这一结论都是成立的
所以由此我们可以看到
插入排序 在这样一个意义下的
平均复杂度
依然是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)深度优先搜索--作业
-第六章 图--本章测验