ベクトル-vector最下位実装


最も基本的な線形構造はシーケンスと総称され、データ項目の論理順序とその物理記憶アドレスとの対応関係に応じて、シーケンスをベクトル(vector)とリスト(list)にさらに区別することができる.
ベクトルでは、すべてのデータ項目の物理的格納位置が論理順序と完全に一致し、このときの論理順序もランク(rank)と呼ばれる.
リストでは,論理的に隣接するデータ項目は物理的に必ずしも隣接していないが,間接アドレス方式でカプセル化された位置(position)で相互参照される.
 
Vectorテンプレートクラス
/*************************************************************************
	> File Name: vector.h
	> Author: amoscykl
	> Mail: [email protected] 
	> Created Time: 2018 07 02      20 51 45 
 ************************************************************************/

typedef int Rank;	// 
#define DEFAULT_CAPACITY  3			//       

template  class  Vector {	//     
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);			//      
	void selectionSort(Rank lo, Rank hi);	//      
	void merge(Rank lo, Rank mi, Rank hi);	//    
	void mergeSort(Rank lo, Rank hi);		//      
	Rank partition(Rank lo, Rank hi);		//      
	void quickSort(Rank lo, Rank hi);		//      
	void heapSort(Rank lo, Rank hi);		//   

public:
//     
	Vector( 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
					/*    */
	Vector( T const* A, Rank n) { copyFrom(A,0,n); }				//      
	Vector( T const* A, Rank lo, Rank hi) { copyFrom(A,lo,hi); }	//  
	Vector( Vector const& V) { copyFrom( V._elem, 0, V._size); }	//      
	Vector( Vector const& V, Rank lo, Rank hi) { copyFrom( V._elem, lo, hi); }	//  
//    
	~Vector() { delete [] __elem};
//      
	Rank size() const { return _size; }		//  	
	bool empty() const { return !_size; }	//  
	int disordered() const;					//         
	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;	//        
//      
	T& operator[] (Rank r) const;			//       ,              
	Vector & operator = (Vector const& );	//       ,        
	T remove ( Rank r );					//    r   
	int remove(Rank lo, Rank hi);			//         
	Rank insert(Rank r, T const& e);		//    
	Rank insert(T const& e ) { return insert (_size,e); }	//         
	void sort(Rank lo, Rank hi);			//     
	void sort() { sort(0,_size); }			//    
	void unsort (Rank lo, Rank hi );		//     
	void unsort { unsort(0, _size); }		//    
	int deduplicate();						//    
	int uniquify();							//    
//  
	void traverse( void (* ) (T &) );				//  :       
	template  void traverse (	VST& );	//  :      
};	//Vector 

 
 
 
レプリケーションベースの構築方法:
template 		//    
void Vector::copyFrom ( T const* A, Rank lo, Rank hi) {	//     A[lo,hi]       
	_elem = new T[_capacity = 2 * (hi - lo) ]; _size = 0;	//    ,    
	while ( lo < hi) 
		_elem[_size++] = A[lo++];			//   _elem[0,hi-lo]
}

 
 
 
リロードベクトル複素値オペレータ:
template  Vector& Vector::operator= (Vector const& V) { //  
	if (_elem )	  delete [] _elem;			//      
	copyFrom(V._elem, 0, V.size() );		//    
	return *this;							//         ,      
}

 
 
 
ダイナミックスペース管理
1.静的空間管理
内部配列が占める物理空間の容量は、ベクトルのライフタイム内に調整が許可されない場合、静的空間管理ポリシーと呼ばれます.このポリシーの空間効率は保証しにくい.一方、容量が固定され、オーバーフローを招く可能性がある.一方,一部の空間を予約しても,合理的な予約量を明確に定義することは困難である.
上記copyFrom()メソッドでは,容量を初期規模の2倍にしてもオーバーフローするリスクがある.
 
ベクトルの実際の規模とその内部配列容量との比(_size/_capacity)は、空間利用率を測定する重要な指標である充填因子と呼ばれる.
 
そのため、ダイナミックスペース管理ポリシーを変更する必要があります.その中で有効な方法は,いわゆる拡張可能容量を用いることである.
 
2.動的空間管理
拡張アルゴリズムexpand()
 template  void Vector::expand() {	//         
	if (_size < _capacity ) return;			//     ,    
	if (_capacity < DEFAULT_CAPACITY ) _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  void Vector::shrink() {	//               
	if (_capacity < DEFAULT_CAPACITY << 1) return;	//     DEFAULT_CAPACITY   
	if (_size << 2 > _capacity) return ;			// 25%  
	T* oldElem = _elem;	  _elem = new T[_capacity >>= 1];		//    ,    
	for (int i = 0; i < _size; i++) _elem[i] = oldElem[i];		//       
	delete [] oldElem;								//     
}

 
 
 
 
リロードベクトルオペレータ[]
template  T& Vector::operator[] (Rank r) const	//       
{ return _elem[r]; }

 
 
 
無秩序ベクトル要素検索インタフェースfind()
template 				//         :        e   ;   ,  lo-1
Rank Vector::find(T const& e, Rank lo, Rank hi) const {
	while( (lo < hi -- ) && (e != _elem[hi] ) );		//    ,     
	return hi;						// hi < lo,       ;  hi       
}

 
 
 
ベクトル要素挿入インタフェースinsert()
template 				// e    r    
Rank Vector::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;						//   
} 

 
 
 
区間削除:remove(lo,hi)
template  int Vector::remove ( Rank lo, Rank hi ) { //    [lo,hi] 
	if (lo == hi) return 0;			//      ,        ,  remove(0,0)
	while (hi < _size) _elem[lo++] = _elem[hi++];		//[hi,_size]    hi-lo   
	_size = lo;						//    ,      [lo,_size=hi]   
	shrink();						//    ,   
	return hi - lo;					//          
}

 
単一要素削除remove(r)
 
