数据结构——向量——向量模板源码
来源:互联网 发布:linux tcp backlog 编辑:程序博客网 时间:2024/06/11 02:36
推荐文章:那些年,做的几个应用
自己动手写了一个向量模板,模板函数的定义与实现本该写在同一个文件里的,为了查找方便分开了。定义写在头文件,实现写在源文件了。
本页内容:
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);}}
1 0
- 数据结构——向量——向量模板源码
- 数据结构—向量(vector)-数组
- R语言中的数据结构——向量
- 数据结构与算法笔记 —— 向量
- 数据结构——第二章 向量
- 数学公式 —— 向量
- 算法系列——向量空间模型计算模板选择
- 数据结构(C++)—— 向量(Vector)
- 支持向量机—SMO算法源码分析(1)
- 支持向量机—核函数源码分析(2)
- 数学基础 —— 向量旋转到另一个向量
- 支持向量机专题——线性支持向量机
- 线性代数笔记3——向量1(向量简介)
- C++数据类型——向量
- cocos2d-android——向量
- cuda——向量内积
- 数据结构--向量--向量介绍
- 向量模板
- AngularJS Form 进阶:远程校验和自定义输入项
- specular BRDF reference
- 冒泡排序
- iOS 使用模拟器的时候快速切换网络的指令
- mac git 步骤
- 数据结构——向量——向量模板源码
- hibernate 中TIMESTAMP的使用
- js创建对象几种常用方法
- 黑马程序员——Foundation框架NSFileManager介绍和用法
- 第十二章 特质
- RandomAccess接口
- c++数据类型间的转换
- UVALive 5072 Find the Multiples
- 相同格式EXCEL汇总