一、【資料結構】向量(vector)的實現

csu_zhengzy~發表於2018-11-20

本文使用c++實現vector資料結構,vector的介面函式採用高效的實現方式,這樣一方面使我加深對資料結構的理解,另一方便可以讓我再回顧回顧c++,之前寫了好久python都快把c++忘記了。

vector介面列表
操作 功能 物件
vector(int c, Rank s, T v) 設定容量、初始大小、元素初始值  
vector(int c, Rank s) 設定容量、初始大小  
vector(initializer_list<T>) 列表初始化方式構造  
vector(const vector<T>& A, Rank lo, Rank hi) 從另一vector拷貝構造新vector物件  
~vector() 解構函式,手動釋放動態陣列所佔的空間  
expand() 容量更新(擴容) 向量
sharink() 容量更新(縮減) 向量
display() 列印vector內部元素 向量
size() 返回vector當前有效尺寸 向量
get(Rank r) 獲取指定元素 向量
put(Rank r, const T e) 替換指定元素 向量
permute() 打亂vector順序 向量
unsort(Rank lo, Rank hi) 打亂vector指定區間的順序 向量
find(Rank lo,Rank hi,const T e) 在指定區間查詢指定元素 向量
insert(Rank r, const T& e) 在指定區間插入元素 向量
insert(const T& e) 在尾部插入元素 向量
remove(Rank lo, Rank hi) 刪除指定區間的元素 向量
remove(Rank r) 刪除單個元素 向量
deduplicate() 除去重複元素 向量
traverse(void(*func)(T& a)) 用指定函式批量處理元素(函式指標方式) 向量
traverse(FunClass func) 用指定函式批量處理元素(函式物件方式) 向量
disordered() 判斷是不是有序向量 向量
uniquify() 除去重複元素 有序向量
search(Rank lo, Rank hi, const T e) 在指定區間中查詢元素 有序向量
binsearch(Rank lo, Rank hi, const T e) 在指定區間中查詢元素(二分查詢) 有序向量
sort(Rank lo, Rank hi, int a) 排序演算法彙總 向量
bubbleSort(Rank lo, Rank hi) 氣泡排序 向量
mergeSort(Rank lo, Rank hi) 歸併排序 向量
過載運算子[] 下標運算子 向量
過載運算子= 賦值運算子 向量
過載運算子= 賦值運算子(列表賦值方式) 向量
過載運算子== 相等判斷運算子 向量
過載運算子<= 小於等於判斷運算子 向量
過載運算子>= 大於等於判斷運算子 向量
#pragma once
#define DEFAULT_CAPACITY 10 //預設容量大小
using namespace std;
typedef int Rank;

template <typename T>
class vector
{
protected:
	Rank _size;
	int _capacity;
	T *_elem; //vector內部所維護的陣列的指標
public:
	//建構函式(容量,初始大小,初始值)
	vector(int c = DEFAULT_CAPACITY, Rank s = 0, T v = 0);
	vector(initializer_list<T>);    //列表初始化方式
	vector(const vector<T>& A, Rank lo, Rank hi);
	//解構函式
	~vector();

	//複製建構函式
	void copyFrom(const vector<T>& A, Rank lo, Rank hi);

	//容量更新(擴容和縮減)
	void expand();		
	void sharink();      

