使用 vector


如果需要线性、长度可变的数据容器,可以使用vector,这需要包含vector标头文件:

#include <vector>

技术上来说,vector是个类模版(class template),不过使用上,只需要知道,vector可以装载指定类型的数据。例如,创建一个可装载intvector<int>

vector<int> number;

这会创建一个空的vector<int>,如果想在创建容器时装载指定的元素,可以使用清单初始化化(list initialization)或者初始化器(Initializer):

vector<int> number = {10, 20, 30};
vector<double> score{85.5, 78.2, 63.0};

想要顺序地遍历vector中的元素,可以使用 for range 语法,例如:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> number = {10, 20, 30};

    for(auto n : number) {
        cout << n << endl;
    }

    return 0;
}

透过[]指定索引可以访问特定位置的元素,例如:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> number = {10, 20, 30};

    for(int i = 0; i < number.size(); i++) {
        cout << number[i] << endl;
    }

    return 0;
}

可以从vectorsize方法得知元素的个数,empty方法可以得知是否为空,front方法可以获取第一个元素,back方法可以获取最后一个元素,想要新增元素,可以使用push_backinsert方法,想取出最后一个元素可以用pop_backclear可以清空vector等。

底下会显示 9 到 0 的数字:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> number;

    for(int i = 0; i < 10; i++) {
        number.push_back(i);
    }

    while(!number.empty()) {
        int n = number.back();
        number.pop_back();
        cout << n << endl;        
    }

    return 0;
}

创建vector时可以指定初始化的长度,每个元素会被初始化为指定类型的空值,例如底下会创建长度为 10 的vector,元素初值都是 0:

vector<int> v1(10);

也可以在指定初始化长度的同时,指定每个元素的初值,例如底下会创建长度为 10 的vector,元素初值都是 5:

vector<int> v1(10, 5);

vector可以使用另一个vector作为实参来构造,例如以v1作为实参来构造v2

vector<int> v1 = {10, 20, 30};
vector<int> v2(v1);

这会将vector的元素复制给被指定的vectorvector可以指定给另一vector,这也会将vector的元素复制给被指定的vector,例如:

vector<int> v1 = {10, 20, 30};
vector<int> v2 = v1;

若要指定来源vector的某个范围构造出新的vector,必须指定起始位置的iterator与结束位置的iterator,例如底下从索引 2 开始遍历至尾端的元素,用以创建新的vector

vector<int> v1 = {10, 20, 30, 40, 50};
vector<int> v2(v1.begin() + 2, v1.end()); // 包含 30, 40, 50

在上头,beginend方法分别返回起始位置的vector<int>::iterator与结束位置的vector<int>::iterator,可以把它们看成代表首个元素与最后一个元素的位置,对它们进行+-运算,表示元素的位移量,操作上很像指针,至于是不是真的指针,要看底层的实现而定。

就 API 的设计来说,不建议将beginend方法的返回值看成是指针,而建议将之看成迭代器(iterator),这些迭代器重载了相关的运算符,令其看来像是指针操作,因为容器相关的程序库,为基于这类操作协定,令提供的 API 具有通用性。

若要使用迭代器来遍历元素,例如,先前的 for range 语法,若要使用beginend方法,可以搭配for循环,例如:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> number = {10, 20, 30};

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

    return 0;
}

类似地,若要使用数组的元素来构造vector,可以透过以下的方式:

int number[] = {10, 20, 30, 40, 50};
vector<int> v(begin(number) + 2, end(number)); // 包含 30, 40, 50

如果打算对vector进行排序、寻找、反转等操作,可以使用包含algorithm标头文件:

#include <algorithm>

一些操作会使用到迭代器,例如下面这个程序直接示范了排序、寻找、反转等操作:

#include <algorithm>
#include <iostream> 
#include <vector>
using namespace std; 

int main() { 
    vector<int> number = {30, 12, 55, 31, 98, 11, 41, 80, 66, 21};

    // 排序 
    sort(number.begin(), number.end());
    for(auto n : number) {
        cout << n << " ";
    }
    cout << endl;

    cout << "输入搜寻值:";
    int search = 0;
    cin >> search;

    vector<int>::iterator it = find(number.begin(), number.end(), search);
    cout << (it != number.end() ? "找到" : "没有")
         << "搜寻值" 
         << endl;

    // 反转 
    reverse(number.begin(), number.end());
    for(auto n : number) {
        cout << n << " ";
    }
    cout << endl;

    return 0; 
}

执行结果:

11 12 21 30 31 41 55 66 80 98
输入搜寻值:22
没有搜寻值
98 80 66 55 41 31 30 21 12 11




展开阅读全文