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