无序向量Vector
2015-06-09 19:06
316 查看
向量vector
1、AbstractData Type(ADT)抽象数据类型:数据模型上定义的一种操作。Data structure数据结构:基于某种特定语言,实现ADT的一整套算法。向量是数组的抽象和泛化,有一组元素按线性顺序封装而成。
ADT操作接口:
2、vector模板类
(1)基于复制的构造
template<typename T>
voidVector<T>::copyFrom(T* const A,Rank lo,Rank hi)
{
_elem=new T[_capacity=2*(hi-lo)];//申请空间
_size=0;
while(lo<hi)
_elem[_size++]=A[lo++];
}
一般都以左闭右开,A[lo,hi),所以总共长度是hi-lo,hi不属于vector的,可以当做哨兵使用。
(2)扩容expand()
上溢overflow,下溢underflow.动态空间管理:在即将发生上溢时,适当地扩大内部数组的容量。
template<typename T>
voidVector<T>::expand()
{
if(_size<_capacity) return;
T *oldElem=_elem; //备份
_elem=new T[capacity<<=1]; //容量加倍
for(int i=0;i<_size;i++)
_elem[i]=oldElem[i];
delete [] oldElem; //释放空间
}
为什么需要容量加倍呢?下图是递增扩容和加倍扩容。
平均复杂度average/expected complexity,是独立的过程。
分摊分析amortized complexity,连续的操作,更加贴近实际。
3、无序向量
template <typename T> Vector{...};定义一系列vector:
例如Vector<int> myVector… Vector<BinTree > myVector…
(1)元素访问:重载操下标操作符[]
template<typename T>
T&Vector<T>::operator[](Rank r)const
{
return _elem[r];
}
(2)插入元素insert( )
template<typename T> //把e作为秩r的元素插入
RankVector<T>::insert(Rank r,T const &e)
{
expand(); //扩容
for(int i=_size;i>r;i--)
_elem[i]=_elem[i-1]; //将元素往后移动,直到移动到r
_elem[r]=e;_size++;
return r;
}
(3) 区间删除remove(),复杂度O(n-hi)
(4)单元素删除remove(),复杂度为O(n-r)
如果区间删除调用单元素删除的话,理论上是可以的,但是复杂度的话每次调用都需要O(n-r),这样级数相加,最后区间删除的复杂度有可能是O(n2)。
(5)查找操作find无需判断一般只支持判等操作,有序向量支持比较操作
template<typename T>
intVector<T>::deduplicate()
{
int oldSize=_size;
Rank i=1;
while(i<_size)
(find(_elem[i],0,i)<0)?i++:remove(i);//如果找到元素则删除,否i++
return oldSize-_size; //返回删除的元素个数
}
1、AbstractData Type(ADT)抽象数据类型:数据模型上定义的一种操作。Data structure数据结构:基于某种特定语言,实现ADT的一整套算法。向量是数组的抽象和泛化,有一组元素按线性顺序封装而成。
ADT操作接口:
2、vector模板类
(1)基于复制的构造
template<typename T>
voidVector<T>::copyFrom(T* const A,Rank lo,Rank hi)
{
_elem=new T[_capacity=2*(hi-lo)];//申请空间
_size=0;
while(lo<hi)
_elem[_size++]=A[lo++];
}
一般都以左闭右开,A[lo,hi),所以总共长度是hi-lo,hi不属于vector的,可以当做哨兵使用。
(2)扩容expand()
上溢overflow,下溢underflow.动态空间管理:在即将发生上溢时,适当地扩大内部数组的容量。
template<typename T>
voidVector<T>::expand()
{
if(_size<_capacity) return;
T *oldElem=_elem; //备份
_elem=new T[capacity<<=1]; //容量加倍
for(int i=0;i<_size;i++)
_elem[i]=oldElem[i];
delete [] oldElem; //释放空间
}
为什么需要容量加倍呢?下图是递增扩容和加倍扩容。
平均复杂度average/expected complexity,是独立的过程。
分摊分析amortized complexity,连续的操作,更加贴近实际。
3、无序向量
template <typename T> Vector{...};定义一系列vector:
例如Vector<int> myVector… Vector<BinTree > myVector…
(1)元素访问:重载操下标操作符[]
template<typename T>
T&Vector<T>::operator[](Rank r)const
{
return _elem[r];
}
(2)插入元素insert( )
template<typename T> //把e作为秩r的元素插入
RankVector<T>::insert(Rank r,T const &e)
{
expand(); //扩容
for(int i=_size;i>r;i--)
_elem[i]=_elem[i-1]; //将元素往后移动,直到移动到r
_elem[r]=e;_size++;
return r;
}
(3) 区间删除remove(),复杂度O(n-hi)
template <typename T> //删除区间[lo,hi)
int Vector<T>::remove(Rank lo,Rank hi)
{
if(lo==hi) return 0;
while(hi<_size) _
elem[lo++]=_elem[hi++]; //顺次往前移动hi-lo位
_size=lo;shrink();
return hi-lo;
}
(4)单元素删除remove(),复杂度为O(n-r)
template <typename T>
T Vector<T> ::remove(Rank r)
{
T e=_elem[r];
remove(r,r+1);
return e;
}
如果区间删除调用单元素删除的话,理论上是可以的,但是复杂度的话每次调用都需要O(n-r),这样级数相加,最后区间删除的复杂度有可能是O(n2)。
(5)查找操作find无需判断一般只支持判等操作,有序向量支持比较操作
template <typename T> //查找在区间lo,hi之间的元素,靠近hi
Rank Vector<T>::find(T const &e,Rank lo,Rank hi) const
{
while((lo<hi--)&&(e!=_elem[hi]));//持续到成功为止才退出循环
return hi;
}最好O(1),最差O(n)
(6)唯一化deduplicate( )去重操作:经过查找函数,如果有的话删除
template<typename T>
intVector<T>::deduplicate()
{
int oldSize=_size;
Rank i=1;
while(i<_size)
(find(_elem[i],0,i)<0)?i++:remove(i);//如果找到元素则删除,否i++
return oldSize-_size; //返回删除的元素个数
}
对于find,remove每次迭代最多是O(n),所以最坏的复杂度是O(n2)。
相关文章推荐
- GlassFish移植Tips 来自<美丽的爪哇岛>的博客
- TCP网络通信服务器端简单示例
- js模块化开发--AMD--CMD
- Function类型-作为值的函数
- PyQt + QML 快速开发GUI入门总结
- UIDynamics -- 力学部分
- linux(CentOS) 下安装java运行环境及输出Hello World
- Uva 1586 Molar mass
- 初次接触真正意义上的Java EE
- Linux安全之SYN攻击原理及处理
- Java for LeetCode 211 Add and Search Word - Data structure design
- 闹钟功能实现+本地通知+音频播放
- JVM优化与案例分析
- State of Hyperparameter Selection
- OSA实践——WCF服务异步调用
- (2)LinuxI2C驱动--I2C总线
- vc中winexec使用
- LightOJ1020(博弈)
- 01 Linux入门介绍
- 14.1.1 小玩文件