C++STL標準模板與vector

C++拓展了面向對象和模板
STL分兩大部分:容器,算法
函數模板

//任意類型的選擇排序
template <typename T>
void sort(T arr[], int len)
{
	for (int i = 0; i < len - 1; ++i)
	{
		for (int j = i + 1; j < len; ++j)
		{
			if (arr[i] > arr[j])
			{
				T tempVal = arr[i];
				arr[i] = arr[j];
				arr[j] = tempVal;
			}
		}
	}
}

容器

vector deque list map (set multiset multimap)

分爲兩類:
1、序列式容器 是可序羣集,每個元素都有固定的位置,元素的位置取決於插入的時機和地點,和元素值無關(vector deque list)
2、關係(聯)式容器 是已序羣集 元素的位置取決於元素值和特定的排序規律 (set map multiset multimap)

優劣:
元素進入容器,序列式優於關係式
搜索元素時,關係式優於序列式

查找:
二分查找(折半查找)

STL容器必須滿足以下條件:
1、容器進行元素的插入操作,內部實現的是拷貝操作,因此STL容器內的每一個元素都必須能夠被拷貝
2、所有的元素形成次序,也就是說多次遍歷每個元素時的次序總是相同的
3、一般而言,各項操作並非絕對安全,調用者必須確保傳給操作函數的參數符合需求

迭代器:可遍歷stl容器內全部或部分元素的一個對象,對象行爲理解爲指針(智能指針)

vector
動態數組(c++標準並沒有要求必須用動態數組來實現vector,只是規定了相應的條件和操作複雜度)

使用案例:

vector<int> v;//定義了一個對象,這個對象就是一個動態數組

	for (int i = 0; i < 10; ++i)
		v.push_back(i + 1);//分配空間的事情,賦值的事情

	for (int i = 0; i < 10; ++i)
		printf("%d\n",v[i]);

	vector<int>::iterator vit = v.begin();//vector的迭代器

	v.insert(vit + 2, 100);
	vit = vit + 3;
	v.erase(vit);
	
	for (vit = v.begin(); vit != v.end(); ++vit)
		printf("%d\n",*vit);

vector是一個動態數組,支持隨機存取,只要知道位置,很方便直接存取這個位置的元素

在尾部進插入和刪除元素時,性能是比較高,在前端和中部進行插入和刪除,性能相對比較差,要做大量的移位

容器大小可以變化,注意:如果大小發生變化,可能會導致內存重新分配。重分配會有什麼後果?

棧鏈式棧(鏈表) 順序棧(數組)

STL容器並非絕對安全,比如越界等等

T模板函數遇到問題不能return,只能拋異常throw

assert(nullptr);//斷言函數,當參數爲空觸發斷點

C++有接口用類,只有運算符重載和成員用結構,習慣

注意內存重分配後地址變了要返回迭代器

系統vector在刪除時會導致內存重分配

手撕Vector
例子的vector內存是連續(通過new),系統vector內存未必連續

#pragma once

//動態數組

