小言_互联网的博客

走近STL - Vector,再次见面

294人阅读  评论(0)

在Leecode上做了一些vector的题目,有了新的感悟,所以重新对这篇文章进行一次脱胎换骨式的修改。

Vector是STL中一个很常用的容器。
作用:Vector可以理解为是一个可以存放 任意的统一种类的数据的动态数组

能来看的对vector应该是有了解的,闲话不多说。

1、Vector,再次见面,还请多多关照

Vector的数据结构与array非常相似,不同的地方在于array是静态的,一旦确定了范围之后便不能改变(不定长数组零担别论)。
要换个更大的空间是比较麻烦的,一切都得自己手动来。
Vector是动态分配空间的,相对比较友好,如果需要扩容的话它的内部机制会自己去处理。


2、Vector基本函数使用

  1. 创建
#include<vector>

vector<int>test;	//初始化一个Vector实例,用于存放int型数据,实例名字叫test

vector<int>test2 = test;	//以test1为标准创建test2

再看一个vector<int>test3(10);
//创建一个vector容器,大小为10,内容默认置空 //不是很建议这种做法啊,因为我今天使用这种初始化方式出了bug,我往里面插成段的值的时候只能插入第一个,后面就无法插入了。
//再说了,你不用自己分配空间,STL都给你安排的好好的。

当然,初始化方式千千万,放多了反而让人眼花缭乱,会基本的最实用的够了。

  1. 插入元素
test.insert(test.begin()+i,a);	//在第i个元素前插入a

test.insert(test.begin()+i,te2.begin(),te2.end());	
//插入一段相同数据类型数据,第一个参数放插入位置(指针/迭代器形式),第二三个参数放待插入元素起始位置

test.push_back(a);	//往尾部插入
  1. 删除元素
test.erase(test.begin());
test.erase(test.begin(),test.begin()+5);//删除区间(第一个元素到第五个元素)

test.clear();	//清空

test.pop_back();	//删除尾部元素

删除呢,还有个比较灵活的方式:

test.erase(it);	//这个it是迭代器

关于删除有一个必须·要注意的点:不要在foreach的时候进行删除操作,如果你一定要在遍历的时候进行删除,你最好看一下下一行那个链接。

对于增删,对于初学者有一个坑在等着,不过我已经帮你们踩平了,点进来看看

  1. 遍历元素
    当然,你可以使用数组下标形式访问元素,因为vector重载了 [] 操作,不过不建议。虽然是很方便,但是有诸多限制,要是随便就任你操作数据,那人家封装起来干什么?
    我们应该养成使用下面这种迭代器访问的方式。
vector<int>::iterator it;	//初始化一个vector<int>类型的迭代器
for(it = test.begin();it!=test.end();it++)	//从头遍历到尾
{
	cout<<*it<<endl;	//取出内容
}

关于迭代器还需要知道的是:vector的迭代器支持前后向,及重载了 +,—,++,-- 操作。

还有一个叫at()的函数,这个好用。

test.at(2);		//用这个比直接用下标要好的地方在于它会检测越界
  1. 头尾指针
    这四个函数的区别要清楚:begin()、end()、front()、back()。我喜欢称它们为头尾指针。
    我也不知道为什么有人要就这些区别长篇大论。
begin():指向容器的第一个元素的地址。
front():指向容器的第一个元素的值。
end():和begin()配套
back():和front()配套
  1. 容器容量
test.size();	//容器已存入数据量
test.capacity();	//容器还能存多少数据量

其实不用担心容器不够大,容量要满的时候它会自己扩容。

  1. 排序
#include<algorithm>
/*test.*/sort(test.begin(),test.end());	//从头到尾,默认从小到大排序
这里要非常注意,前面那个test. 被我注释掉了,因为sort是属于算法范畴,不是容器的类方法。

//一般排序都是要自定义排序的:
bool Comp(const int &a,const int &b)
{
    return a>b;
}
sort(test.begin(),test.end(),Comp);	//这样就降序排序。 
  1. 其他

swap(test,test2);	//交换test和test2中的数据

test.resize(20);	//重置大小

reverse(test);		//元素翻转

如果要问为什么没有 “修改数据的部分”,参见第四点“遍历数据”。


10、unique()函数

这个函数用来清理容器中的重复项,但前提是容器经过排序了。
而且,它不提供删除操作,只是把重复项移到容器后面的部分,所以直接size()的话大小是不会变的。
如果要清理重复项,这样:nums.erase(unique(nums.begin(),nums.end()),nums.end());


最后再提一下两个头文件:

#include<vector>	//vector类相关
#include<algorithm>	//容器算法

vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。

特别注意:

使用vector需要注意以下几点:

1、如果你要表示的向量长度较长(需要为向量内部保存很多数),容易导致内存泄漏,而且效率会很低;

2、Vector作为函数的参数或者返回值时,需要注意它的写法:

double Distance(vector&a, vector&b) 其中的“&”绝对不能少!!!


Vector的数据结构

所谓动态增添大小,并不是在原有空间之后再开辟空间,显然那也不太现实。
而是以原大小的两倍大小寻找一块新空间,将内容真实的拷贝过去,然后释放原空间。
不过就算删除元素过半也不会将内存放出来。

但是,需要牢记的一点是:对于Vector的一切操作,一旦引起空间的重新分配,那么指向原有空间的迭代器将会全部失效。

关于这点,我也做了一个测试代码:
可测可不测,结果我都注释好了

#include <iostream>

#include<vector>

using namespace std;

int main()
{
    vector<int> vec1;
    //vector<int>::iterator it1 = vec1.begin();
    //放这里试试
    vec1.push_back(1);
     cout<<"left size :"<<vec1.capacity()<<endl;	//1
    vec1.push_back(6);
     cout<<"left size :"<<vec1.capacity()<<endl;	//2
    vec1.push_back(5);
     cout<<"left size :"<<vec1.capacity()<<endl;	//4
    vec1.push_back(4);
     cout<<"left size :"<<vec1.capacity()<<endl;	//4
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    //vector<int>::iterator it1 = vec1.begin();
    //放这里试试
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(2);
     cout<<"left size :"<<vec1.capacity()<<endl;	//16

    vector<int>::iterator it1 = vec1.begin();
//这个循环用于在6之后插入4
    while (it1 != vec1.end())
    {
        if (3 == *it1)
        {
            vec1.insert(it1+1, 4);
            cout<<"insert:"<<*it1<<endl;
        }
        it1++;
    }

//执行完插入操作,将值全部打印
    for(it1 = vec1.begin();it1!=vec1.end();it1++)
    {
        cout<<*it1<<endl;
    }
    cout<<"it1over"<<endl;

//准备执行对元素‘3’的删除
    vector<int>::iterator it2 = vec1.begin() ;
    while (it2 != vec1.end())
    {
        if (3 == *it2)
        {
             //it2 =vec1.erase(it2);
             vec1.erase(it2);	//这里有没有都一样,都指向删除之后的那个位置
             cout<<"delete:"<<*it2<<endl;
        }
        else
            it2++;
    }
//执行完删除操作,将容器数据进行打印
    for(it2 = vec1.begin();it2!=vec1.end();it2++)
    {
        cout<<*it2<<endl;
    }
    cout<<"it2over"<<endl;

//为测试方便,这里直接清空Vector,看看它放不放空间
    vec1.clear();
    cout<<"clear left size :"<<vec1.capacity()<<endl;	//16
    return 0;
}

这一章就先到这里吧


转载:https://blog.csdn.net/qq_43762191/article/details/105738512
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场