【C++STL容器篇之vector】

335 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

vector 容器

功能:vector数据结构和数组相似,也称为单端数组

与普通数组的区别

不同之处在于数组是静态空间,而vector是动态扩展
动态扩展:
    不是在原来的空间之后续接新空间,而是找更大的内存空间,将原数据拷贝到新空间,释放原空间  
    vector容器的迭代器是支持随机访问的迭代器

构造函数

【函数原型】:

vector<T> v; 采用模板实现类实现,默认的构造函数
vector(v.begin(),v.end()); 将v[begin(),end()]区间中的元素拷贝给本身
vector(n,elem); 构造函数将n个elem拷贝给本身
vector(const vector &v); 拷贝构造函数

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v1; // 无参构造
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    printVector(v1);

    vector<int> v2(v1.begin(), v1.end()); // 将v1[a,b]区间中的元素拷贝给v2
    printVector(v2);

    vector<int> v3(5, 1); // 将 5个1 拷贝到 v3
    printVector(v3);

    vector<int> v4(v3); // 拷贝构造
    printVector(v4);
}
int main()
{
    test01();
    return 0;
}

vector赋值操作

【函数原型】:

vector &operator=(const vector &v); 重载符号操作
assign(begin,end); 将[begin,end]区间中的元素拷贝赋值给本身
assign(n,elem); 将n个elem赋值给本身

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    printVector(v1);

    vector<int> v2;
    v2 = v1;
    printVector(v2);

    vector<int> v3;
    v3.assign(v1.begin(), v1.end());
    printVector(v3);

    vector<int> v4;
    v4.assign(10, 1);
    printVector(v4);
}

int main()
{
    test01();
    return 0;
}

vector容量和大小

【函数原型】:

empty(); 判断容器是否为空
capacity(); 容器的容量
size(); 返回容器中元素的个数
resize(int num); 重新指定容器的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
resize(int num,elem); 重新指定容器的长度为num,若容器变长,则以elem值填充新位置,若容器变短,则末尾超出容器长度的元素被删除

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v;
    for (int i = 0; i < 50; i++)
    {
        v.push_back(i);
    }
    printVector(v);
    if (v.empty())
    {
        cout << "v 为空" << endl;
    }
    else
    {
        cout << "v 非空" << endl;
        cout << "v 的容量:" << v.capacity() << endl;
        cout << "v 当前的大小为:" << v.size() << endl;

        // resize 重新指定大小,
        // 若指定的更大,默认使用0来填充,可以利用重载版本替换默认填充
        v.resize(15, 10);
        printVector(v);
    }
}

int main()
{
    test01();
    return 0;
}

【小结】

  • 判断是否为空 --- empty
  • 返回元素个数 --- size
  • 返回容器容量 --- capacity
  • 重新指定大小 --- resize
- 对于普通的数组,一旦定义了大小就不能改变了。对于动态数组,就不用考虑初始时的数组大小,因为可以随意往动态数组中添加元素。
- vector的底层实现也是普通数组,vector的大小有两个维度,一个是size ,一个是capcity 。 
- size是数组元素的个数,capcity是vector底层数组的大小,capcity不一定等于size。
- 在进行插入的数据的时候,如果size已经大于capcity,那么capcity会进行扩容,而且是成倍扩容,但是对外暴露的size其实就仅仅是 size+1

vector插入与删除

【函数原型】:

push_back(ele); 尾部插入元素ele
pop_back(); 删除最后一个元素
insert(const_iterator pos,ele); 在迭代器指向位置pos插入元素ele
insert(const_iterator pos,int count,ele); 迭代器指向位置pos插入count个元素ele
erase(const_iterator pos); 删除迭代器指向的元素
erase(const_iterator start,const_iterator end); 删除迭代器从start到end之间的元素
clear(); 删除容器中的所有元素

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{

    if (v.empty())
    {
        cout << "v 为空" << endl;
    }

    else
    {
        cout << "v.capacity = " << v.capacity() << endl;
        cout << "v.size = " << v.size() << endl;

        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
}
void test01()
{

    vector<int> v;
    // 在尾部插入新元素
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    printVector(v);

    // 在尾部删除元素
    v.pop_back();
    printVector(v);

    // 在指定位置插入元素
    v.insert(v.begin(), 10); // 在开始的位置插入10
    printVector(v);
    v.insert(v.begin(), 2, 100); // 在开始的位置插入两个100
    printVector(v);

    // 删除元素
    v.erase(v.begin()); // 将开始位置的元素删除
    printVector(v);

    // 删除所有元素
    // v.clear();
    v.erase(v.begin(), v.end()); // 清空所有数据
    printVector(v);
}

int main()
{
    test01();
    return 0;
}

【小结】

  • 尾插 : push_back()
  • 尾删 : pop_back()
  • 插入 : insert()
  • 删除 : erase()
  • 清空 : clear()

vector 数据读取

【函数原型】:

at(int idx); 返回索引idx所指向的元素
operator[idx]; 返回索引idx所指向的元素
front(); 返回容器中的第一个元素
back(); 返回容器中的最后一个元素

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    cout << "使用 [] 获取元素值:";
    for (int i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }
    cout << endl;
    printVector(v);

    // 根据索引取值
    int idx = 1;
    int idxValue = v.at(idx);
    cout << "v.at(" << idx << ") = " << idxValue << endl;

    cout << "v.front = " << v.front() << endl;
    cout << "v.back = " << v.back() << endl;
}

int main()
{
    test01();
    return 0;
}

vector 互换容器

实现两个容器内的元素互换

【函数原型】:

swap(v); 将v于本身的元素互换

【demo】:

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<int> &v)
{

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{

    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }

    vector<int> v2;
    for (int i = 5; i < 10; i++)
    {

        v2.push_back(i);
    }
    cout << "交换前:" << endl;
    printVector(v1);
    printVector(v2);

    v1.swap(v2);
    cout << "交换后:" << endl;
    printVector(v1);
    printVector(v2);
}

int main()
{
    test01();
    return 0;
}

vector 预留空间

减少vector在动态扩展容量时的扩展次数

【函数原型】:

reverse(int len); 容器预留len个元素长度,预留位置不初始化,元素不可访问

【demo】:

#include <iostream>
#include <vector>

using namespace std;
void printVector(vector<int> &v)
{

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v;
    // 预留空间
    v.reserve(10000);

    int num = 0;
    int *p = NULL;
    for (int i = 0; i < 10000; i++)
    {
        v.push_back(i);
        if (p != &v[0])
        {
            p = &v[0];
            num++;
        }
    }

    cout << "num:" << num << endl;
}

int main()
{
    test01();
    return 0;
}