//template<class T>
template<typename T>
class CMyVector
{
	T				*pBuff;//給出一個指針,用來指向一個動態內存
	unsigned int	len;//給一個長度,表示這個動態內存中的元素個數
	size_t			maxSize;//這個動態內存最大的空間大小,也是U_int
public:
	struct MyIterator//這個結構也是一個模板,一個模板內部嵌套定義了一個模板 
	{
		T *pIt;
		MyIterator & operator = (MyIterator const& srcIt)
		{
			pIt = srcIt.pIt;
			return *this;
		}
		bool operator!=(MyIterator const& srcIt) const
		{
			return pIt != srcIt.pIt;
		}
		MyIterator & operator++()//前置
		{
			pIt++;
			return *this;
		}
		MyIterator operator++(int)//後置
		{
			MyIterator tempIt = *this;
			pIt++;
			return tempIt;
		}
		T &operator*()
		{
			return *pIt;
		}
		int operator-(MyIterator const & scrIt) const 
		{
			return pIt - scrIt.pIt;
		}
		MyIterator operator +(int n)
		{
			MyIterator tempIt = *this;
			tempIt.pIt += n;
			return tempIt;
		}
	};
public:
	MyIterator begin()//得到容器的第一個位置
	{
		MyIterator tempIt;
		tempIt.pIt = pBuff;
		return tempIt;
	}
	MyIterator end()//得到容器的最後一個元素的下一個位置
	{
		MyIterator tempIt;
		tempIt.pIt = pBuff + len;
		return tempIt;
	}
public:
	MyIterator insert(MyIterator const& pos, MyIterator const& first, MyIterator const& second)
	{
		MyIterator tempIt = pos;
		int n = second - first;
		for (int i = 0; i < n; ++i)
			tempIt = insert(tempIt, *(first + i));
		return tempIt;
	}
	MyIterator insert(MyIterator const& pos, int n, T const & elem)//在pos處插入n個elem元素
	{
		MyIterator tempIt = pos;
		for (int i = 0; i < n; ++i)
			tempIt = insert(tempIt, elem);
		return tempIt;
	}
	MyIterator insert(MyIterator const& pos, T const& elem)//插入,在pos這個迭代器所指的位置插入一個elem元素
	{
		int index = pos.pIt - pBuff;//通過迭代器位置和容器的首地址進行相減,得到當前的下標 
		if (len >= maxSize)
		{
			maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
			T *tempBuff = new T[maxSize];
			for (size_t i = 0; i < len; ++i)
				tempBuff[i] = pBuff[i];
			if (pBuff != nullptr)
				delete[] pBuff;
			pBuff = tempBuff;
		}
		//移位
		for (size_t i = len; i > index; --i)
		{
			pBuff[i] = pBuff[i - 1];
		}
		pBuff[index] = elem;
		len++;
		MyIterator tempIt;
		tempIt.pIt = pBuff + index;
		return tempIt;
	}
	//注意:自己模擬的動態數組在元素刪除時不會有內存重分配,但是系統vector在刪除時會導致內存重分配
	MyIterator erase(MyIterator const& pos)
	{
		int index = pos.pIt - pBuff;
		for (size_t i = index; i < len - 1; ++i)
		{
			pBuff[i] = pBuff[i + 1];
		}
		len--;
		MyIterator tempIt;
		tempIt.pIt = pBuff + index;
		return tempIt;
	}
	MyIterator erase(MyIterator const& first, MyIterator const& second)
	{
		int n = second - first;
		MyIterator tempIt = first;
		for (int i = 0; i < n; ++i)
			tempIt = erase(tempIt);
		return tempIt;
	}
public:
	CMyVector();
	CMyVector(int n);//有n個用T的默認構造構造的對象,構造進這個容器
	CMyVector(int n, T const& elem);//用n個elem對象,構造進這個容器
	CMyVector(CMyVector const& other);
	~CMyVector();
	void clear();//清除
public:
	size_t size() const;
	size_t capacity() const;//返回容器大小
	bool empty() const;//判斷容器是否爲空
public:
	bool operator==(CMyVector const& srcVector) const;
	bool operator!=(CMyVector const& srcVector) const;
	//作業:實現>,>=,<,<=運算符重載(規則:參照strcmp)
	//作業:實現自身類和參數類交換,要求必須有2個參數
public:
	void assign(int n, T const& elem);//賦值
	void swap(CMyVector & srcVector);//交換
public:
	T at(int index);//返回動態數組中下標爲index的元素
	T operator[](int index);
	T front();//得到容器中的第一個元素,不管容器爲不爲空
	T back();
public:
	void push_back(T const& elem);//往動態數組尾部進行添加數據
	void pop_back();//從動態數組的尾部進入刪除數據
public:
	void resize(int num);//將元素的數量len改爲num這個數量,如果size()變大了,多出來的將用默認構造來創建
	void resize(int num, T const& elem);
	void reserve(int num);//如果容器的容量不足,擴大容量
};

template<typename T>
void CMyVector<T>::reserve(int num)
{
	if (num > maxSize)
	{
		maxSize = num;
		T * tempBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			tempBuff[i] = pBuff[i];
		if (pBuff != nullptr)
			delete[] pBuff;
		pBuff = tempBuff;
	}
}

template<typename T>
void CMyVector<T>::resize(int num, T const& elem)
{
	if (num < 0)
		assert(nullptr);//斷言函數

	if (num > len)
	{
		while (num >= maxSize)
			maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
		T *tempBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			tempBuff[i] = pBuff[i];
		if (pBuff != nullptr)
			delete[] pBuff;
		pBuff = tempBuff;
		for (size_t i = len; i < num; ++i)
			pBuff[i] = elem;
	}

	len = num;
}

