vimer linux kernel 爱好者

c++中 vector 和 set 简介

2019-06-17

vector是一个在c++编程中很常见的一个类型,我们更喜欢称之为容器。

vector:basic operator

容器的声明

std::vector<int> v;

那么应该如何将数组的内容复制给容器呢?可以一个个去添加(v.push_back()),不过那样是非常的慢.这里可以直接使用容器的构造函数。

int arrays[] = {1,2,3,4,5};
std::vector v(arrays, arrays+5);

基本操作-迭代器使用

int main() {
    std::vector<int> v = {3, 1, 4};
    auto vi = std::end(v); // find an element after 4
    std::cout << std::showpos << *vi << "\n"; // showpos print "+" or "-"

    sort(v.begin(), v.end());

    std::vector<int>::iterator i; // 使用迭代器
    for (i = v.begin(); i != v.end(); i++){
        std::cout << *i << " "; // 输出1 3 4
    }
    std::cout << std::endl;
    int a[] = {-5, 10, 16};
    auto ai = std::begin(a);
    std::cout << *ai << '\n';
}

output:

+0
+1 +3 +4
-5

二维vector

 std::vector<std::vector<int> >array(3); // 二维数组包含三个向量
    for (int i = 0; i < 3; i++){
        array[i].resize(3); // 设置数组的大小 3*3
    }
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++){
            array[i][j] = i * j; // 使用二维数组
        }
    }
    // 输出
    for(int i = 0 ; i < 3; i++){
        for (int j = 0; j < 3; j++){
            cout << array[i][j] << " ";
        }
        cout << endl;
    }

二维vector按行赋值

https://blog.csdn.net/sinat_41852207/article/details/86668954

构造函数 vector<vector> vec(10, vector(8)); //10行8列,全部初始化为零。 按照上面链接的说法,我可以一行一行的赋值:

// 1. 示例, 一行一行赋值
int a[] = { 1, 2, 3, 4 }; // 把数组的元素放进vector中
vector<int> ivec(a, a + 4);//数组初始化vector,见最下面(也可以不用数组初始化,直接{}初始化vector)
vector<vector<int> > m; // 声明一个二维数组
m.push_back(ivec); // 把ivec(a数组的内容整体放入m,按行)
ivec[0] = 5; ivec[1] = 6; ivec[2] = 7; ivec[3] = 8;
m.push_back(ivec);

ivec[0] = 9; ivec[1] = 10; ivec[2] = 11; ivec[3] = 12;
m.push_back(ivec);

ivec[0] = 13; ivec[1] = 14; ivec[2] = 15; ivec[3] = 16;
m.push_back(ivec);
// 2. 具体赋值某一个值,以某行某列的形式,也就是所谓的直接初始化
vector<vector<char>> board = {
    {'X','.','.','X'},
    {'.','.','.','X'},
    {'.','.','.','X'}
}; // 这样的

我有一个代码,遇到了这样的逻辑,一开始不明白:

class Solution {
public:
    vector<vector<int>> result;
    vector<vector<int>> levelOrder(TreeNode* root) {
        levelOrderHelper(root,0);
        return result;
    }
    void levelOrderHelper (TreeNode* root, int level) {
        ...
        if(level == result.size()) result.push_back(vector<int>()); // 主要是这两行
        result[level].push_back({root->val}); // 不太理解
        ...
    }
};

lower_bound() && uppper_bound()

这个方法是可以返回一个有序的容器类的第一个小于其中元素的索引。其效率为log2(N) + 1.看来真滴该研究下合格stl。高效。

	int myints[] = {10, 20, 30, 30, 20, 10, 10 ,20};
	std::vector<int> v(myints, myints + 8);
	std::sort(v.begin(), v.end()); // 10 10 10 20 20 20

	std::vector<int>::iterator low,up; // HERE,^_^
	low = std::lower_bound(v.begin(), v.end(), 20);
	up = std::upper_bound(v.begin(), v.end(), 20);

	cout << "low_bound at position " << (low - v.begin()) << endl;;
	cout << "up_bound at position " << (up - v.begin()) << endl;

结果:

low_bound at position 3   up_bound at position 6

通过上面的注释也许你已经注意到了,注意这个方法的类型,如果想得到整型的索引,还需要减去v.begin() 才可以得到。

二维动态数组

要求:

Sample Input

2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
Sample Output

5
9

程序如下:

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int row,query,col,temp;
    int **v = NULL;
    cin >> row >> query;
    v = new int*[row];

    for(int i = 0; i < row ; i++){

            cin >> col;
            v[i] = new int[col];
            for (int j = 0; j < col; j++) {
	                cin >> temp;
	                v[i][j] = temp;
	            }
        }
    for (int i = 0; i < query; i++) {
            int t1, t2;
            cin >> t1 >> t2;
            cout << v[t1][t2] << endl;

        }
    for(int i = 0; i < row; i++){
            delete []v[i];
            v[i] = NULL;
        }
    delete []v;
    v = NULL;
    return 0;
}

set

这里set和vector还有具有一定区别的,至少从内置的方法来说,他们的特点差别还是挺大的。那有没有协调array vector和set的方法?我想一定会有的。

上面的这句话后来在后来回顾时发现错的太离谱。set本身具有hashtable的属性,这才是set真正的意义所在。

Declaration

set<int> s;

size

 s.size()

Insert

s.insert(x)

Erase

s.erase(x)

Find an element

这一点也是vector没有的吧?

set<int>::iterator itr = s.find(x);

如果没有找到,则有itr == s.end(), s.end()并不指向最后一个元素,而只是标志结束。 它的操作和map还是很相近的。

unordered_set

不要求具有特殊的顺序,无序的都可以。方法有count,insert等。

#include <string>
#include <unordered_set>
using namespace std;

int main(){
        std::unordered_set<std::string> myset = {"hat", "umberlla", "suit"};
        for (auto& x: {"hat", "sunglass", "suit"}){
                if(myset.count(x) > 0)
                        std::cout << "myset has " << x << std::endl;
                else
                        std::cout << "myset does not have " << x << std::endl;
        }
}

输出:

myset has hat
myset does not have sunglass
myset has suit

Comments

Content