1. 程式人生 > >資料結構——向量——向量模板原始碼

資料結構——向量——向量模板原始碼

 自己動手寫了一個向量模板,模板函式的定義與實現本該寫在同一個檔案裡的,為了查詢方便分開了。定義寫在標頭檔案,實現寫在原始檔了。

本頁內容:

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);
	}
}