当前课程知识点:数据结构(上) > 第二章 向量(上) > (b)可扩充向量 > 02B-2 动态空间管理
当然 我们最开始
给出的这个方案
不见得是最好的
但是 不妨把它作为
我们改进的起点
就策略而言
我们实际上需要把刚才
所采用的静态空间管理策略
改变为所谓的动态管理策略
这种策略 某种意义上讲
是在模仿蝉这种动物的做法
也就是说 像蝉那样
每经过一段时间
因为身体的生长
使得自己的外壳
已经无法容纳自身
就会蜕掉原来的外壳
并且代之以一个新的外壳
是的 我们如果把
这种策略翻译过来
就是 如果在某个时刻
某一个向量即将发生上溢
那么我们就像蝉那样
适当地扩大内部数组的容量
使之足以容纳新的元素
按照这样一种策略
向量的生命期
可以大致由这样一组图来表示
最开始的时候
向量所存放的有效元素
还不是很多
还不致于出现上溢的情况
这时候可以从容应对
但是剩余的空间
有可能会逐步地被占用
直到某一个关键时刻
也就是 在这个时刻
内部数组
有可能已经饱和
这个时候 它存在一个风险
也就是说 再插入一个元素的话
就会导致上溢
那么在这个时候
我们可以模仿蝉
蜕掉原来的外壳
为此 我们可以动态的
申请另一个外壳
也就是 另一段存放空间
当然它的大小
应该比原来的有所增长
接下来 我们要把
原先已经存放好的
那些有效元素
逐一地按次序地复制过来
从而使得它们 对外界而言
依然保持原貌
而在这个时候
新多出来的这些空间
就足够用以存放
新需要插入的元素
而原来所占用的空间
将在此之后被释放
并且归还给系统
上述这样一个
完整的调整过程
可以描述并且实现
为这样一段c++的代码
首先我们要判断一下
现在是否的确处于
即将发生上溢的临界状态
那么它的标志就是_size
是否还继续严格地小于
_capacity
如果是 还不存在上溢的风险
可以直接返回
所以这里隐含着有一个else
也就是说 接下来
我们的_size虽然不见得
一定大于_capacity
但是至少会出现
等于_capacity的情况
在这个时候 就要像
刚才所说的那样
模仿蝉去蜕掉原来的壳
那么不同的在于
我们首先的要将原来的那个数据域
做一个备份
接下来呢 以原先的容量
大家注意 这里
是左移一位 相当于加倍
以原先的容量
加倍的 一个新的容量
来申请一段动态空间
并且将这段空间交由原来的
也就是我们通用的那个
element来指示
接下来要做的事情是复制
对 从原先的
那个数据域中 逐一地取出各项
并且将其转移至新的
这个数据域中对应的位置
在整体赋值完之后
原先的这个空间
已经没有任何存在的意义了
所以通过delete操作
将它释放
可以看到这段代码
确实忠实的实现了
上一页扩容算法(的)构思
其实 对于尚未封装的数组
同样可以采用上述的
这样的一个策略
那么对于向量而言
这里调整又有什么优势呢?
我们说这种优势
体现在向量整体的封装性上
因为我们都知道
在对于一般的数组而言
如果它经过了动态的
重新分配地址
那么原先指向它内部的
某些元素的一些指针
就有可能会出现无效
也就是说 虽然它能指向一个地址
但其中并没有存放
我们所需要的数值
那我们看到 对于向量而言
经过了这样的封装以后 就安全了
我们不会出现这种情况
因为无论是此前此后
我们在访问
某一个具体的元素的时候
在内部都是通过
element这个统一的指示器
来标识空间的起点
所以从这一点 我们也可以看出
进行封装以后的一个好处
当然 最大的困惑
也许在这里
这里采用了
一个容量加倍的策略
为什么一定要用
这样的一个策略呢?
用其它的策略是不是也可行呢?
能够适当地增加
内部数组的容量不就足够了吗?
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验