当前课程知识点:数据结构(上) > 第三章 列表 > (e)插入排序 > 03E-6 性能分析
那么以上insertion sort算法的性能如何呢?
我们来对此做一分析
首先来看一种最好的情况
这里我们已经把场景给设计好了
也就是说 如果比作是抓牌的过程的话
那么所有的牌都是按照完全
或者至少是几乎有序的次序抵达的
因此 你的理牌过程大概是这样的
最开始 来的是一张最小的牌
接下来的第二张牌呢
至少不会比它更小
第三张也是如此 第四张、第五张
以及后边若干张 也几乎都是这样
为什么说这是最好的情况呢?
因为每当有一张新牌到达
我们向前搜索的过程
只需做一次比较
即可确定应该将这张新的牌
插入于当前的最后位置
一次比较 零次交换
每张牌所需要的时间都是一个单位
累计而言 当然也就是线性了
看好了 线性
为什么需要大家看好呢?
因为我们要和此前所讲的
selection sort 做对比
大家应该还记得
那个算法的复杂度是n平方
而且是θ(n平方) 它的意思是说
没有最好情况 当然也没有最坏情况
在所有的情况下
它都需要n的平方这么多时间
这又是插入排序和选择排序的一大区别
当然相应地 也有最坏的情况
不难设想 这种场景就是
所有的牌完全按照颠倒的次序
也就是逆序来给出
所以即便在任何时候
你已经将手里的牌从小到大
排列成了一个有序的部分
却保不齐下面来的一张牌
会比此前的所有的牌都更小
以致于你必须逐个经过比对之后
才能够确定应该将它插入在最前方的位置
这样为了插入每一张牌
我们所需要经过的搜索
都需要走过漫漫的一条长路
它的长度就是当前你迭代的次数所界定的
每个元素都需要这样
整体构成一个算术级数
我们讲过 它的总和应该又回到了n的平方
这里有一个插曲
有的同学可能会敏锐地注意到
噢 你这里为什么要这样
亦步亦趋地进行查找呢?
你没有注意到吗?
这个地方已经是有序了的
在一个有序的序列中进行查找
你为什么不采用
我们此前所说的二分查找呢?
那么我的回答是
噢 那对不起 如果是那样的话
那我们就不能用列表了
你或许会说
那我们就用Vector呗
啊 事实上也只有Vector
能够支持这种call-by-rank的方式了
嗯 没错
但是我说 这依然存在问题
你如果想深入思考
不妨在这暂停一下
一、二、三
是的 我想聪明的你
已经发现了问题所在
的确 如果我们改用向量
来组织整个序列
包括这个有序的序列
固然可以将这样一个查找的过程加快
具体来说 只需logn的时间
或者说logn次比较
就可以确定一个位置
即便在最坏的情况下
我们可以将原来的线性次比较
减少为logn次
但是很遗憾
在此后
我们为了将新的这个元素
真正地从物理上插入于这样的一个序列
注意 这个时候已经是一个向量
我们不得不将它所有的后继
也就是原来整个这个序列
整体地向后移动一个单位
这意味着什么呢?
这意味着我们的交换操作次数
将变成O(n)
也就是说 原来只需一次交换
现在却需要进行O(n)次
采用列表结构
此前两项累计是O(n)
以致整体是O(n平方)
而现在呢 采用新方案
虽然比较的次数能够降至logn
但是总体所花的时间却依然是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)深度优先搜索--作业
-第六章 图--本章测验