新手向:stl常用容器介绍

1、容器的基本概念

    stl库为许多常用的数据结构提供了通用的模板, 我们叫它容器。顾名思义, 容器可以用来储存数据, 其中的数据可以是预定义类型, 如int、 double, 也可以是自定义类型。容器类中的元素自动申请内存, 不需要new和delete。添加了相应的头文件后容器就可以直接使用了。声明一个容器的一般方法如下:

容器类型<元素数据类型(可能有多个, 如map)>容器名称

例如声明一个类型为不定长数组vector, 元素类型为int, 名称为v的容器:

vector<int>v;

为了方便访问容器中的元素, c++提供了一个叫做迭代器的对象,迭代器是个所谓的复杂的指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。使用的时候像指针一样用就行了。

声明一个迭代器地方法如下:

容器类型<元素数据类型>::iterator 迭代器名称

大多数容器都提供了begin()和end()方法, 返回指向容器第一个元素和容器末尾(注意这里是容器最后一个元素的下一个位置, 也就是说.end()所返回的迭代器是没有指向的元素的。如果解引用它就会出现问题)的迭代器。有了迭代器我们就可以很方便地遍历一个容器,例如遍历一个vector

for(vector<int>::iterator it = v.begin(); it != v.begin(); it++)
{
   //要进行的操作
}

c++11中提供了更方便的方法

for(auto x : 容器名称)
{
  //要进行的操作
}
其中x是一个变量, 它的类型和容器中元素相同, 在每次循环中会把访问到的元素的值赋给它。如果是只读的操作直接把它当成容器中的元素来用就可以了。如果要修改容器中的元素的话, 对它的操作是不会改变容器中的元素的, 这时候for循环中要声明成auto & x。注意如果要对容器中的元素有增删就不能使用序列for循环, 因为这会使原来的首尾迭代器失效。

1)vector

    vector是一个不定长的数组, 它重载了[]运算符,支持随机访问。

    下面是vector的几种初始化方法

vector<int> v;//直接初始化一个空vector
vector<int> v2(v)//创建一个v的副本
vector<int>v3(n, x)//v3包含了n个值为x的元素
vector<int> v4 = {1, 2, 3}; //v4包含了初始值列表中的元素

    vector常用的方法有:

    begin() 返回首迭代器

    end()  返回尾迭代器 

    push_back() 在容器尾部添加一个元素,参数是要添加的元素。

    erase()删除容器中的元素, 参数是指向该元素的迭代器。返回要删除元素下一个位置的迭代器。由于删除后会使原来的迭代器失效, 我们在遍历容器并删除某些元素时可以这样写:

//删除一个vector中小于10的数
vector<int> v = {1, 10, 20, 5, 50};
for(auto it = v.begin; it != v.end;)
{
   if(*it >= 10) it++;
   else it = v.erase(it);
}

 它的一个重载是传入两个迭代器来删除这一段的所有元素    

    vector<int>v{1, 2, 3, 4};
    v.erase(v.begin(), v.begin() + 2);//删除v的前三个元素

size() 返回容器的大小。它由首尾迭代器相减得到,时间复杂度是O(1), 我们可以把它当成一个常数来用。

clear() 清空容器

比如栈和队列两个基本的数据结构, stl库提供了实现。栈和队列的概念相必大家都知道, 这里就不提了。

 2)queue(队列)

   queue<int>q; 声明一个队列
   q.front();//返回队首
   q.back(); //返回队尾
   q.push(1);//入队
   q.pop();//出队
   q.empty(); //判断队列是否为空, 是的话返回true
   q.size(); //返回队列元素个数

  3)stack(栈)

    stack<int>s; // 申明一个栈
    s.push(1); //将元素入栈
    s.pop(); //将栈顶出栈
    s.top(); //返回栈顶元素
    s.empty();//判断栈是否为空
    s.size();//返回栈中元素个数

栈和队列没有clear方法, 如果想清空栈或者队列我们可以这样做

    queue<int>q;
    while(!q.empty()) q.pop(); // 一直将队尾出队, 直到队列为空
    //或者
    queue<int> p;
    q = p; //将一个空队列赋值给要清空的队列
    //栈的话也一样
    stack<int>s;
    while(!s.empty()) s.pop();
    
    stack<int> s2;
    s = s2;


  4)set(集合)

    实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。平衡二叉检索树使用中序遍历算法,检索效率高于vector和list等容器(log(n)),另外使用中序遍历可将键值按照从小到大遍历出来。构造set集合主要目的是为了快速检索,不可直接去修改键值。集合中的元素是不会出现重复的, 如果插入重复的元素, 集合不会发生改变

     insert() 插入一个元素, 由于二叉树要重新平衡, 复杂度是log(n)

     erase() 删除元素, 复杂度也是log(n)

     find() 在容器中查找某个元素, 如果找到返回指向这个元素的迭代器, 如果没找到返回尾迭代器。

     count() 判断某个元素是否存在, 若存在返回true

    lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器

    还有一些大多数容器通用的方法, 其用法也和之前提到的类似

    clear()

    size()

    begin()

    end()

5)map

   Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

    map中的元素是pair。 是一个键(key)到值(value)的映射, key和value可以是自定义的任何类型, 不过key需要是重载了小于运算符的类型。value的值是可以改变的而key不能改变。map重载了[]运算符, 可以通过key来找到value。在通过迭代器来访问map中的元素时。用->first来访问key, 通过->second来访问value。 

定义一个map时, 必须同时指明健和值的类型。下面是一段统计单词出现个数的代码

    map<string, size_t> mp;//申明一个string到size_t的映射的空容器
    string word;
    while(cin >> word)
    {
        ++mp[word]; //给单词对应的值加1, 如果对应的值未在map中, 下标运算符创建一个新元素, 键为word, 值为0;然后再给值加一
    }
    
    for(auto x : mp)
    {
        cout << x.first << ": " << x.second << endl; //输出出现的单词及其个数
    }

    insert() 插入一个元素,注意这里需要插入pair。pair将一对值组合成一个值, 两个值拥有不同的数据类型, 两个值可以用pair的两个公有函数first和second来访问。

   map<string, size_t> mp;
   mp.insert(pair<string, int>("xxx", 1)); 
   //这里在初始化一个pair的同时给它赋值,构造函数的两个参数数将分别作为pair的一对值。insert函数将这个pair作为新的元素插入。

    erase() 删除元素, 复杂度也是logn

    find() 通过key在容器中查找某个元素, 如果找到返回指向这个元素的迭代器, 如果没找到返回尾迭代器。

    count() 判断某个元素是否存在, 若存在返回true


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值