	//普通成員函式
	void display() const; //列印vector內部元素
	Rank size() const;    //返回vector當前size
	T get(Rank r);        //獲取指定元素
	void put(Rank r, const T e);  //替換指定元素
	void permute();       //打亂順序
	void unsort(Rank lo, Rank hi);  //打亂區間順序
	Rank find(Rank lo,Rank hi,const T e);           //查詢指定元素
	Rank insert(Rank r, const T& e); // 插入
	Rank insert(const T& e);       //在向量尾部插入
	int remove(Rank lo, Rank hi); //刪除指定區間的元素
	T remove(Rank r);           //刪除指定索引的單個元素
	void deduplicate();			  //除去重複元素
	void traverse(void(*func)(T& a));  //用指定函式批量處理元素(函式指標方式)
	template<typename FunClass> void traverse(FunClass func);             //用指定函式批量處理元素(函式物件方式)
	bool disordered() const;      //判斷是不是有序向量
	void uniquify();              //有序向量除去重複元素
	Rank search(Rank lo, Rank hi, const T e); //有序向量,在指定區間中查詢元素
	Rank search(const T e);
	Rank binsearch(Rank lo, Rank hi, const T e); //有序向量,二分查詢
	void swap(T& a, T& b);        //交換元素值
	void sort(Rank lo, Rank hi, int a);    //排序演算法彙總
	void bubbleSort(Rank lo, Rank hi);     //氣泡排序
	void mergeSort(Rank lo, Rank hi); //歸併排序(遞迴實現)
	//過載運算子
	T& operator[](const Rank i) const;           //下標運算子
	vector<T>& operator=(const vector<T> &A);    //賦值運算子
	vector<T>& operator=(initializer_list<T>);   //賦值運算子,列表初始化
	bool operator==(const vector<T>& A);         //判等運算子
	bool operator<=(const vector<T>& A);         //小於等於判斷
	bool operator>=(const vector<T>& A);         //大於等於判斷
};

//實現c++中vector容器底層(具體實現也要放在與宣告同樣的檔案中)

template <typename T> vector<T>::vector(int c, Rank s, T v)
{
	_elem = new T[_capacity = c];  //申請容量為T*c的記憶體空間並用_elem指標指向該地址
	for (_size = 0; _size < s; _elem[_size++] = v);  //對有效值進行初始化並更新_size
}

template<typename T> vector<T>::vector(initializer_list<T> li)
{
	_elem = new T[_capacity = li.size()];
	for (auto iter = li.begin(); iter != li.end(); iter++)
		_elem[_size++] = *iter;
}

template <typename T> vector<T>::vector(const vector<T>& A, Rank lo, Rank hi)
{
	copyFrom(A, lo, hi);
}


template <typename T> vector<T>::~vector()
{
	//釋放陣列中的空間
	delete[] _elem;
}

template <typename T> void vector<T>::copyFrom(const vector<T>& A, Rank lo, Rank hi)
{
	_capacity = (hi - lo) << 1;
	_size = 0;
	_elem = new T[_capacity];  //申請記憶體
	while (lo < hi)
	{
		_elem[_size++] = A[lo++];
	}
}

template<typename T> void vector<T>::display() const
{
	if (_size)
	{
		for (int i = 0; i < _size - 1; i++)
		{
			cout << _elem[i] << ",";
		}
		cout << _elem[_size - 1] << endl;
	}
}

//過載[]運算子
template<typename T> T& vector<T>::operator[](const Rank i) const
{
	return _elem[i];
}

template<typename T> vector<T>& vector<T>::operator=(const vector<T> &A)
{
	//釋放之前的空間,後面會自動建立
	delete[] _elem;
	copyFrom(A, 0, A.size());
	return *this;  //返回this的引用才能連續賦值A=B=C
}

template<typename T> vector<T>& vector<T>::operator=(initializer_list<T> li)
{
	delete[] _elem;
	_size = 0;
	_capacity = li.size() << 1;
	_elem = new T[_capacity];  //申請記憶體
	for(auto iter=li.begin();iter!=li.end(); iter++)
		_elem[_size++] = *iter;

	return *this;
}

template<typename T> Rank vector<T>::size() const
{
	return _size;
}

template<typename T> T vector<T>::get(Rank r)   
{
	return _elem[r];
}

template<typename T> void vector<T>::put(Rank r, const T e)
{
	_elem[r] = e;
}

template<typename T> void vector<T>::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];
	delete[] oldElem;
}


//{
//	//cout << "enpand():the old capacity: " << _capacity << endl;
//	if (_capacity < DEFAULT_CAPACITY) _capacity = DEFAULT_CAPACITY;
//	if ((_capacity >> 1) < _size) {  //如果_capacity不大於_size的兩倍,擴容
//		T* tempPtr = new T[_capacity=(_size << 1)];
//		//cout << "_size" << _size << endl;
//		for(int i=0;i<_size;i++)
//		{
//			tempPtr[i] = _elem[i];  //轉移資料
//			//cout << "i:" << i << endl;
//		}
//		delete[] _elem;  //清除之前的空間
//		_elem = tempPtr; //指標指向新的空間 
//	}
//	//cout << "enpand():the new capacity: " << _capacity << endl;
//}


