推荐文章:那些年,做的几个应用
自己动手写了一个向量模板,模板函数的定义与实现本该写在同一个文件里的,为了查找方便分开了。定义写在头文件,实现写在源文件了。
本页内容:
a.头文件("myVector.h")
b.源文件(“myVector.cpp")
c.模板测试文件("mainVTest.cpp")
向量模板实现源码:
a.头文件("myVector.h"):
#ifndef _MYVECTOR_H__
#define _MYVECTOR_H__
typedef int Rank;//秩
#define DEFAULT_CAPACITY 3 //默认的初始容量(实际应用中可设置为更大)
template <typename T> class myVector { //向量模板类
protected:
Rank _size; int _capacity; T* _elem; //规模、容量、数据区
void copyFrom ( T const* A, Rank lo, Rank hi ); //复制数组区间A[lo, hi)
void expand(); //空间不足时扩容
void shrink(); //装填因子过小时压缩
bool bubble ( Rank lo, Rank hi ); //扫描交换
void bubbleSort ( Rank lo, Rank hi ); //起泡排序算法
Rank max ( Rank lo, Rank hi ); //选取区间[lo,hi)间的最大元素
int maxoftwo(int one,int two){ if(one>two) return one; else return two; }//选取两者之间的最大值
Rank binSearch(T*A,T const&e,Rank lo,Rank hi) const;//二分查找
public:
// 构造函数
myVector ( int c = DEFAULT_CAPACITY, int s = 0, T v = 0 ) //容量为c、规模为s、所有元素初始为v
{ _elem = new T[_capacity = c]; for ( _size = 0; _size < s; _elem[_size++] = v ); } //s<=c
myVector ( T const* A, Rank n ) { copyFrom ( A, 0, n ); } //数组整体复制
myVector ( T const* A, Rank lo, Rank hi ) { copyFrom ( A, lo, hi ); } //区间
myVector ( myVector<T> const& V ) { copyFrom ( V._elem, 0, V._size ); } //向量整体复制
myVector ( myVector<T> const& V, Rank lo, Rank hi ) { copyFrom ( V._elem, lo, hi ); } //区间
// 析构函数
~myVector() { delete [] _elem; } //释放内部空间
// 只读访问接口
Rank size() const { return _size; } //规模
T get(Rank r) const;//获取秩为r的元素
void put(Rank r,T e);//用e替换秩为r的数值
Rank insert ( Rank r, T const& e ); //插入元素
Rank insert ( T const& e ) { return insert ( _size, e ); } //默认作为末元素插入
int remove ( Rank lo, Rank hi ); //删除秩在区间[lo, hi)之内的元素
T remove ( Rank r ){ T e=_elem[r];remove(r,r+1); return e;} //删除秩为r的元素
int disordered() const; //判断向量是否已排序
void sort ( Rank lo, Rank hi ); //对[lo, hi)排序
void sort() { sort ( 0, _size ); } //整体排序
Rank find ( T const& e ) const { return find ( e, 0, _size ); } //无序向量整体查找
Rank find ( T const& e, Rank lo, Rank hi ) const; //无序向量区间查找
Rank search ( T const& e ) const //有序向量整体查找
{ return ( 0 >= _size ) ? -1 : search ( e, 0, _size ); }
Rank search ( T const& e, Rank lo, Rank hi ) const; //有序向量区间查找
int deduplicate(); //无序去重
int uniquify(); //有序去重
bool empty() const { return !_size; } //判空
// 重载
T& operator[] ( Rank r ) const{return _elem[r];}; //重载下标操作符,可以类似于数组形式引用各元素
myVector<T> & operator= ( myVector<T> const& ); //重载赋值操作符,以便直接克隆向量
// 遍历
void traverse ( void (*visit ) ( T& ) ); //遍历(使用函数指针,只读或局部性修改)
template <typename VST> void traverse ( VST& ); //遍历(使用函数对象,可全局性修改)
}; //Vector
#include"myVector.cpp"
#endif
b.源文件("myVector.cpp"):
/***************protected函数实现****************/
//复制数组区间A[lo, hi)--"copyFrom"函数
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]=A[i];
}
}
//向量空间不足时扩容--"expand"函数
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;//释放原空间
}
//装填因子过小时压缩空间--"shrink"函数
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];//T为基本类型 ,或已重载赋值操作符"="
}
}
}
//扫描交换--"bubble"函数
template<typename T>
bool myVector<T>::bubble(Rank lo,Rank hi)
{
bool sorted=true;//整体有序标志
while(++lo<hi)
{
if(_elem[lo-1]>_elem[lo])//自做向右,逐一检查各对相邻元素
{
sorted=false; //逆序
T temp;//交换
temp=_elem[lo-1];
_elem[lo-1]=_elem[lo];
_elem[lo]=temp;
}
}
return sorted;
}
//起泡排序算法
template<typename T>
void myVector<T>::bubbleSort(Rank lo,Rank hi)
{
while(!bubble(lo,hi--));//逐趟做扫描交换,直至全部有序
}
//选取区间[lo,hi)间的最大元素
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;
}
/****************public函数实现******************/
//获取秩为r的元素
template<typename T>
T myVector<T>::get(Rank r) const
{
return _elem[r];
}
//向向量写入数值--"put"函数
template<typename T>
void myVector<T>::put(Rank r,T e)
{
_elem[r]=e;//用e替换秩为r的数值
}
//插入元素--"insert"函数
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;//返回秩
}
//删除秩在区间[lo, hi)之内的元素--"remove"函数
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;//返回被删除元素的数目
}
// 判断向量是否已排序--"disordered"函数
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
}
//对区间[lo,hi)排序(排序接口)--"sort"函数
template<typename T>
void myVector<T>::sort(Rank lo,Rank hi)
{
bubbleSort(lo,hi);
}
//无序向量[lo,hi)区间查找--"find"函数
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即命中元素的秩
}
//有序向量[lo,hi)区间查找--"search"函数
template<typename T>
Rank myVector<T>::search(T const &e,Rank lo,Rank hi) const
{
return binSearch(_elem,e,lo,hi);//二分查找
}
//无序去重--"deduplicate"函数
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;//向量规模变化量。即删除元素总数
}
//有序去重--"uniquify"函数
template<typename T>
int myVector<T>::uniquify()
{
int oldSize=_size;//记录原规模
int i=0;//从首元素开始
while(i<_size-1)//从前向后逐一比对各队相邻元素
{
(_elem[i]==_elem[i+1])?remove(i+1):i++;//若雷同,则删除后者;否则转至后后一元素
}
return oldSize-_size;//向量规模变化量。即删除元素总数
}
//遍历--"traverse"函数
//遍历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>
Rank myVector<T>::binSearch(T*A,T const&e,Rank lo,Rank hi) const
{
Rank mi;
while(lo<hi)//每步迭代可能要做两次比较判断,有3个分支
{
mi=(lo+hi)>>1;//以中点为轴点
if(e<A[mi]) hi=mi;//深入前半段[lo,mi)继续查找
else if(A[mi]<e) lo=mi+1;//深入后半段(mi,hi)
else return mi;//在mi处待命
}
if(e<A[mi])
{
return mi-1;//查找失败
}
else
{
return mi;//查找失败
}
<pre>}
c.模板测试文件("mainVTest.cpp"):
#include<iostream>
#include"myVector.h"
#include<cstdlib>
using namespace std;
myVector<int> VTest;
void CoutVTest();
void DisturbVTest();
template <typename T> void visit(T e)
{
e++;
}
int main()
{
for(int i=0;i<20;i++)
{
VTest.insert(i);
}
cout<<"初始向量(insert加入,get读取):"<<endl;
CoutVTest();
//测试函数
cout<<"测试函数:"<<endl;
//size()
cout<<"size()="<<VTest.size()<<endl;
//put(int r,T e)
VTest.put(0,20);//将0号元素换为20
cout<<"put(0,20)=";
CoutVTest();
//insert(2,100)
VTest.insert(2,100);
cout<<"insert(2,100)=";
CoutVTest();
//remove(4)
VTest.remove(4);
cout<<"remove(4)=";
CoutVTest();
VTest.remove(0,10);
cout<<"remove(0,10)=";
CoutVTest();
//disordered()
cout<<"disordered()="<<VTest.disordered()<<endl;
VTest.put(0,100);
cout<<"After put(0,100)=";
CoutVTest();
cout<<"Then disordered()="<<VTest.disordered()<<endl;
//sort()
VTest.sort();
cout<<"sort()=";
CoutVTest();
cout<<"After New VTest=";
DisturbVTest();
CoutVTest();
VTest.sort(0,5);
cout<<"sort(0,5)=";
CoutVTest();
//find(41)
cout<<"find(41)="<<VTest.find(41)<<endl;
cout<<"find(1000)="<<VTest.find(1000)<<endl;
cout<<"find(41,0,5)="<<VTest.find(41,0,5)<<endl;
cout<<"find(41,5,10)="<<VTest.find(41,5,10)<<endl;
// search(4)
VTest.sort();
cout<<"After sort()=";
CoutVTest();
cout<<"search(41)="<<VTest.search(41)<<endl;
cout<<"search(50)="<<VTest.search(50)<<endl;
//deduplicate()
VTest.put(2,58);
VTest.put(9,58);
cout<<"After New VTest=";
CoutVTest();
cout<<"deduplicate()="<<VTest.deduplicate()<<endl;
CoutVTest();
//uniquify()
VTest.sort();
VTest.insert(3,58);
VTest.insert(3,58);
cout<<"After New VTest=";
CoutVTest();
cout<<"uniquify()="<<VTest.uniquify()<<endl;
CoutVTest();
//traverse()
VTest.traverse(visit);
cout<<"traverse()=";
CoutVTest();
cout<<"测试结束!";
return 0;
}
void CoutVTest()
{
for(int i=0;i<VTest.size();i++)
{
cout<<VTest.get(i)<<" ";
}
cout<<endl;
}
void DisturbVTest()
{
for(int i=0;i<VTest.size();i++)
{
VTest.put(i,rand()%100);
}
}