STL学习(3):vector

STL学习网址:

vector是将元素放到动态数组中加以管理的容器。vector容器可以随机存取元素,也就是说支持[]运算符和at方式存取。

  • vector在尾部添加或者移除元素非常快,在中间操作非常耗时,因为它需要移动元素

vector的基本用法

既然vector是容器,那么就可以向这个容器添加删除元素。

基本用法:

  • front()返回头部元素的引用,可以当左值
  • back()返回尾部元素的引用,可以当左值
  • push_back()添加元素,只能尾部添加
  • pop_back()移除元素,只能在尾部移除

初始化

第一种:用数组来初始化

    int a[10] = {0};
    vector<int> my_list1(a, a+10);

第二种:直接初始化

vector<int> my_list1(10);

 

    //定义一个vector容器
    vector<int> v1;

    //插入元素(尾部插入)
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);

    //迭代器遍历打印
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

    //修改头部元素的值(front()返回是引用,可以当左值)
    v1.front() = 44;

    //输出头部元素
    cout<<"头部元素:"<< v1.front() << endl;

    //修改尾部的值(back()返回是引用,可以当左值)
    v1.back() = 99;

    //输出尾部元素
    cout << "尾部元素" << v1.back() <<endl;

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

    //迭代器遍历打印
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

vector的遍历

vector的遍历有多种方式,可以根据[]或者迭代器遍历。

需要主要的是:

  • []方式,如果越界或出现其他错误,不会抛出异常,可能会崩溃,可能数据随机出现
  • at方式,如果越界或出现其他错误,会抛出异常,需要捕获异常并处理
  • 迭代器提供了逆向遍历,可以通过迭代器来实现逆向遍历,当然上面两种方式也可以
int main(int argc, const char * argv[]) {
    
    //创建vector
    vector<int> v1;
    
    //插入元素
    for (int i = 0; i < 10; i++) {
        v1.push_back(i);
    }
    
    //遍历-[]取值
    for (int i = 0; i < v1.size(); i++) {
        cout << v1[i] << " ";
    }
    cout << endl;
   
    //遍历-at取值
    for (int i = 0; i < v1.size(); i++) {
        cout << v1.at(i) << " ";
    }
    cout << endl;

    //遍历-迭代器遍历
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
    
    //遍历-迭代器逆向遍历
    for (vector<int>::reverse_iterator it = v1.rbegin(); it != v1.rend(); it++) {
        cout << *it << " ";
    }
    cout << endl;
    
    //测试越界
    cout << "[]越界:" << v1[20] << endl;      //不会抛出异常,可能会崩溃,可能会乱码
    cout << "at越界:" << v1.at(20) << endl;   //会抛出异常,需要捕获异常
    
    return 0;
}

vector的push_back强化

push_back是在当前vector的内存末尾拷贝元素进入容器。注意这个地方可能产生浅拷贝,所以容器中的对象要支持拷贝操作。另外,如果vector初始化了个数,而不初始化具体的值,push_back也只会在最后面追加。

   //初始化10个元素的容器
    vector<int> v(10);

    //打印容器大小
    cout << v.size() << endl;

    //push_back添加元素
    v.push_back(100);

    //打印容器大小
    cout << v.size() << endl;

    //遍历后的结果是  0 0 0 0 0 0 0 0 0 0 100
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

vector的元素删除

vector的删除,是根据位置进行删除,如果想要删除某个元素,需要找到当前元素的迭代器位置,再进行删除。

iterator erase(iterator it);		            //删除向量中某一个元素
iterator erase(iterator first, iterator last)	//删除向量中[first,last)中元素
void pop_back();			                    //删除向量中最后一个元素
void clear();				                    //删除向量中所有元素

erase(iterator)函数,删除后会返回当前迭代器的下一个位置。

    //1 创建容器并初始化
    vector<int> v1(10);
    for (int i = 0; i < v1.size(); i++) {
        v1[i] = i;
    }
    
    //2 区间删除
    //--2.1 删除前3个元素
    v1.erase(v1.begin(), v1.begin() + 3);
    
    //--2.2 删除指定位置的元素
    v1.erase(v1.begin() +3);
    
    //3 根据元素的值进行删除,删除值为2的元素
    v1.push_back(2);
    v1.push_back(2);
    vector<int>::iterator it = v1.begin();
    while (it != v1.end()) {
        if (*it == 2) {
            it = v1.erase(it);   //删除后,迭代器指针会执行下一个位置并返回。
        }else{
            it++;
        }
    }
    
    //4 遍历打印
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

vector的插入元素

vector提供了insert函数,结合迭代器位置插入指定的元素。

如果迭代器位置越界,会抛出异常。

    //初始化vector对象
    vector<int> v1(10);
    
    //在指定的位置插入元素10的拷贝
    v1.insert(v1.begin() + 3, 10);
    
    //在指定的位置插入3个元素11的拷贝
    v1.insert(v1.begin(), 3, 11);
    
    //遍历
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

总之,增加新元素时,如果超过当前的容量,则容量会自动扩充2倍,如果两倍容量仍不足,就扩大至足够大的容量。本图是直接在原空间基础上画的新增空间,其实要复杂得多,包括重新配置、元素移动、释放原始空间的过程。因此对vector容器而言当增加新的元素时,有可能很快完成(直接存在预留空间中),有可能稍慢(扩容后再放新元素);对修改元素值而言是较快的;对删除元素来说,若删除尾部元素较快,非尾部元素则稍慢,因为牵涉到删除后的元素移动。

综合操作示例

利用vector编一个学生信息[学号(它是关键字)、姓名、性别、出生日期]管理类,有添加函数、查询函数(依据学好号查询),显示函数(对查询结果完成显示)。并编制测试函数测试。

(1)基本思想是要有一个基本信息类及该基本信息的集合类。对本题而言,基本信息类是学生类Student,集合类是StudCollect。 (2)Student类中定义了4个基本的成员变量及屏幕显示函数Display()。StudCollect定义了一个成员变量vector<Student> v,可看出本类是对学生集合对象的一个管理类,是实现集合管理类的根本所在。该类主要定义了Add(Student&  s)函数及Student *Find(string  strNO)函数。

#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Student		//学生类
{
public:
string m_strNO;		//学号
	string m_strName;	//姓名
	string m_strSex;	//性别
	string m_strDate;	//出生日期
public:
	Student(string strNO, string strName,string strSex,string strDate):
	  m_strNO(strNO),m_strName(strName),m_strSex(strSex),m_strDate(strDate){}
	  void Display(){
		  cout <<m_strNO<<"\t"<<m_strName<<"\t"<<m_strSex<<"\t"<<m_strDate<<endl;
	  }
};
class StudCollect
{
	vector<Student> m_vStud;
public:
	void Add(Student& s){
		m_vStud.push_back(s);
	}
	Student* Find(string strNO){
		bool bFind = false;
		for(int i=0; i<m_vStud.size(); i++)
		{
			Student& s = m_vStud.at(i);
			if(s.m_strNO == strNO)
			{
				bFind = true;
				break;
			}
		}
		Student *s = NULL;
		if(bFind) 
			s = &m_vStud.at(i);
		return s;
	}
};
void main()			//仿真测试程序
{
	Student s1("1001","zhangsan","boy","1985-10-10");
	Student s2("1002","lisi","boy","1984-6-10");
	Student s3("1003","wangwu","boy","1985-11-15");
     StudCollect s;
     s.Add(s1),s.Add(s2),s.Add(s3);
     Student *ps = s.Find("1002");
     if(ps)
	ps->Display();
}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值