template<typename T>
void CMyVector<T>::resize(int num)
{
	if (num < 0)
		assert(nullptr);//斷言函數

	if (num > len)
	{
		while (num >= maxSize)
			maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
		T *tempBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			tempBuff[i] = pBuff[i];
		if (pBuff != nullptr)
			delete[] pBuff;
		pBuff = tempBuff;
	}

	len = num;
}

template<typename T>
void CMyVector<T>::pop_back()
{
	--len;
}

template<typename T>
void CMyVector<T>::push_back(T const& elem)
{
	//1 2 3 4 6 9 13 19
	if (len >= maxSize)
	{
		maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
		T *tempBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			tempBuff[i] = pBuff[i];
		if (pBuff != nullptr)
			delete[] pBuff;
		pBuff = tempBuff;
	}
	pBuff[len++] = elem;
}

template<typename T>
T CMyVector<T>::back()
{
	return pBuff[len - 1];
}

template<typename T>
T CMyVector<T>::front()
{
	return pBuff[0];
}

template<typename T>
T CMyVector<T>::operator[](int index)
{
	return pBuff[index];
}

template<typename T>
T CMyVector<T>::at(int index)//唯一的會主動拋異常的函數
{
	if (index < 0 || index >= len)
		throw "out_of_range";
	return pBuff[index];
}

template<typename T>
void CMyVector<T>::swap(CMyVector & srcVector)
{
	T *tempBuff = pBuff;
	size_t tempLen = len;
	size_t tempMaxSize = maxSize;
	
	pBuff = srcVector.pBuff;
	len = srcVector.len;
	maxSize = srcVector.maxSize;

	srcVector.pBuff = tempBuff;
	srcVector.len = tempLen;
	srcVector.maxSize = tempMaxSize;
}

template<typename T>
void CMyVector<T>::assign(int n, T const& elem)
{
	clear();//重點:清除自身可能原有的動態內存
	if (n > 0)
	{
		len = maxSize = n;
		pBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			pBuff[i] = elem;
	}
}

template<typename T>
bool CMyVector<T>::operator!=(CMyVector const& srcVector) const
{
	return !(*this == srcVector);
}

template<typename T>
bool CMyVector<T>::operator==(CMyVector const& srcVector) const
{
	if (len != srcVector.len)
		return false;
	for (size_t i = 0; i < len; ++i)
	{
		if (pBuff[i] != srcVector.pBuff[i])
			return false;
	}
	return true;
}

template<typename T>
bool CMyVector<T>::empty() const
{
	//return pBuff == nullptr;
	return len == 0;
}

template<typename T>
size_t CMyVector<T>::capacity() const
{
	return maxSize;
}

template<typename T>
size_t CMyVector<T>::size() const
{
	return len;
}

template<typename T>
CMyVector<T>::CMyVector(CMyVector const& other)
{
	len = other.len;
	maxSize = other.maxSize;
	pBuff = nullptr;
	if (len > 0)
	{
		pBuff = new T[maxSize];
		for (int i = 0; i < len; ++i)
			pBuff[i] = other.pBuff[i];
	}
}

template<typename T>
CMyVector<T>::CMyVector(int n, T const& elem)
{
	if (n <= 0)
	{
		pBuff = nullptr;
		len = 0;
		maxSize = 0;
	}
	else
	{
		len = maxSize = n;
		pBuff = new T[maxSize];
		for (size_t i = 0; i < len; ++i)
			pBuff[i] = elem;
	}
}

template<typename T>
CMyVector<T>::CMyVector(int n)
{
	if (n <= 0)
	{
		pBuff = nullptr;
		len = 0;
		maxSize = 0;
	}
	else
	{
		len = maxSize = n;
		pBuff = new T[maxSize];
	}
}

template<typename T>
void CMyVector<T>::clear()
{
	if (pBuff != nullptr)
		delete[] pBuff;
	pBuff = nullptr;
	len = 0;
	maxSize = 0;
}

template<typename T>
CMyVector<T>::~CMyVector()
{
	clear();
}

template<typename T>
CMyVector<T>::CMyVector()
{
	pBuff = nullptr;
	len = 0;
	maxSize = 0;
}

發佈了52 篇原創文章 · 獲贊 5 · 訪問量 4423
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章