【笔记】STL的七种武器(一)顺序容器

(0)启示:程序=算法+数据结构

参考资料:

C++迭代器(STL迭代器)iterator详解 (biancheng.net)

(8条消息) 士兵队列训练问题(链表)_Stone 不会喝水的博客-CSDN博客

(8条消息) C++容器适配器_JakeMiao的专栏-CSDN博客_c++ 适配器

 

 

< ITERATOR >

1.(算法-迭代器-容器)

迭代器是一种 检查容器内元素 并 遍历元素 的数据类型。

C++更趋向于使用迭 代器而不是下标操作,因为标准库为每一种标准容器(如vector)定义了一种 迭代器类型,而只用少数容器(如vector)支持下标操作访问容器元素。

 

2.迭代器按照定义方式分成以下四种。

1)正向迭代器

 容器类名::iterator  迭代器名;

2) 常量正向迭代器

 容器类名::const_iterator  迭代器名;

3) 反向迭代器

 容器类名::reverse_iterator  迭代器名;

4) 常量反向迭代器

 容器类名::const_reverse_iterator  迭代器名;

 

3.*迭代器名就表示迭代器指向的元素。通过非常量迭代器还能修改其指向的元素。

迭代器都可以进行++操作。反向迭代器和正向迭代器++后移动方向不同。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v;  //v是存放int类型变量的可变长数组,开始时没有元素
    for (int n = 0; n<5; ++n)
        v.push_back(n);  //push_back成员函数在vector容器尾部添加一个元素
    vector<int>::iterator i;  //定义正向迭代器
    for (i = v.begin(); i != v.end(); ++i) {  //用迭代器遍历容器
        cout << *i << " ";  //*i 就是迭代器i指向的元素
        *i *= 2;  //每个元素变为原来的2倍
    }
    cout << endl;
    //用反向迭代器遍历容器
    for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)
        cout << *j << " ";
    return 0;
}
View Code

 

4.后置++要多生成一个局部对象 tmp,因此执行速度比前置的慢。

同理,迭代器是一个对象,STL 在重载迭代器的++运算符时,后置形式也比前置形式慢。

 

5.STL 中有用于操作迭代器的三个函数模板,它们是:
  • advance(p, n):使迭代器 p 向前或向后移动 n 个元素。
  • distance(p, q):计算两个迭代器之间的距离,即迭代器 p 经过多少次 + + 操作后和迭代器 q 相等。如果调用时 p 已经指向 q 的后面,则这个函数会陷入死循环。
  • iter_swap(p, q):用于交换两个迭代器 p、q 指向的值。

 

< CONTAINER >顺序容器

0.  vector   deque  list

顺序容器的取舍,一般应遵循下面的原则:

高效的随即存取,而不在乎插入和删除的效率,使用vector

大量的插入和删除,而不关心随即存取,则应使用list

随即存取,而且需要两端数据的插入和删除,则应使用deque

 

1.常用算法函数

a.front();                 a.back(); 

a.size();                  a.clear();   

a.push_front(x);      a.pop_front();

a.push_back(x);      a.pop_back();

a.insert(it, x);           

a.erase(it);               a.erase(first, last)

 

2.vector 例题:

back and forth 倒牛奶[USACO]

图的表示和存储

 

3.deque 

扑克游戏: 题目加题解在这【刷题】【stl】扑克游戏 - 心若笺诗 - 博客园 (cnblogs.com)

 

4.list 循环链表

List容器的每个节点都含有 前驱元素指针域 、 数据域 、 后继元素指针域

在链表的任意位置进行元素的插入、删除和查找操作速度是较快的。

由于list对象的结点并不要求在一段连续的内存中,所以对于迭代器,只能通过“++”或者“–”的操作,不能对其进行+N或者-N的操作。

操作:

一)创建list对象:

  list l 或 list l(10); //创建具有10个整形元素的list对象l 。

(二)插入元素:

  push_back()  push_front()  insert()

(三)遍历元素:

(1)前向遍历:以前向迭代器的方式遍历;

(2)反向遍历:使用反向迭代器进行遍历。

(四)删除元素:

(1)remove(元素值),删除链表中的元素,值相同的元素都会被删除;

(2)pop_front()   pop_back()

(3)erase()删除迭代器位置的元素;

(4)clear()清空链表容器。

(五)查找元素:需要添加#include

  find(迭代器1,迭代器2,元素)

  函数返回一个迭代器值,若该值被找到则返回该值所在的迭代器值,若没有找到则返回end()迭代器的位置。

(六)l.sort()实现升序排序

list例题:

士兵队列训练问题【刷题】【stl】士兵队列训练问题 - 心若笺诗 - 博客园 (cnblogs.com)

 

5.pair

(1)表示一个元 素对

并提供了按照字典序对元素对进行大小比较的比较 运算符模板函数。

pair模板类对象有两个成员:first和 second,分别表示首元素和尾元素。

(2)操作:

 

  pair<int,int> pii;

  make_pair(x,y); 

例题:【刷题】【pair】最大数 - 心若笺诗 - 博客园 (cnblogs.com)

 

容器适配器(CONTAINERS ADAPTER)

  ”适配器是使一种事物的行为类似于另外一种事物行为的一种机制”,适配器对容器进行包装,使其表现出另外一种行为。例如,stack<int, vector<int> >实现了栈的功能,但其内部 使用顺序容器vector<int>来存储数据 。(相当于是vector<int>表现出了栈的行为)。

  不真的存储内容,将内容转给顺序容器存储,只负责提供操作。精简了容器功能,不提供迭代器以及不必要的访问功能。

  标准库提供了三种顺序容器适配器:queue(FIFO队列)、priority_queue(优先级队列)、stack(栈)。

 

 1.queue队列

  先进先出(FIFO)

  std::queue  <int , std::deque<int>  >  a;

  std::queue a;

应用:queue实现bfs

 

2.stack

  先进后出(FILO)

3.单调栈

  栈内的元素,单调排序。可以很方便地求出某个数的左边或者右边第一个比它大或者小的元素,而且总时间 复杂度O(N)。

 

4.priority_queue 单调队列

  一种特殊的双端队列,其内部元素具有严格单调性。

单调队列的时间复杂度是O(N),因为每 个数只会进队和出队一次,所以这个算法的效率还是很高的。

注意:建议直接用数组模拟单调队列,因为系统自带容器不方便而且不易调试。

同时,每个数只会进去一次,所以,数组绝对不会爆,空间也是S(N), 优于堆或线段树等数据结构

例题:滑动窗口【刷题】【stl】最大(连续)子序列之和 - 心若笺诗 - 博客园 (cnblogs.com)

 

5.重载运算符

两种重载方法

struct node1
{
    int id;
    double x,y;
};
bool operator <(const node1 &a,const node1 &b)
{
    return a.x<b.x && a.y<b.y;
}

struct node2
{
    int id;
    double x,y;
    bool operator < (const node2 &b )
    {
        return x<b.x && y<b.y;
    }
};

 

 

一些例题:

合并果子(二分+队列)

【二分】【基础】(跳石头)(合并果子)(蚯蚓) - 心若笺诗 - 博客园 (cnblogs.com)

dijikstra(队列实现最短路)

 

posted @ 2022-02-14 04:23  心若笺诗  阅读(70)  评论(0编辑  收藏  举报