1.向量介绍 2.向量的抽象数据类型接口
3.ADT接口函数辅助函数
4.ADT接口函数操作实例
5.向量模板实现源码
6.ADT接口函数实现及算法讲解
7.ADT接口函数辅助函数实现及算法讲解
8.向量的运算符重载
向量是数组的抽象与泛化,由一组元素由线性次序封装而成。各元素与其相应的秩(rank)一一对应,采用循秩访问(call-by-rank)的方式,使对各元素的操作,管理维护更加简化、统一与安全。向量的元素类型可以灵活选取,便于定制复杂的数据结构。
template<typename T> Rank myVector<T>::size() const { return _size; }
template<typename T> T myVector<T>::get(Rank r) const { return _elem[r]; }
template<typename T> void myVector<T>::put(Rank r,T e) { _elem[r]=e;//用e替换秩为r的数值 }
template<typename T> Rank myVector<T>::insert(Rank r,T const& e) { expand();//如果有必要,扩容 for(int i=_size;i>r;i--)//自后向前 { _elem[i]=_elem[i-1];//后继元素顺次后移一个单元 } _elem[r]=e;//置入新元素 _size++;// 更新容量 return r;//返回秩 }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
template<typename T> int myVector<T>::remove(Rank lo,Rank hi) { if(lo==hi) { return 0; } while(hi<_size) { _elem[lo++]=_elem[hi++];//[hi,_size)顺次前移hi-lo位 } _size=lo;//更新规模 shrink();// 如有必要,缩容 return hi-lo;//返回被删除元素的数目 }
template<typename T> T myVector<T>::remove(Rank r) { T e=_elem[r]; remove(r,r+1); return e; }
template<typename T> int myVector<T>::disordered() const { int n=0;//计数器 for(int i=1;i<_size;i++)//逐一检查各对相邻元素 { n+=(_elem[i-1]>_elem[i]);//逆序则计数 } return n;//向量有序当且仅当n=0 }
template<typename T> void myVector<T>::sort() { sort(0,_size); }
template<typename T> Rank myVector<T>::find( T const& e, Rank lo, Rank hi ) const//在向量中查找元素,并返回秩最大者 { while((lo<hi--)&&e!=_elem[hi]) ;//逆向查找 return hi;//hi<lo意味着失败;否则hi即命中元素的秩 }
template<typename T> Rank myVector<T>::find( T const& e ) const//在向量中查找元素,并返回秩最大者 { while((lo<hi--)&&e!=_elem[hi]) ;//逆向查找 return hi;//hi<lo意味着失败;否则hi即命中元素的秩 }
template<typename T> Rank myVector<T>::search(T const &e) const { return search(e,0,_size); }
template<typename T> int myVector<T>::deduplicate() { int oldSize=_size;//记录原规模 Rank i=1;//从_elem[1]开始 while(i<_size)//自前向后逐一考查各元素_elem[i] { if(find(_elem[i],0,i)<0)//在前缀中寻找雷同者 { i++;//若无雷同则继续考查其后继 } else { remove(i);//否则删除雷同者 } } return oldSize-_size;//向量规模变化量。即删除元素总数 }
template<typename T> int Vector<T>::uniquify() { int oldSize=_size; int i=0;//从首元素开始 while(i<_size-1)//从前向后逐一比对各队相邻元素 { (_elem[i]==_elem[i+1])?remove(i+1):i++;//若雷同,则删除后者;否则转至后后一元素 } return oldSize-_size;//向量规模变化量。即删除元素总数 }高效算法:上述低效算法之所以低效,是因为要多次执行remove函数,每执行一次remove,都要将后继元素依次前移,导致复杂度增加。由此可想,我们何不去掉 remove函数,直接在每个区间中取出一个元素组成一个新的向量呢。可用下图形象展示。
template<typename T> int Vector<T>::uniquify() { Rank i=0,j=0;//各对互异"相邻"元素的秩 while(++j<_size)//逐一扫描,直至末元素 { if(_elem[i]!=_elem[j]) _elem[++i]=_elem[j];//跳过雷同者;发现不同元素时,向前移至紧邻于前者右侧 } _size=++i;shrink();//直接截除尾部多于元素 return j-i;//向量规模变化量。即删除元素总数 }
//遍历1--利用函数指针进行只读或局部性修改 template<typename T> void myVector<T>::traverse(void (*visit ) ( T& )) { for(int i=0;i<_size;i++) { visit(_elem[i]); } } //遍历2--利用对象机制可进行全局性修改 template<typename T> template<typename VST> void myVector<T>::traverse(VST &visit) { for(int i=0;i<_size;i++) { visit(_elem[i]); } }
template<typename T> void myVector<T>::copyFrom(T const*A,Rank lo,Rank hi) { _size=hi-lo;//获取向量规模 _capacity=hi-lo;//获取向量容量 _elem=new T[_capacity];//生成向量数据区(此时向量处于饱和状态) for(int i=lo;i<hi;i++) { _elem[i-lo]=A[i]; } }
template<typename T> void myVector<T>::expand() { if(_size<_capacity) { return; //尚未满员时,不必扩容 } _capacity=maxoftwo(_capacity,DEFAULT_CAPACITY);//不低于最小容量 T*oldElem=_elem;//原向量指针保存 _elem=new T[_capacity<<=1];//容量加倍 for(int i=0;i<_size;i++)//复制原向量内容 { _elem[i]=oldElem[i];//T为基本类型 ,或已重载赋值操作符"=" } delete [] oldElem;//释放原空间 }
template<typename T> void myVector<T>::shrink() { if(_size<_capacity/2) { T*oldElem=_elem;//原向量指针保存 _elem=new T[_capacity>>=1];//容量缩减一半 for(int i=0;i<_size;i++)//复制原向量内容 { _elem[i]=oldElem[i]; } } }
template<typename T> Rank myVector<T>::max(Rank lo,Rank hi) { T maxT; Rank rank; maxT=_elem[lo]; for(int i=lo;i<hi;i++) { if(maxT<_elem[i]) { rank=i; maxT=_elem[i]; } } return rank; }
template<typename T> int myVector<T>::max(int one,int two) { if(one>two) { return one; } else { return two; } }
T& operator[] ( Rank r ) const{return _elem[r];}; //重载下标操作符,可以类似于数组形式引用各元素 myVector<T> & operator= ( myVector<T> const& ); //重载赋值操作符,以便直接克隆向量