STL学习笔记——序列式容器
2016-04-15 20:18
204 查看
vector 维护的是一个连续线性空间,这点和array类似,但vector更灵活,支持空间的扩展。如果当前分配的线性空间已满,又要加入新的元素,就要能扩展空间,就要选择好策略。STL的策略是重新找一块原容量2倍的存储块,然后将原来空间里的所有元素复制过来,再填入新元素。(因为连续存储,不能再原存储块后扩展)
至于为什么是2倍而不是其他的策略,这值得思考:
为什么不是每次需要扩充时:1.新容量=原容量+N(N为1,2,3,4.......),2.新容量=原容量*1.5,或者新容量=原容量*3;
假设添加m元素到空的vector中:
方案一:新容量=原容量+N 是常数扩充,需要(m-1)/N+1次扩充,每次复制k*N个元素(k=1,2,3,4......),时间复杂度为O(m^2) ;
方案二:新容量=原容量*N 是倍数扩充,需要logN(m-1)次扩充,每次复制k*N个元素(k=1,2,3,4......),时间复杂度为O(m*logm) 。
可见方案二在时间上比较节省,但空间上会比较浪费,最坏的情况下,可能会有接近一半(k=2的情况下)的空间被申请但没存任何数据。
STL设计者站在时间优先的角度,又不原造成过多的空间浪费,选择了两倍扩容的策略。而java采用1.5倍扩容。
list维护的是一个链表,更准确说是双向链表,更准确说是环状双向链表。list的last 迭代器指向的节点数据为空,但next指针指向first迭代器指向的节点。
所以用一个指针link_type node(指向那个空节点)就可以表示整个环状双向链表。
iterator end() {return node;}
iterator begin() {return (link_type)((*node).next);}
bool empty() {return node->next==node;}
至于为什么是2倍而不是其他的策略,这值得思考:
为什么不是每次需要扩充时:1.新容量=原容量+N(N为1,2,3,4.......),2.新容量=原容量*1.5,或者新容量=原容量*3;
假设添加m元素到空的vector中:
方案一:新容量=原容量+N 是常数扩充,需要(m-1)/N+1次扩充,每次复制k*N个元素(k=1,2,3,4......),时间复杂度为O(m^2) ;
方案二:新容量=原容量*N 是倍数扩充,需要logN(m-1)次扩充,每次复制k*N个元素(k=1,2,3,4......),时间复杂度为O(m*logm) 。
可见方案二在时间上比较节省,但空间上会比较浪费,最坏的情况下,可能会有接近一半(k=2的情况下)的空间被申请但没存任何数据。
STL设计者站在时间优先的角度,又不原造成过多的空间浪费,选择了两倍扩容的策略。而java采用1.5倍扩容。
list维护的是一个链表,更准确说是双向链表,更准确说是环状双向链表。list的last 迭代器指向的节点数据为空,但next指针指向first迭代器指向的节点。
所以用一个指针link_type node(指向那个空节点)就可以表示整个环状双向链表。
iterator end() {return node;}
iterator begin() {return (link_type)((*node).next);}
bool empty() {return node->next==node;}
相关文章推荐
- 在Windows上安装TimesTen
- 删除链表中重复的结点
- Java IO5:序列化与反序列化
- 栈的压入、弹出序列
- 中国学者利用纳米人工红细胞精准治疗癌症获突破
- 穷举法之完美综合式
- 泛型方法的定义与使用
- GitHub与StackOverFlow等等
- 面试题:什么叫二叉查找树
- 2016年4月微软在线笔试第二题-403 forbidden
- 泛型类的定义与使用
- 半平面交初级
- 环境——卸载redhat6.5的yum,安装centos6的yum,配置第三房yum源
- java第五次作业
- iOS小技巧 - 选择编译
- HDU 3367 Pseudoforest(最大生成树+并查集)
- Fragment嵌套ViewPager,viewpager切换的时候,手机出现白屏
- 泛型
- Android学习之Android 5.0分享动画实现微信点击全屏效果
- Python3.5.1 百度翻译代码