template<typename T> void vector<T>::sharink()
{
	//cout << "sharink():the old capacity: " << _capacity << endl;
	if (_size < _capacity/4.0)   //_size小於_capacity的1/4,縮減
	{
		T *tempPtr = ((_size << 1) > DEFAULT_CAPACITY) ? new T[_capacity =(_size<<1)] : new T[_capacity = DEFAULT_CAPACITY];
		for (int i = 0; i < _size; i++)
		{
			tempPtr[i] = _elem[i];
			//cout << "i:" << i << endl;
		}
		delete[] _elem;
		_elem = tempPtr;   //更新指標指向
	}
	//cout << "sharink():the new capacity: " << _capacity << endl;

}

template<typename T> void vector<T>::permute()
{
	for(int i=0;i<_size;i++)
	{
		swap(_elem[i], _elem[rand()%_size]);   //隨機找一個替換
	}
}


template<typename T> void vector<T>::unsort(Rank lo,Rank hi)
{
	for (int i = lo; i < hi; i++)
	{
		swap(_elem[i], _elem[rand() % (hi - lo) + lo]);
	}
}

template<typename T> bool vector<T>::operator==(const vector<T>& A)
{
	if (_size != A.size()) return false;
	for (int i = 0; i < _size; i++)
	{
		if(_elem[i] != A[i]) return false;
	}
	return true; 
}

template<typename T> bool vector<T>::operator<=(const vector<T>& A)
{
	int min = (_size <= A.size()) ? _size : A.size();
	for (int i = 0; i < min; i++)
	{
		if ((*this)[i] != A[i])
			return ((*this)[i] <= A[i]) ? true : false;
	}
	return (_size <= A.size()) ? true : false;
}

template<typename T> bool vector<T>::operator>=(const vector<T>& A)
{
	int min = (_size <= A.size()) ? _size : A.size();
	for (int i = 0; i < min; i++)
	{
		if ((*this)[i] != A[i])
			return ((*this)[i] >= A[i]) ? true : false;
	}
	return (_size >= A.size()) ? true : false;
}

template<typename T>  Rank vector<T>::find(Rank lo, Rank hi, const T e)  //	前閉後開
{

	while ((hi--)>lo)
	{
		if(_elem[hi] == e) break;
	}
	return hi;
}

template<typename T> Rank vector<T>::insert(Rank r, const  T& e)
{	
	expand();
	//Rank從r至以後的元素都要往後面移一位
	for (int i = _size; i > r; i--)
	{
		_elem[i] = _elem[i - 1];
	}
	_elem[r] = e;
	_size++;
	return r;
 }

template<typename T> Rank vector<T>::insert(const T& e)
{
	return insert(_size, e);
}

template<typename T> int vector<T>::remove(Rank lo, Rank hi)   //前閉後開
{
	//首先指定後界秩後面的元素都往前面移動(hi-lo+1)個位置,原位置置零
	if (lo == hi) return 0;
	while(hi<_size)
	{
		_elem[lo++] = _elem[hi];
		_elem[hi++] = 0;
	}
	//更新_size
	_size -= (hi - lo);
	sharink();
	return (hi - lo);
}

template<typename T> T vector<T>::remove(Rank r)
{
	T e = _elem[r];
	remove(r, r + 1);
	return e;
}

template<typename T> void vector<T>::deduplicate()
{
	if (!_size) return;

	Rank rl = 0;   //第rl個是已經確認無重的最後一個
	Rank rr = 1;   //第rr個是要判斷的
	while (rr < _size)  // _size會減,rr會加
	{
		if (find(0, rl + 1, _elem[rr]) >= 0)    //確認是之前出現過
			remove(rr);
		else
		{
			rl++;       //加入一個有效值
			rr++;
		}
	}
}

template<typename T> void vector<T>::traverse(void(*func)(T& a))
{
	for (int i = 0; i < _size; i++)
	{
		func(_elem[i]);
	}
}

template<typename T> template<typename FunClass> void vector<T>::traverse(FunClass func)
{
	for (int i = 0; i < _size; i++)
	{
		func(_elem[i]);
	}
}


