模拟vector
一、vector---模拟动态数组
#include
1、vector的理解
封装了动态数组的顺序容器,可以简单的认为,vector是一个能够存放任意类型的动态数组,也称为向量
2、vector的特性
1.顺序序列,有序群集,逻辑位置和物理位置连续
2.支持随机存取
3.在末端添加或删除元素方便,性能好
4.头部或者中部插入元素或删除元素需要移位,性能差
5.可以扩容,但是会导致内存重新分配
二、vector里的基本函数
1、构造与析构
1;
vector();//创建一个空vector
2;
vector(int size);//创建一个vector,元素个数为size
3;
vector(int size,const T&t);//创建一个vector,元素个数为size,且值均为t
4;
vector(const vector&other);//复制构造函数
5;
vector(begin,end);//复制[begin,end]区间内另一个数组的元素到vector中
6;
~vector();//删除所有元素,释放内存
2、非变动性函数
1;
int size()const;//返回向量中元素的个数
2;
bool empty()const;//判断向量是否为空,若为空,则向量中无元素
3;
int capaicity()const;//返回当前向量所能容纳的最大元素值,capacity--容量
4;
int max_size()const;//返回最大可允许的vector元素数量值
5;
int capaicity()const;//返会容器的大小
3、赋值操作
1;
void swap(vector&);//交换两个同类型向量的数据
2;
void assign(int n,const T&x=T());//清除容器中的元素,然后n个元素赋值为x
3;
void assign(const_iterator first,const_iterator last);//向量中[fist,last]中元素设置为当前向量元素
4、元素存取
1;
reference at(int pos);//返回pos位置元素的引用,reference--引用
2;
operator[idx];//返回索引idx所标示的元素,不进行范围检查
3;
reference front();//返回首元素的引用
4;
reference back();//返回尾元素的引用
5、迭代器相关
1;
iterator begin();//返回向量头指针,指向第一个元素
2;
iterator end();//返回向量尾指针,指向向量最后一个元素的下一个位置
3;
reverse_iterator rbegin();//反向迭代器,指向最后一个元素
4;
reverse_iterator rend();//反向迭代器,指向第一个元素之前的位置
6、插入和删除
1;
void push_back(const T&x);//向量尾部增加一个元素x
2;
iterator insert(iterator it,const T&x);//在迭代器指向位置处插入元素x
3;
iterator insert(iterator it,int n,const T&x);//在迭代器指向位置处插入n个元素,值为x
iterator insert(iterator it,const_iterator first,const_iterator last);//容器中迭代器指向位置插入另一个相同类型向量的[first,last]间的数据
5;
iterator erase(iterator it);//删除向量中迭代器指向元素,erase-擦去
6;
iterator erase(iterator first,iterator last);//删除容器中[first,last]中的元素
7;
void pop_back();//删除向量中最后一个元素
8;
void clear();//清空向量中的所有元素
9;
void resize(int num);//将元素数量改为num,对空间进行重分配
10;
void resize(int num,T elem);//将元素数量改为num,如果size()变大了。多出来的新元素都用elem来赋值
void reserve(int n);//修改容器的大小
//resize既修改capacity的大小,也修改size的大小
//reserve只修改capacity的大小
7、实际使用
vector<double> v1(10);//调用构造函数
vector<int> v;//动态数组的容器
for (int i = 0; i < 10; i++)
{
v.push_back(i + 1);//尾部插入元素
}
printf("%d
", v[5]);//operator[idx]返回idx所标示的元素,不进行范围检查
v.pop_back();//尾部弹出容器
vector<int>::iterator vit;//定义一个迭代器
vit = v.begin() + 3;//begin()返回的是指向第一个元素的指针,再向后面移动三位,移动到容器下标为3的位置
v.insert(vit, 123);//从迭代器位置进行插入
vit=v.begin();//插入数据后,导致内存重分配,内存地址改变,必须重新让迭代器指向新的容器
vit=vit+5;//vit(迭代器)指向了容器下标为6的元素
v.erase(vit);//iterator erase(iterator it);//删除向量中迭代器指向元素,erase-擦去
//begin函数返回容器中第一个元素的位置(返回迭代器)
//end函数返回容器中最后一个元素的下一个位置(返回迭代器)
for (vit = v.begin(); vit != v.end(); vit++)
{
printf("%d
", *vit);
}
8、二维数组的操作
int row = 5, col = 6;//5行,6列
vector<vector<int>>myvector(row);//定义二维动态数组大小为row行
for (size_t i = 0; i < myvector.size(); i++)//动态二维数组为row行col列,值全为0
{
myvector[i].resize(col);//表示调整容器的大小为col,扩容后的每个元素的值为element,默认为0,就是给每一行指定大小为col
//void resize(int n);//将元素数量改为num
//int size()const;//返回向量中元素的个数
}
for (size_t i = 0; i < myvector.size(); i++)//输出动态二维数组
{
for (size_t j = 0; j < myvector[i].size(); j++)
{
myvector[i][j] = i * 10 + j;
cout << myvector[i][j] << " ";
}
cout << endl;
}
9、sort函数
/*
algorithm库的sort() 排序函数
首先,sort不会用到冒泡排序,时间复杂度过高导致性能太差。SGI STL版本的sort在数据量很大时采用Quick Sort进行分段递归排序。如果分段之后的数据量小于某个门槛值,会改用Insertion Sort这种在数据量很小时性能很好的排序算法。
使用方法:Sort(start,end,排序方法)
Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
想要实现从大到小的排序,可以自己写一个比较函数作为sort的第三个参数
*/
三、模拟vector
//#pragma once
#ifndef __MYVECTOR_H__
#define __MYVECTOR_H__
#include<assert.h>
template<class T>
class CMyVector
{
T* pbuff;
size_t len;
size_t maxsize;
public:
struct MyIterator//迭代器
{
T* pIt;//指向模板这种类型的数据的指针
MyIterator& operator=(MyIterator const&srcIt)
{
pIt = srcIt.pIt;//迭代器的赋值操作
return *this;
}
bool operator!=(MyIterator const&srcIt)
{
return pIt != srcIt.pIt;
}
MyIterator&operator++()//++a
{
pIt++;
return *this;
}
MyIterator operator++(int)//a++
{
MyIterator tempIt = *this;
pIt++;
return tempIt;
}
T operator*()
{
return *pIt;
}
MyIterator operator+(int n)//指针的偏移
{
MyIterator tempIt = *this;
tempIt.pIt += n;
return tempIt;
}
int operator-(MyIterator const&srcIt)//指针相减
{
return pIt - srcIt.pIt;
}
};
public:
MyIterator begin()
{
MyIterator tempIt;
tempIt.pIt = pbuff;//让迭代器里的指针指向动态数组
return tempIt;
}
MyIterator end()
{
MyIterator tempIt;
tempIt.pIt = pbuff + len;
return tempIt;
}
MyIterator insert(MyIterator const &pos, T const &elem)//在迭代器指向位置处插入元素x
{
int index = (int)(pos.pIt - pbuff);//把迭代器位置转为当前从下标0的偏移,防止迭代器失效
if (len >= maxsize)
{
maxsize = maxsize + ((maxsize >> 1) > 1 ? maxsize >> 1 : 1);
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
for (int i = (int)len; i > index; i--)
{
pbuff[i] = pbuff[i - 1];
}
pbuff[index] = elem;
len++;
MyIterator tempIt;
tempIt.pIt = pbuff + index;
return tempIt;//返回的是当前插入元素的位置
}
MyIterator insert(MyIterator const &pos, int n, T const &elem)
{
//MyIterator tempPit = pos;
//for (int i = 0; i < n; i++)
//{
// tempPit = insert(tempPit, elem);//函数重用,效率太低了
//}
//return tempPit;
int index = pos.pIt - pbuff;
if (len + n > maxsize)
{
maxsize = maxsize + ((maxsize >> 1) > 1 ? maxsize >> 1 : 1);
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
for (int i = (int)len + n-1; i > index; i--)
{
pbuff[i] = pbuff[i - n];
}
for (int i = 0; i < n; i++)
{
pbuff[index + i] = elem;
}
len += n;
MyIterator tempIt;
tempIt.pIt = pbuff + index;
return tempIt;
}
MyIterator insert(MyIterator const&pos, MyIterator const &first, MyIterator const &second)
{
MyIterator tempPit = pos;
int n = second - first;//两个指针的间隔距离
for (int i = 0; i < n; i++)
{
tempPit = insert(tempPit, *(first + i));
}
return tempPit;
}
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 tempPit;
tempPit.pIt = pbuff + index;//迭代器指向删除位置
return tempPit;
}
MyIterator erase(MyIterator const&first, MyIterator const &second)
{
int n = second.pIt - first.pIt;
MyIterator tempPit = first;
for (int i = 0; i < n; i++)
{
tempPit = erase(tempPit);
}
return tempPit;
}
public://构造析构
CMyVector();
CMyVector(int n);//带参构造,n表示动态数组的大小
CMyVector(int n, T elem);//带参构造,创建一个vector,元素个数n,大小均为elem
CMyVector(CMyVector const&other);//拷贝构造,就是将一个vector拷贝(复制)到一个新的vector中
~CMyVector();
public://这些都是非变动性函数
size_t size() const;//计算动态数组中有多少个元素
size_t capacity() const;//计算动态数组的最大容量
bool empty() const;//判断动态数组元素是否为空
//运算符重载
bool operator==(CMyVector const &srcVector) const;//比较两个容器里的元素是否相等,元素个数是否相同,相等返回true
bool operator!=(CMyVector const&srcVector) const;//不相等返回true
bool operator>(CMyVector const &srcVector) const;
bool operator>=(CMyVector const&srcVector) const;
bool operator<(CMyVector const &srcVector) const;
bool operator<=(CMyVector const &srcVector) const;
public://变动性函数
void swap(CMyVector&v);//交换两个容器的元素
void assign(int n, const T&x);////清除容器中的元素,然后n个元素赋值为x
void clear();
public://元素的存取
T at(int index);//唯一一个要抛异常的函数,根据索引index,查找容器中的元素
T operator[](int index);//根据索引index,返回容器中的值
T front();//获取容器的第一个元素
T back();//获取容器的最后一个元素
void push_back(T const &elem);//尾插法
void pop_back();//删除最后一个元素
public:
void resize(int num);//将元素数量改为num,对空间进行重分配
void resize(int num, T const &elem);//将元素数量改为num,如果size()变大了。多出来的新元素都用elem来赋值,这种函数基本上都是成对的出现
void reserve(int n);//修改容器的大小,只有当n>maxsize的时候才会修改
};
#endif//只执行一次
template<class T>
CMyVector<T>::CMyVector()
{
pbuff = nullptr;
len = maxsize = 0;
}
template<class T>
CMyVector<T>::CMyVector(int n)
{
if (n <= 0)//这里没有抛异常,而系统的会报错
{
pbuff = nullptr;
maxsize = len = 0;
}
else
{
len = maxsize = n;
pbuff = new T[maxsize];//这里可以是使用T类型的默认构造函数去构造T
/*for (int i = 0; i < len; i++)
{
pbuff[i] = 0;//这个操作是不行的,因为不知道T的类型
}*/
//可以使用memset
memset(pbuff, 0, sizeof(T)*len);
}
}
template<class T>
CMyVector<T>::CMyVector(int n, T elem)
{
if (n <= 0)//这里没有抛异常,而系统的会报错
{
pbuff = nullptr;
maxsize = len = 0;
}
else
{
len = maxsize = n;
pbuff = new T[maxsize];
for (int i = 0; i < len; i++)
{
pbuff[i] = elem;//让数组中的每一个元素都等于elem
}
}
}
template<class T>
CMyVector<T>::CMyVector(CMyVector const & other)
{
len = other.len;
maxsize = other.maxsize;//先让数组大小,元素个数等于other
pbuff = nullptr;
if (maxsize > 0)//证明other里面一定有堆区内存
{
pbuff = new T[maxsize];//这个是给新的vector申请的内存空间
for (size_t i= 0; i < len; i++)
{
pbuff[i] = other.pbuff[i];//将旧的vector中的元素数据拷贝到新的vector中去
}
}
}
template<class T>
CMyVector<T>::~CMyVector()
{
clear();
}
template<class T>
size_t CMyVector<T>::size() const
{
return len;
}
template<class T>
size_t CMyVector<T>::capacity() const
{
return maxsize;
}
template<class T>
bool CMyVector<T>::empty() const
{
//return pbuff == nullptr;
return len = 0;
//有两种可能,一种是:pbuff为空,容器为null。一种是:pbuff不为空,len=0,就是有内存,但是没有元素存在
}
template<class T>
bool CMyVector<T>::operator==(CMyVector const & srcVector) const
{
//strcpm
if (this == &srcVector)//这个是自己和自己比较
return true;
if (len != srcVector.len)//两个容器里的元素个数不相等的话,就返回false
return false;
for (size_t i = 0; i < len; i++)
{
if (pbuff[i] != srcVector.pbuff[i])
{
return false;
}
}
return true;//把两个容器里的元素比较完了,都是相等的,就返回true
}
template<class T>
bool CMyVector<T>::operator!=(CMyVector const & srcVector) const
{
return !(*this == srcVector);//调用了上面的等号重载
}
template<class T>
bool CMyVector<T>::operator>(CMyVector const & srcVector) const
{
size_t minlen = (len < srcVector.len) ? len : srcVector.len;//先出二者中较小的len
for (size_t i = 0; i < len; i++)
{
if (pbuff[i] > srcVector.pbuff[i])
return true;
if (pbuff[i] < srcVector.pbuff[i])
return false;
}
//如果循环完了没有结果,那么就还有三种情况
//1,两个容器相等。2,this.len>srcVector.len。3,this.len<srcVector.len
if (len == minlen)//这一步表示两种情况,两个容器相等返回false,还有this.len<srcVector.len也要返回false
return false;
return true;//this.len>srcVector.len返回true
}
template<class T>
bool CMyVector<T>::operator>=(CMyVector const & srcVector) const
{
return (*this > srcVector || *this == srcVector);
}
template<class T>
bool CMyVector<T>::operator<(CMyVector const & srcVector) const
{
return !(*this >= srcVector);
}
template<class T>
bool CMyVector<T>::operator<=(CMyVector const & srcVector) const
{
return (*this < srcVector || *this == srcVector);
}
template<class T>
T CMyVector<T>::at(int index)
{
if (index < 0 || index >= len)
{
throw "out_of_range";
}
return pbuff[index];
}
template<class T>
T CMyVector<T>::operator[](int index)
{
return pbuff[index];
}
template<class T>
T CMyVector<T>::front()
{
return pbuff[0];
}
template<class T>
T CMyVector<T>::back()
{
return pbuff[len - 1];
}
template<class T>
void CMyVector<T>::push_back(T const & elem)
{
if (len >= maxsize)
{
maxsize = maxsize + ((maxsize >> 1) > 1 ? maxsize >> 1 : 1);
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
pbuff[len++] = elem;
}
template<class T>
void CMyVector<T>::pop_back()
{
len--;
}
template<class T>
void CMyVector<T>::resize(int num)
{
if (num < 0)
assert(NULL);
if (num > maxsize)
{
maxsize = num;
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
//上面是只给len个元素赋了值,num-len个元素是用T的默认类型去构造的值
len = num;
}
template<class T>
void CMyVector<T>::resize(int num, T const & elem)
{
if (num < 0)
assert(NULL);
if (num > maxsize)
{
maxsize = num;
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
if (num > len)
{
for (size_t i = len; i < num; i++)
pbuff[i] = elem;
}
len = num;
}
template<class T>
void CMyVector<T>::reserve(int n)
{
if (n > maxsize)
{
maxsize = n;
T* temp = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];
}
if (pbuff)
delete[]pbuff;
pbuff = temp;
}
}
template<class T>
void CMyVector<T>::swap(CMyVector & v)
{
T* tempbuff = pbuff;
size_t templen = len;
size_t tempmaxsize = maxsize;
pbuff = v.pbuff;
len = v.len;
maxsize = v.maxsize;
v.pbuff = tempbuff;
v.len = templen;
v.maxsize = tempmaxsize;
}
template<class T>
void CMyVector<T>::assign(int n, const T & x)
{
clear();
len = maxsize = n;
if (maxsize > 0)
{
pbuff = new T[maxsize];
for (size_t i = 0; i < len; i++)
{
pbuff[i] = x;
}
}
}
template<class T>
void CMyVector<T>::clear()
{
if (pbuff)
delete[]pbuff;
pbuff = nullptr;
maxsize = len = 0;
}