zoukankan      html  css  js  c++  java
  • STL容器操作

    1. 数组

    int a[] = {1, 2, 3, 4, 5, 5};

    2. Vector

    构造函数

    * vector<datatype> a;  //empty vector
    * vector<datatype> b (no of elements, value of each element); //fixed number of elements with default value
    * vector<datatype> c (starting iterator/pointer,ending iterator/pointer); //inserting elements from other data structures
    * vector<datatype> d (name of vector to be copied);
    * vector<vector<datatype> > matrix(no of rows,vector<datatype>(no of coloumn,default value))  //Declaring a 2D array
    

    vector array{1,2,3,4};

    注意: vector<datatype> v[10]; , following declaration isn't a vector with 10 elements but an array of size ten having vector elements.

    methods:

    • at(index) # 等同于 "[]" operator
    • clear()
    • push_back(item)
    • pop_back()
    • front()
    • back()
    • empty()
    • size()
    • resize(n)

    3. List

    methods:

    • front()
    • back()
    • begin()
    • end()
    • rbegin()
    • rend()
    • empty()
    • size()
    • resize()
    • max_size()

    • push_back()
    • push_front()
    • insert() # 任意位置插入
    • pop_back()
    • pop_front()
    • clear()
    • erase() # 删除一个元素或一个区域的元素(两个重载)
    • remove() # 删除链表中匹配值的元素(匹配元素全部删除)
    • remove_if() # 删除条件满足的元素(遍历一次链表),参数为自定义的回调函数

    • reverse()
    • sort()
    • merge()
    • splice()
    • swap()
    • unique()

    3.1. std::forward_list

    std::forward_list 是一个列表容器,使用方法和 std::list 基本类似,因此我们就不花费篇幅进行介绍了。

    需要知道的是,和 std::list 的双向链表的实现不同,std::forward_list 使用单向链表进行实现, 提供了 O(1) 复杂度的元素插入,不支持快速随机访问(这也是链表的特点), 也是标准库容器中唯一一个不提供 size() 方法的容器。当不需要双向迭代时,具有比 std::list 更高的空间利用率。

    4. Tuple

    构造函数

    * tuple <char, int, float> gk;
    * tuple <int,char,float> tup1(20,'g',17.5);
    * tuple <char, int, float> gk2 = make_tuple('a', 10, 15.5);
    
    int len_tuple = tuple_size<decltype(gk)>::value;
    tie(i_val,ch_val,f_val) = tup1;
    

    method:

    • get() # get<0>(gk)
    • make_tuple()
    • tuple_size
    • swap()
    • tie()
    • tuple_cat()

    std::get 除了使用常量获取元组对象外,C++14 增加了使用类型来获取元组中的对象:

    std::tuple<std::string, double, double, int> t("123", 4.5, 6.7, 8);
    std::cout << std::get<std::string>(t) << std::endl;
    std::cout << std::get<double>(t) << std::endl; // 非法, 引发编译期错误
    std::cout << std::get<3>(t) << std::endl;
    

    4.1. 运行期索引

    如果你仔细思考一下可能就会发现上面代码的问题,std::get<> 依赖一个编译期的常量,所以下面的方式是不合法的:

    int index = 1;
    std::get<index>(t);
    

    那么要怎么处理?答案是,使用 std::variant<>C++ 17 引入),提供给 variant<> 的类型模板参数 可以让一个 variant<> 从而容纳提供的几种类型的变量(在其他语言,例如 Python/JavaScript 等,表现为动态类型):

    #include <variant>
    template <size_t n, typename... T>
    constexpr std::variant<T...> _tuple_index(const std::tuple<T...>& tpl, size_t i) {
        if constexpr (n >= sizeof...(T))
            throw std::out_of_range("越界.");
        if (i == n)
            return std::variant<T...>{ std::in_place_index<n>, std::get<n>(tpl) };
        return _tuple_index<(n < sizeof...(T)-1 ? n+1 : 0)>(tpl, i);
    }
    template <typename... T>
    constexpr std::variant<T...> tuple_index(const std::tuple<T...>& tpl, size_t i) {
        return _tuple_index<0>(tpl, i);
    }
    template <typename T0, typename ... Ts>
    std::ostream & operator<< (std::ostream & s, std::variant<T0, Ts...> const & v) {
        std::visit([&](auto && x){ s << x;}, v);
        return s;
    }
    

    这样我们就能:

    int i = 1;
    std::cout << tuple_index(t, i) << std::endl;
    

    4.2. 元组合并

    还有一个常见的需求就是合并两个元组,这可以通过 std::tuple_cat 来实现:

    auto new_tuple = std::tuple_cat(get_student(1), std::move(t));

    4.3. 元祖遍历

    我们刚才介绍了如何在运行期通过非常数索引一个 tuple 那么遍历就变得简单了, 首先我们需要知道一个元组的长度,可以:

    template <typename T>
    auto tuple_len(T &tpl) {
        return std::tuple_size<T>::value;
    }
    

    这样就能够对元组进行迭代了:

    // 迭代
    for(int i = 0; i != tuple_len(new_tuple); ++i)
        // 运行期索引
        std::cout << tuple_index(i, new_tuple) << std::endl;
    

    5. Pair

    构造方法:

    * pair <data_type1, data_type2> Pair_name (value1, value2);
    * pair <data_type1, data_type2> g1;  //default
    * pair <data_type1, data_type2> g2(1, 'a');  //initialized,  different data type
    * pair <data_type1, data_type2> g3(1, 10);  //initialized,  same data type
    * pair <data_type1, data_type2> g4(g3);  //copy of g3
    

    Pair<string, int> xxx = make_pair(key, value);

    methods:

    • operators(=, ==, !=, >=, <=)
    • swap()

    6. Sets / Multiset

    二者的区别:

    Set集合中一个值只能出现一次,而Multiset中一个值可以出现多次。

    int a[] = {1, 2, 3, 4, 5, 5};
    set<int> s2 (a, a + 6);  // s2 = {1, 2, 3, 4, 5}
    set<int> s4 (s3.begin(), s3.end());
    

    method:

    • insert()
    • erase()

    • begin()
    • end()
    • clear()
    • count()
    • empty()
    • find()
    • size()
    • contains (C++20) 检查容器是否含有带特定键的元素

    6.1. std::unordered_set / std::unordered_multiset

    7. Map / Multimap

    std::map<int, string> dict = {
        {0, "ahts"},
        {1, "1234"}
    };
    

    method:

    map<char, int> map_b(map_a.begin(), map_a.end());
    map_a.insert(pair<char, int>('a', 502));
    map_a['a'] = 10;
    cout << map_a['b'];
    cout << map_a.at('b');
    map_a.find('b');
    map_a.erase('b');
    

    7.1. std::unordered_map / std::unordered_multimap

    8. 无序容器

    我们已经熟知了传统 C++ 中的有序容器 std::map / std::set ,这些元素内部通过 红黑树 进行实现, 插入和搜索的平均复杂度均为 O(log(size)) 。在插入元素时候,会根据 < 操作符比较元素大小并判断元素是否相同, 并选择合适的位置插入到容器中。当对这个容器中的元素进行遍历时,输出结果会按照 < 操作符的顺序来逐个遍历。

    而无序容器中的元素是不进行排序的,内部通过哈希表实现,插入和搜索元素的平均复杂度为 O(constant) , 在不关心容器内部元素顺序时,能够获得显著的性能提升

    C++11 引入了两组无序容器: std::unordered_map / std::unordered_multimapstd::unordered_set / std::unordered_multiset

    它们的用法和原有的 std::map/std::multimap/std::set/set::multiset 基本类似, 由于这些容器我们已经很熟悉了,便不再举例了。

    9. Queue / PriorityQueue

    methods:

    • push()
    • pop()
    • front()
    • empty()
    • size()

    A priority queue is a container that provides constant time extraction of the largest element.

    In a priority queue, an element with high priority is served before an element with low priority.

    All insertion / deletion operations takes place in Logarithmic time.

    10. 10. Stack

    methods:

    • push()
    • pop()
    • top() # Returns a reference to the top most element of the stack
    • empty()
    • size()

    11. 11. Bitsets

    https://github.com/kjsce-codecell/standard-library-in-x/blob/master/cpp/containers/bitsets.md

    12. 12. std::array

    看到这个容器的时候肯定会出现这样的问题:

    • 为什么要引入 std::array 而不是直接使用 std::vector

      与 std::vector 不同,std::array 对象的大小是固定的,如果容器大小是固定的,那么可以优先考虑使用 std::array 容器。

      另外由于 std::vector 是自动扩容的,当存入大量的数据后,并且对容器进行了删除操作, 容器并不会自动归还被删除元素相应的内存,这时候就需要手动运行 shrink_to_fit() 释放这部分内存。

    • 已经有了传统数组,为什么要用 std::array

      使用 std::array 能够让代码变得更加“现代化”,而且封装了一些操作函数,比如获取数组大小以及检查是否非空,同时还能够友好的使用标准库中的容器算法,比如 std::sort。

    12.1. 12.1. std::array 的使用

    std::array<int, 4> arr = {1, 2, 3, 4};
    
    arr.empty(); // 检查容器是否为空
    arr.size();  // 返回容纳的元素数
    
    // 迭代器支持
    for (auto &i : arr)
    {
        // ...
    }
    
    // 用 lambda 表达式排序
    std::sort(arr.begin(), arr.end(), [](int a, int b) {
        return b < a;
    });
    
    // 数组大小参数必须是常量表达式
    constexpr int len = 4;
    std::array<int, len> arr = {1, 2, 3, 4};
    
    // 非法,不同于 C 风格数组,std::array 不会自动退化成 T*
    // int *arr_p = arr;
    

    12.2. 12.2. 兼容 C 风格的接口

    void foo(int *p, int len) {
        return;
    }
    
    std::array<int, 4> arr = {1,2,3,4};
    
    // C 风格接口传参
    // foo(arr, arr.size()); // 非法, 无法隐式转换
    foo(&arr[0], arr.size());
    foo(arr.data(), arr.size());
    
    // 使用 `std::sort`
    std::sort(arr.begin(), arr.end());
    
  • 相关阅读:
    gitea (git服务器), 修改配置,更换IP地址
    使用ffmpeg裁剪和合并视频
    linux/windows/Mac平台生成随机数的不同方法
    Android源代码同步脚本(增加设置线程参数)
    小米2S Mk6.0.1 [只能做测试体验,不能使用]
    MultiROM for the XIAOMI MI2S/2C/2! (Kexec HardBoot Enabled with Kexec HardBoot Patch!)
    [PATCH] UBUNTU: SAUCE: (no-up) apparmor: Sync to apparmor3
    [转载]起动service保存android系统log( logcat服务)
    小米2S TWRP 3.0.2-0 最新中文版本Recovery
    centos 64位编译安装 glibc-2.14
  • 原文地址:https://www.cnblogs.com/brt2/p/12982249.html
Copyright © 2011-2022 走看看