template  int Vector::remove (Rank r) {  //       r   ,0 <= e < size
	T e = _elem[r];					//       
	remove(r,r+1);					//        ,      [r,r+1]   
	return e;						//       
} 

 
 
 
秩序性の選別
template  int Vector::disordered() const {	//               
	int n = 0;						//   
	for (int i = 1; i < _size; i ++)	//    _size-1      
		if (_elem[i-1] > _elem[i] )  n++;		//     
	return n;						//        n=0
}

 
 
 
ユニーク化
秩序ベクトルuniquify()インタフェースの効率的な実現
template  int Vector::uniquify()	{	//            
	Rank i = 0, j = 0;				//    “  ”     
	while(++j < _size)				//    ,     
		if ( _elem[i] != _elem[j] ) //     
			_elem[++i] = _elem[j];	//       ,           
	_size = ++i; shrink();			//          
	return j - i;					//       ,        
} 

 
 
 
検索
統合インタフェースsearch()
template        //     [lo,hi] ,     e         
Rank Vector::search (T const& e, Rank lo, Rank hi) const {
    return ( rand() % 2) ?  //  50%            Fibonacci  
        binSearch(_elem, e, lo, hi) : fibSearch (_elem, e, lo, hi);
}

 
 
 
二分検索(バージョンA)
//    
template   static Rank binSearch(T* A, T const& e, Rank lo, Rank hi) {
	while( lo < hi) {	//              ,     
		Rank mi = ( lo + hi) >> 1;		//      
		if( e < A[mi] ) hi = mi;		//     [lo,hi)    
		else if (A[mi] < e)	lo = mi + 1;	//     (mi,hi)    
		else	return mi;				// mi   
	}	//          
	return -1;							//    
}		//        ,          。 

 
 
 
Fibonacci検索
ちょっと...
 
 
シーケンサ
ユニファイドエントリ
template  void Vector::sort (Rank lo, Rank hi) {	//    [lo,hi]   
	switch( rand() % 5) {	//        ,                 
		case 1: bubbleSort ( lo, hi); break;		//    
		case 2: selectionSort (lo, hi); break;		//    
		case 3: mergeSort (lo,hi);	break;			//    
		case 4: heapSort (lo,hi);	break;			//   
		default: quickSort (lo,hi); break;			//    
	}
}

 
バブルソート
 
 //    
template 		//       
void Vector::bubbleSort( Rank lo, Rank hi)
{ while ( !bubble(lo, hi--) ); }	//       ,     

//    
template  bool Vector::bubble (Rank lo, Rank hi) {	//      
	bool sorted = true;		//      
	while (++lo < hi)		//    ,          
		if ( _elem[lo-1] > _elem[lo] ) {	//   ,          ,            
			sorted = false;
			swap( _elem[lo-1],_elem[lo]);
		}
	return sorted;			//      
}

 
 
 
 
集計ソート
集計ソートの主体構造は典型的な分治戦略に属し、コードのように再帰的に記述し、実現することができる.
//    
template 		//      
void Vector::mergeSort (Rank lo, Rank hi) {
	if (hi - lo < 2)	return ;	//         ,  ...
	int mi = ( lo + hi ) / 2;		//     
	mergeSort ( lo, mi ); mergeSort ( mi, hi );		//    
	merge(lo,mi,hi);				//  
}

template 		//       
void Vector::merge ( Rank lo, Rank mi, Rank hi )	{	//        [lo,mi) [mi,hi)
	T* A = _elem + lo;		//      A[0,hi-lo) = _elem[lo,hi)
	int lb = mi - lo;	T* B = new T[lb];		//    B[0,lb) = _elem[lo,mi)
	for ( Rank i = 0; i < lb; B[i] = A[i++] ) 
		;	//      
	int lc = hi - mi;	T* C = _elem + mi;		//    C[0,lc_ = _elem[mi,hi)
	for (Rank i = 0, j = 0, k = 0; ( j < lb ) || ( k < lc) ; ) { //B[j] C[k]      A  }
		if ( ( j < lb ) && ( ! ( k < lc ) || (B[j] <= C[k] ))) A[i++] = B[j++];
		if ( ( k < lc ) && ( ! ( j < lb ) || (C[k] <  B[j] ))) A[i++] = C[k++];
	}
	delete [] B;		//      B
}		//