template<typename T> bool vector<T>::disordered() const
{
	for (int i = 0; i < _size - 1; i++)
	{
		if (_elem[i] > _elem[i + 1])
		{
			return false;
		}
	}
	return true;
}

template<typename T> void vector<T>::uniquify()
{
	if (_size<=1) return;
	Rank rl=0;    //已經確認好的序列的最後一個元素的秩
	Rank rr=1;    //正要判斷的元素的秩
	while (rr < _size)
	{
		if (_elem[rr] != _elem[rr - 1])  //發現一個新值,移動到rl+1
		{
			_elem[++rl] = _elem[rr++];
		}
		else
			rr++;
	}
	_size = rl + 1;
	sharink();
}

template<typename T> Rank vector<T>::search(Rank lo, Rank hi, const T e)
{
	return binsearch(lo, hi, e);
}

template<typename T> Rank vector<T>::search(const T e)
{
	return (_size <= 0) ? -1 : search(0, _size, e);
}

template<typename T> Rank vector<T>::binsearch(Rank lo, Rank hi, const T e)    //  [0][1][2][m][4][5][6][7][-hi-]
{
	//方法一
	//把mi這一點作為一個分界線,單數直接作為右側區間的左端點
	Rank mi;
	while (lo < hi)
	{
		mi = (lo + hi) >> 1;   //取中點的時候是往左偏的
		(e < _elem[mi]) ? hi = mi : lo = mi+1;     //都是左閉右開區間
	}
	return --lo;
}
																			   																																					   
//{   //方法二
//	Rank mi;
//	while (lo<hi)
//	{
//		mi = (lo + hi) >> 1;
//		if (_elem[mi] < e)
//			lo = mi + 1;
//		else if(_elem[mi] > e)
//			hi = mi;   //都是左閉右開區間
//		else
//			return mi;
//		}
//	return -1;
//}

template<typename T> void vector<T>::swap(T& a, T& b)
{
	a = a^b;      //原理:(a^b)^a=b
	b = a^b;
	a = a^b;  
}


template<typename T> void vector<T>::sort(Rank lo, Rank hi, int a)
{
	switch (a)
	{
		case 1:
			bubbleSort(lo, hi); break;   //氣泡排序
		case 2:;
			//selectSort(lo, hi); break;   //選擇排序
		case 3:
			mergeSort(lo, hi); break;    //歸併排序
		case 4:;
			//heapSort(lo, hi); break;     //堆排序
		default:;
			//quickSort(lo, hi); break;    //快速排序
	}
}

template<typename T> void vector<T>::bubbleSort(Rank lo, Rank hi)
{
	bool sorted = false;   //已有序標誌
	while (!sorted)        //如果有序,提前退出
	{
		sorted = true;
		for (int i = lo; i < hi - 1; i++)  //在一次迴圈中如果發現逆序,就置標誌位為false
		{
			
			if (_elem[i] > _elem[i + 1])
			{
				sorted = false;
				swap(_elem[i], _elem[i + 1]);
			}
			
		}
		hi--;
	}
}

template<typename T> void vector<T>::mergeSort(Rank lo, Rank hi)  //左閉右開區間
{
	if (!(lo < hi-1)) //只有一個元素則不用排序
		return;
	Rank mi = (lo + hi) >> 1;          //[0][1][2] [3]
	mergeSort(lo, mi);
	mergeSort(mi, hi);

	//開始歸併
	T* A = _elem + lo;
	T* C = _elem + mi;
	int lb = mi - lo;  //1
	int lc = hi - mi;  //2
	T* B = new T[lb];  
	for (int i = 0; i < lb; i++)
		B[i] = A[i];    //複製元素到新空間
	//比較B和C所指序列的大小,將結果放置在A處
	for (int a=0, i = 0, j = 0; i < lb || j < lc;)
	{
		if (i < lb&&j < lc)       //兩個序列都還有剩餘
			A[a++] = (B[i] < C[j]) ? B[i++] : C[j++];
		if (i < lb && !(j < lc))  //只有B序列還有剩餘
			A[a++] = B[i++];
		if (!(i < lb) && j < lc)  //只有C序列還有剩餘
			A[a++] = C[j++];
	}
	delete[] B;  //有new就要有delete
}

 

相關文章