資料結構——向量——向量模板原始碼
阿新 • • 發佈:2019-02-20
自己動手寫了一個向量模板,模板函式的定義與實現本該寫在同一個檔案裡的,為了查詢方便分開了。定義寫在標頭檔案,實現寫在原始檔了。
本頁內容:
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); } }