zoukankan      html  css  js  c++  java
  • c++提高学习笔记——05-c++STLday11

    在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    05-c++STLday11

    目录:
    一、常用容器
    1、上节作业——评委打分
    2、stack栈容器
    3、queue队列容器
    4、list容器
    测试API、测试:删除自定义数据类型
    5、set容器
    (1)测试API
    (2)pair对组的创建方式——两种
    (3)测试排序规则
    6、map容器
    测试API
    7、STL容器使用时机
    二、总结

    一、常用容器

    1、上节作业——评委打分

    有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
    //1. 创建五名选手,放到vector中
    //2. 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
    //3. sort算法对deque容器中分数排序,pop_back pop_front去除最高和最低分
    //4. deque容器遍历一遍,累加分数,累加分数/d.size()
    //5. person.score = 平均分

      1 /*
      2     create by wp
      3     2020.06.16
      4     文件功能...
      5     
      6     func()...干嘛的  参数1....
      7 */
      8 #define _CRT_SECURE_NO_WARNINGS
      9 #include<iostream>
     10 using namespace std;
     11 #include<vector>
     12 #include<deque>
     13 #include<algorithm>
     14 #include<string>
     15 #inlcude<ctime>
     16 /*
     17 有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
     18 //1. 创建五名选手,放到vector中
     19 //2. 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
     20 //3. sort算法对deque容器中分数排序,pop_back pop_front去除最高和最低分
     21 //4. deque容器遍历一遍,累加分数,累加分数/d.size()
     22 //5. person.score = 平均分
     23 */
     24 
     25 class Person
     26 {
     27 public:
     28     Person(string name, int score)
     29     {
     30         this->m_Name = name;
     31         this->m_Score = score;
     32     }
     33     
     34     string m_Name;//人名
     35     int m_Score;//分数
     36 };
     37 
     38 void createPerson(vector<Person>& v)
     39 {
     40     string nameSeed = "ABCDE";
     41     for(int i = 0; i < 5; i++)
     42     {
     43         string name = "选手";
     44         name += nameSeed[i];
     45         
     46         int score = 0;
     47         Person p(name, score);
     48         
     49         v.push_back(p);
     50     }
     51     
     52     
     53 }
     54 
     55 void setScore(vector<Person>& v)
     56 {
     57     for(vector<Person>::iterator it = v.begin(); it != v.end(); it++)
     58     {
     59         //对5个人进行打分
     60         deque<int>d;
     61         for(int i = 0; i < 10; i++)
     62         {
     63             int score = rand() % 41 + 60;//60~100
     64             
     65             d.push_back(score);
     66         }
     67         /*
     68         //先测试看下打分
     69         for(deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
     70         {
     71             cout << *dit << " ";
     72         }
     73         cout << endl;
     74         */
     75         
     76         //排序
     77         sort(d.begin(), d.end());
     78         
     79         //去除最高和最低
     80         d.pop_back();//最高
     81         d.pop_front();
     82         
     83         int sum = 0;
     84         for(deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
     85         {
     86             sum += *dit;
     87         }
     88         
     89         //平均分
     90         int avg = sum / d.size();
     91         
     92         it->m_Score = avg;
     93     }
     94     
     95 }
     96 
     97 void showScore(vector<Person>& v)
     98 {
     99     for(vector<Person>::iterator it = v.begin(); it != v.end(); it++)
    100     {
    101         cout << "姓名:" << it->m_Name << "最终平均分:" << it->m_Score << endl;
    102     }
    103     
    104 }
    105 
    106 void test01()
    107 {
    108     //为方便测试,最后设置随机数种子
    109     srand(unsigned int)time(NULL);
    110     
    111     //创建容器,存放选手
    112     vector<Person>v;
    113     
    114     //创建5名选手
    115     createPerson(v);
    116     
    117     /*
    118     //测试
    119     for(vector<Person>::iterator it = v.begin(); it != v.end(); it++)
    120     {
    121         cout << "姓名:" << (*it).m_Name << endl;
    122     }
    123     */
    124     
    125     //打分
    126     SetScore(v);
    127     
    128     //展示平均分
    129     showScore(v);
    130 }
    131 
    132 int main()
    133 {
    134     test01();
    135 
    136     system("pause");
    137     return EXIT_SUCCESS;
    138 }

    2、stack栈容器


    stack容器基本概念
    stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口,形式如图所示。stack容器允许新增元素,移除元素,取得栈顶元素,但是除了最顶端外,没有任何其他方法可以存取stack的其他元素。换言之,stack不允许有遍历行为。
    有元素推入栈的操作称为:push,将元素推出stack的操作称为pop.

    stack没有迭代器
    Stack所有元素的进出都必须符合”先进后出”的条件,只有stack顶端的元素,才有机会被外界取用。Stack不提供遍历功能,也不提供迭代器。


    测试API:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 //包含stack头文件
     5 #include<stack>
     6 
     7 /*
     8 //stack构造函数
     9 stack<T> stkT;//stack采用模板类实现, stack对象的默认构造形式: 
    10 stack(const stack &stk);//拷贝构造函数
    11 
    12 //stack赋值操作
    13 stack& operator=(const stack &stk);//重载等号操作符
    14 
    15 //stack数据存取操作
    16 push(elem);//向栈顶添加元素
    17 pop();//从栈顶移除第一个元素
    18 top();//返回栈顶元素
    19 
    20 //stack大小操作
    21 empty();//判断堆栈是否为空
    22 size();//返回堆栈的大小
    23 
    24 */
    25 
    26 
    27 void test01()
    28 {
    29     stack<int>s;
    30     //放入数据 push
    31     s.push(10);
    32     s.push(30);
    33     s.push(20);
    34     s.push(40);
    35     
    36     while(s.size() != 0)
    37     {
    38         cout << "栈顶为:" << s.top() << endl;//40 20 30 10
    39         //弹出栈顶元素
    40         s.pop();
    41     }
    42     cout << "size = " << s.size() << endl;
    43     
    44 }
    45 
    46 int main()
    47 {
    48     test01();
    49     
    50     system("pause");
    51     return EXIT_SUCCESS;
    52 }

    3、queue队列容器


    queue容器基本概念
    Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口,queue容器允许从一端新增元素,从另一端移除元素。


    queue没有迭代器
    Queue所有元素的进出都必须符合”先进先出”的条件,只有queue的顶端元素,才有机会被外界取用。Queue不提供遍历功能,也不提供迭代器。


    测试API:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 //包含队列头文件
     5 #include<queue>
     6 
     7 /*
     8 //queue构造函数
     9 queue<T> queT;//queue采用模板类实现,queue对象的默认构造形式:
    10 queue(const queue &que);//拷贝构造函数
    11 
    12 //queue存取、插入和删除操作
    13 push(elem);//往队尾添加元素
    14 pop();//从队头移除第一个元素
    15 back();//返回最后一个元素
    16 front();//返回第一个元素
    17 
    18 //queue赋值操作
    19 queue& operator=(const queue &que);//重载等号操作符
    20 
    21 //queue大小操作
    22 empty();//判断队列是否为空
    23 size();//返回队列的大小
    24 
    25 */
    26 
    27 void test01()
    28 {
    29     queue<int>q;
    30     q.push(10);//往队尾添加元素
    31     q.push(30);
    32     q.push(20);
    33     q.push(40);
    34     
    35     while(!q.empty())
    36     {
    37         cout << "队头:" << q.front() << endl;//10 40 30 40 20 40 40 40
    38         cout << "队尾:" << q.back() << endl;
    39         //弹出队头
    40         q.pop();
    41     }
    42     cout << "size:" << q.size() << endl;
    43 }
    44 
    45 int main()
    46 {
    47     test01();
    48     
    49     system("pause");
    50     return EXIT_SUCCESS;
    51 }

    4、list容器


    list容器基本概念
    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
    相较于vector的连续线性空间,list就显得负责许多,它的好处是每次插入或者删除一个元素,就是配置或者释放一个元素的空间。因此,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素的移除,list永远是常数时间。
    List和vector是两个最常被使用的容器。
    List容器是一个双向链表。


    >采用动态存储分配,不会造成内存浪费和溢出
    >链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
    >链表灵活,但是空间和时间额外耗费较大

    list容器的迭代器
    List容器不能像vector一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。List迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取操作。所谓”list正确的递增,递减、取值、成员取用”是指,递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取的是节点的成员。
    由于list是一个双向链表,迭代器必须能够具备前移、后移的能力,所以list容器提供的是Bidirectional Iterators.
    List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效。这在vector是不成立的,因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效,甚至List元素的删除,也只有被删除的那个元素的迭代器失效,其他迭代器不受任何影响。

    list容器的数据结构
    list容器不仅是一个双向链表,而且还是一个循环的双向链表


    测试API:

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include<list>
      5 #include<algorithm>
      6 #include<string>
      7 
      8 //list是双向循环链表
      9 void test01()
     10 {
     11     list<int> myList;
     12     for (int i = 0; i < 10; i ++){
     13         myList.push_back(i);
     14     }
     15 
     16     list<int>::_Nodeptr node =  myList._Myhead->_Next;
     17 
     18     for (int i = 0; i < myList._Mysize * 2;i++){
     19         cout << "Node:" << node->_Myval << endl;
     20         node = node->_Next;
     21         if (node == myList._Myhead){
     22             node = node->_Next;
     23         }
     24     }
     25 
     26 }
     27 
     28 /*
     29 //list构造函数
     30 list<T> lstT;//list采用采用模板类实现,对象的默认构造形式:
     31 list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
     32 list(n,elem);//构造函数将n个elem拷贝给本身。
     33 list(const list &lst);//拷贝构造函数。
     34 
     35 //list数据元素插入和删除操作
     36 push_back(elem);//在容器尾部加入一个元素
     37 pop_back();//删除容器中最后一个元素
     38 push_front(elem);//在容器开头插入一个元素
     39 pop_front();//从容器开头移除第一个元素
     40 insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
     41 insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
     42 insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
     43 clear();//移除容器的所有数据
     44 erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
     45 erase(pos);//删除pos位置的数据,返回下一个数据的位置。
     46 remove(elem);//删除容器中所有与elem值匹配的元素。
     47 
     48 */
     49 
     50 void printList(list<int>& L)
     51 {
     52     for(list<int>::iterator it = L.begin(); it != L.end(); it++)
     53     {
     54         cout << *it << " ";
     55     }
     56     cout << endl;
     57 }
     58 
     59 void test02()
     60 {
     61     list<int>L(10, 10);
     62     list<int>L2(L.begin(), L.end());
     63     
     64     printList(L);
     65     printList(L2);
     66     L2.push_back(100);
     67     
     68     //逆向打印
     69     for(list<int>::reverse_iterator it = L2.rbegin(); it != L2.rend(); it++)
     70     {
     71         cout << *it << " ";
     72     }
     73     cout << endl;
     74     
     75     //list迭代器不支持随机访问
     76     list<int>::iterator itBegin = L2.begin();
     77     //itBegin = itBegin + 1;
     78     
     79     //插入数据
     80     list<int>L3;
     81     L3.push_back(10);
     82     L3.push_back(30);
     83     L3.push_back(20);
     84     L3.push_front(100);
     85     L3.push_front(300);
     86     L3.push_front(200);
     87     
     88     printList(L3);//200 300 100 10 30 20
     89     
     90     //删除两端的数据
     91     L3.pop_front();//头删
     92     L3.pop_back();//尾删
     93     printList(L3);//300 100 10 30 
     94     
     95     L3.insert(L3.begin(), 1000);
     96     printList(L3);//1000 300 100 10 30
     97     
     98     //remove(elem);//删除容器中所有与elem值匹配的元素
     99     L3.push_back(10);//1000 300 100 10 30 10
    100     L3.remove(10);//参数,直接放值
    101     
    102     printList(L3);//1000 300 100 30
    103 }
    104 
    105 /*
    106 //list大小操作
    107 size();//返回容器中元素的个数
    108 empty();//判断容器是否为空
    109 resize(num);//重新指定容器的长度为num,
    110 若容器变长,则以默认值填充新位置。
    111 如果容器变短,则末尾超出容器长度的元素被删除。
    112 resize(num, elem);//重新指定容器的长度为num,
    113 若容器变长,则以elem值填充新位置。
    114 如果容器变短,则末尾超出容器长度的元素被删除。
    115 
    116 //list赋值操作
    117 assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
    118 assign(n, elem);//将n个elem拷贝赋值给本身。
    119 list& operator=(const list &lst);//重载等号操作符
    120 swap(lst);//将lst与本身的元素互换。
    121 
    122 //list数据的存取
    123 front();//返回第一个元素。
    124 back();//返回最后一个元素。
    125 
    126 */
    127 
    128 void test03()
    129 {
    130     list<int>L3;
    131     L3.push_back(10);
    132     L3.push_back(30);
    133     L3.push_back(20);
    134     L3.push_front(100);
    135     L3.push_front(300);
    136     L3.push_front(200);
    137     
    138     cout << "大小:" << L3.size() << endl;
    139     if(L3.empty())
    140     {
    141         cout << "L3为空" << endl;
    142     }
    143     else
    144     {
    145         cout << "L3不为空" << endl;
    146     }
    147     
    148     L3.resize(10);
    149     printList(L3);//200 300 100 10 30 20 0 0 0 0
    150     
    151     L3.resize(3);
    152     printList(L3);//200 300 100
    153     
    154     list<int> L4;
    155     L4.assign(L3.begin(), L3.end());
    156     
    157     cout << "front:" << L4.front() << endl;//200
    158     cout << "back:" << L4.back() << endl;//100
    159     
    160 }
    161 
    162 /*
    163 //list反转排序
    164 reverse();//反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素。
    165 sort(); //list排序
    166 */
    167 bool myCompare(int v1, int v2)
    168 {
    169     return v1 > v2;
    170 }
    171 
    172 void test04()
    173 {
    174     list<int>L;
    175     
    176     L.push_back(10);
    177     L.push_back(20);
    178     L.push_back(40);
    179     L.push_back(30);
    180     
    181     L.reverse();
    182     printList(L);//30 40 20 10
    183     
    184     //所有不支持随机访问的迭代器,不可以用系统提供的算法
    185     //如果不支持用系统提供算法,那么这个类内部会提供
    186     //sort(L.begin(), L.end());
    187     L.sort();//从小到大
    188     
    189     printList(L);
    190     
    191     //从大到小
    192     L.sort(myCompare);
    193     printList(L);
    194 }
    195 
    196 //自定义数据类型
    197 class Person
    198 {
    199 public:
    200     Person(string name, int age, int height)
    201     {
    202         this->m_Name = time;
    203         this->m_Age = age;
    204         this->m_Height = height;
    205     }
    206     
    207     
    208     string  m_Name;
    209     int m_Age;
    210     int m_Height;//身高
    211 };
    212 
    213 //Person排序规则:如果年龄相同,按照身高升序排序
    214 bool myComparePerson(Person& p1, Person& p2)
    215 {
    216     /*
    217     if(p1.m_Age > p2.m_Age)
    218     {
    219         return true;
    220     }
    221     return false;
    222     */
    223     
    224     if(p1.m_Age == p2.m_Age)
    225     {
    226         return p1.m_Height < p2.m_Height;
    227     }
    228     else
    229     {
    230         return p1.m_Age > p2.m_Age;
    231     }
    232 }
    233 
    234 void test05()
    235 {
    236     list<Person>L;
    237     
    238     Person p1("亚瑟", 10, 165);
    239     Person p2("德玛西亚", 20, 170);
    240     Person p3("火枪", 17, 177);
    241     Person p4("德雷福斯", 19, 120);
    242     Person p5("MT", 18, 200);
    243     Person p6("狗蛋", 18, 166);
    244     Person p7("狗剩", 18, 210);
    245     
    246     L.push_back(p1);
    247     L.push_back(p2);
    248     L.push_back(p3);
    249     L.push_back(p4);
    250     L.push_back(p5);
    251     L.push_back(p6);
    252     L.push_back(p7);
    253     
    254     //需求:打印数据时候,按照年龄的降序输出
    255     //对于自定义数据类型,必须要指定排序规则
    256     L.sort(myComparePerson);
    257     
    258     for(list<Person>::iterator it = it = L.begin(); it != L.end(); it++)
    259     {
    260         cout << "姓名:" << it->m_Name << "年龄:" << *it.m_Age << "身高:" << it->m_Height << endl;
    261     }
    262 }
    263 
    264 
    265 
    266 
    267 int main()
    268 {
    269     test01();
    270     
    271     system("pause");
    272     return EXIT_SUCCESS;
    273 }

    测试:删除自定义数据类型

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include<list>
      5 #include<algorithm>
      6 #include<string>
      7 
      8 
      9 //自定义数据类型
     10 class Person
     11 {
     12 public:
     13     Person(string name, int age, int height)
     14     {
     15         this->m_Name = time;
     16         this->m_Age = age;
     17         this->m_Height = height;
     18     }
     19     
     20     //重载 == 让remove可以删除自定义的Person类型
     21     bool operator==(const Person& p)//必须加const
     22     {
     23         if(this->m_Name == p.m_Name && this->m_Age == p.m_Age && this->m_Height == p.m_Height)
     24         {
     25             return true;
     26         }
     27         return false;
     28     }
     29     
     30     
     31     string  m_Name;
     32     int m_Age;
     33     int m_Height;//身高
     34 };
     35 
     36 //Person排序规则:如果年龄相同,按照身高升序排序
     37 bool myComparePerson(Person& p1, Person& p2)
     38 {
     39     /*
     40     if(p1.m_Age > p2.m_Age)
     41     {
     42         return true;
     43     }
     44     return false;
     45     */
     46     
     47     if(p1.m_Age == p2.m_Age)
     48     {
     49         return p1.m_Height < p2.m_Height;
     50     }
     51     else
     52     {
     53         return p1.m_Age > p2.m_Age;
     54     }
     55 }
     56 
     57 void test01()
     58 {
     59     list<Person>L;
     60     
     61     Person p1("亚瑟", 10, 165);
     62     Person p2("德玛西亚", 20, 170);
     63     Person p3("火枪", 17, 177);
     64     Person p4("德雷福斯", 19, 120);
     65     Person p5("MT", 18, 200);
     66     Person p6("狗蛋", 18, 166);
     67     Person p7("狗剩", 18, 210);
     68     
     69     L.push_back(p1);
     70     L.push_back(p2);
     71     L.push_back(p3);
     72     L.push_back(p4);
     73     L.push_back(p5);
     74     L.push_back(p6);
     75     L.push_back(p7);
     76     
     77     //需求:打印数据时候,按照年龄的降序输出
     78     //对于自定义数据类型,必须要指定排序规则
     79     L.sort(myComparePerson);
     80     
     81     for(list<Person>::iterator it = it = L.begin(); it != L.end(); it++)
     82     {
     83         cout << "姓名:" << it->m_Name << "年龄:" << *it.m_Age << "身高:" << it->m_Height << endl;
     84     }
     85     
     86     cout << "----------" << endl;
     87     //删除 狗蛋
     88     L.remove(p6);
     89     for(list<Person>::iterator it = it = L.begin(); it != L.end(); it++)
     90     {
     91         cout << "姓名:" << it->m_Name << "年龄:" << *it.m_Age << "身高:" << it->m_Height << endl;
     92     }
     93     
     94 }
     95 
     96 
     97 
     98 
     99 int main()
    100 {
    101     test01();
    102     
    103     system("pause");
    104     return EXIT_SUCCESS;
    105 }

    5、set容器


    set/multiset容器基本概念
    set容器基本概念
    Set的特性是。所有元素都会根据元素的键值自动被排序。Set的元素不像map那样可以同时拥有实值和键值,set的元素即是键值又是实值。Set不允许两个元素有相同的键值。
    我们可以通过set的迭代器改变set元素的值吗?不行,因为set元素值就是其键值,关系到set元素的排序规则。如果任意改变set元素值,会严重破坏set组织。换句话说,set的iterator是一种const_iterator.
    set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。

    multiset容器基本概念
    multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种。
    树的简单知识:
    二叉树就是任何节点最多只允许有两个字节点。分别是左子结点和右子节点。

    二叉树示意图

    二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效。二叉搜索树的放置规则是:任何节点的元素值一定大于其左子树中的每一个节点的元素值,并且小于其右子树的值。因此从根节点一直向左走,一直到无路可走,即得到最小值,一直向右走,直至无路可走,可得到最大值。那么在儿茶搜索树中找到最大元素和最小元素是非常简单的事情。下图为二叉搜索树


    上面我们介绍了二叉搜索树,那么当一个二叉搜索树的左子树和右子树不平衡的时候,那么搜索依据上图表示,搜索9所花费的时间要比搜索17所花费的时间要多,由于我们的输入或者经过我们插入或者删除操作,二叉树失去平衡,造成搜索效率降低。
    所以我们有了一个平衡二叉树的概念,所谓的平衡不是指的完全平衡。


    RB-tree(红黑树)为二叉树的一种。


    (1)测试API:

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include<set>
      5 /*
      6 //set构造函数
      7 set<T> st;//set默认构造函数:
      8 mulitset<T> mst; //multiset默认构造函数: 
      9 set(const set &st);//拷贝构造函数
     10 
     11 //set赋值操作
     12 set& operator=(const set &st);//重载等号操作符
     13 swap(st);//交换两个集合容器
     14 
     15 //set大小操作
     16 size();//返回容器中元素的数目
     17 empty();//判断容器是否为空
     18 
     19 //set插入和删除操作
     20 insert(elem);//在容器中插入元素。
     21 clear();//清除所有元素
     22 erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
     23 erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
     24 erase(elem);//删除容器中值为elem的元素。
     25 
     26 */
     27 void printSet(set<int>& s)
     28 {
     29     for(set<int>::iterator it = s.begin(); it != s.end(); it++)
     30     {
     31         cout << *it << " ";
     32     }
     33     cout << endl;
     34 }
     35 
     36 
     37 void test01()
     38 {
     39     set<int>s1;
     40     
     41     //关联式容器,key进行排序,从小到大
     42     s1.intsert(5);
     43     s1.intsert(1);
     44     s1.intsert(9);
     45     s1.intsert(3);
     46     s1.intsert(7);
     47     
     48     printSet(s1);//1 3 5 7 9
     49     
     50     if(s1.empty())
     51     {
     52         cout << "" << endl;
     53     }
     54     else
     55     {
     56         cout << "size = " << s1.size() << endl;
     57     }
     58     
     59     s1.erase(s1.begin());// 3 5 7 9
     60     printSet(s1);
     61     s1.erase(3);//5 7 9
     62     printSet(s1);
     63     
     64 }
     65 
     66 /*
     67 //set查找操作
     68 find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
     69 count(key);//查找键key的元素个数
     70 lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
     71 upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
     72 equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
     73 
     74 */
     75 void test02()
     76 {
     77     set<int>s1;
     78     s1.intsert(5);
     79     s1.intsert(1);
     80     s1.intsert(9);
     81     s1.intsert(3);
     82     s1.intsert(7);
     83     
     84     //对于set,没有value,key就是value
     85     
     86     set<int>::iterator pos = s1.find(3);
     87     //判断是否找到
     88     if(pos != s1.end())
     89     {
     90         cout << "找到了,值为:" << *pos << endl;
     91     }
     92     else
     93     {
     94         cout << "未找到" << endl;
     95     }
     96     
     97     //count(key);//查找键key的元素个数,对于set而言,结果0或者1
     98     int num = s1.count(1);
     99     cout << "2的个数为:" << num << endl;
    100     
    101     //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器
    102     set<int>::iterator it = s1.lower_bound(3);//10就是未找到
    103     if(it != s1.end())
    104     {
    105         cout << "找到了,lower_bound(3)的值为:" << *it << endl;
    106     }
    107     else
    108     {
    109         cout << "未找到" << endl;
    110     }
    111     //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器
    112     set<int>::iterator it2 = s1.lower_bound(3);
    113     if(it2 != s1.end())
    114     {
    115         cout << "找到了,lower_bound(3)的值为:" << *it2 << endl;
    116     }
    117     else
    118     {
    119         cout << "未找到" << endl;
    120     }
    121     //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
    122     //上下限就是 lower_bound upper_bound
    123     pair<set<int>::iterator, set<int>::iterator> ret = s1.equal_range(3);
    124     //获取第一个值
    125     if(ret.first != s1.end())
    126     {
    127         cout << "找到equal_range中的lower_bound的值:" << *(ret.first) << endl;
    128     }
    129     else
    130     {
    131         cout << "未找到" << endl;
    132     }
    133     //获取第二个值
    134     if(ret.second != s1.end())
    135     {
    136         cout << "找到equal_range中的upper_bound的值:" << *(ret.second) << endl;
    137     }
    138     else
    139     {
    140         cout << "未找到" << endl;
    141     }
    142     
    143 }
    144 
    145 int main()
    146 {
    147     test01();
    148     
    149     system("pause");
    150     return EXIT_SUCCESS;
    151 }

    (2)pair对组的创建方式——两种


    对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second访问。
    类模板:template <class T1, class T2> struct pair.


    测试:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 //创建对组,使用对组pair不需要引用头文件
     7 void test01()
     8 {
     9     //第一种括号
    10     pair<string, int>p(string("Tom"), 100);
    11     
    12     //取值
    13     cout << "姓名:" << p.first << endl;
    14     cout << "年龄:" << p.second << endl;
    15     
    16     //第二种创建
    17     pair<string, int> p2 = make_pair("Jerry", 200);
    18     cout << "姓名:" << p2.first << endl;
    19     cout << "年龄:" << p2.second << endl;
    20     
    21 }
    22 
    23 int main()
    24 {
    25     test01();
    26     
    27     system("pause");
    28     return EXIT_SUCCESS;
    29 }

    (3)测试排序规则:

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 #include<set>
      5 #include<string>
      6 
      7 void printSet(set<int>& s)
      8 {
      9     for(set<int>::iterator it = s.begin(); it != s.end(); it++)
     10     {
     11         cout << *it << " ";
     12     }
     13     cout << endl;
     14 }
     15 
     16 //set容器,不允许插入重复的键值
     17 void test01()
     18 {
     19     set<int>s1;
     20     
     21     pair<set<int>::iterator, bool> ret = s1.intsert(10);
     22 
     23     
     24     if(ret.second)
     25     {
     26         cout << "插入成功" << endl;
     27     }
     28     else
     29     {
     30         cout << "插入失败" << endl;
     31     }
     32     s1.intsert(10);
     33 
     34 
     35     if(ret.second)
     36     {
     37         cout << "第二次插入成功" << endl;
     38     }
     39     else
     40     {
     41         cout << "第二次插入失败" << endl;
     42     }
     43 
     44     printSet(s1);//10

        //multiset允许插入重复的值
        multiset<int>mul;
        mul.insert(10);
        mul.insert(10);
    45 } 46 47 //指定set排序规则,从大到小 48 //仿函数 49 class myCompare 50 { 51 public: 52 //重载() 53 bool operator()(int v1, int v2) 54 { 55 return v1 > v2; 56 } 57 58 59 }; 60 61 //set容器排序 62 void test02() 63 { 64 set<int, myCompare>s1; 65 66 s1.insert(5); 67 s1.insert(1); 68 s1.insert(9); 69 s1.insert(3); 70 s1.insert(7); 71 72 //printSet(s1); 73 74 //从大到小排序 75 //在插入之前就指定排序规则 76 77 for(set<int, myCompare>::iterator it = s1.begin(); it != s1.end(); it++) 78 { 79 cout << *it << " "; 80 } 81 cout << endl; 82 83 } 84 85 //自定义数据类型 86 class Person 87 { 88 public: 89 Person(string name, int age) 90 { 91 this->m_Name = name; 92 this->m_Age = age; 93 } 94 95 string m_Name; 96 int m_Age; 97 }; 98 99 class myComparePerson 100 { 101 public: 102 bool operator()(const Person& p1, const Person& p2)//必须加入const 103 { 104 if(p1.m_Age > p2.m_Age)//降序 105 { 106 return true; 107 } 108 return false; 109 } 110 111 112 }; 113 114 void test03() 115 { 116 set<Person, myComparePerson> s1; 117 118 Person p1("大娃", 100); 119 Person p2("二娃", 90); 120 Person p3("六娃", 10); 121 Person p4("爷爷", 1000); 122 123 s1.insert(p1); 124 s1.insert(p2); 125 s1.insert(p3); 126 s1.insert(p4); 127 128 //插入自定义数据类型,一开始就指定排序规则 129 130 //显示 131 for(set<Person, myComparePerson>::iterator it = s1.begin(); it != s1.end(); it++) 132 { 133 cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << endl; 134 } 135 } 136 137 138 139 140 141 142 int main() 143 { 144 test01(); 145 146 system("pause"); 147 return EXIT_SUCCESS; 148 }

    6、map容器


    map/multimap基本概念
    Map的特性是,所有元素都会根据元素的键值自动排序。Map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值。
    我们可以通过map的迭代器改变map的键值吗?答案是不行,因为map的键值关系到map元素的排列规则,任意改变map键值将会严重破坏map组织。如果想要修改元素的实值,那么是可以的。
    Map和list拥有相同的某些性质,当对它的容器元素进行新增操作或者删除操作时,操作之前的所有迭代器,在操作完成之后依然有效,当然被删除的那个元素的迭代器必然是个例外。
    Multimap和map的操作类似,唯一区别multimap键值可重复。
    Map和multimap都是以红黑树为底层实现机制。


     测试API:

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<iostream>
      3 using namespace std;
      4 //引入头文件
      5 #include<map>
      6 
      7 /*
      8 //map构造函数
      9 map<T1, T2> mapTT;//map默认构造函数: 
     10 map(const map &mp);//拷贝构造函数
     11 
     12 //map赋值操作
     13 map& operator=(const map &mp);//重载等号操作符
     14 swap(mp);//交换两个集合容器
     15 
     16 //map大小操作
     17 size();//返回容器中元素的数目
     18 empty();//判断容器是否为空
     19 
     20 //map插入数据元素操作
     21 map.insert(...); //往容器插入元素,返回pair<iterator,bool>
     22 map<int, string> mapStu;
     23 // 第一种 通过pair的方式插入对象
     24 mapStu.insert(pair<int, string>(3, "小张"));
     25 // 第二种 通过pair的方式插入对象
     26 mapStu.inset(make_pair(-1, "校长"));
     27 // 第三种 通过value_type的方式插入对象
     28 mapStu.insert(map<int, string>::value_type(1, "小李"));
     29 // 第四种 通过数组的方式插入值
     30 mapStu[3] = "小刘";
     31 mapStu[5] = "小王";
     32 
     33 */
     34 
     35 
     36 void test01()
     37 {
     38     map<int, int>m;
     39     //插入值
     40     //4种方式
     41     //第一种
     42     m.insert(pair<int, int>(1, 10));
     43     //第二种 推荐
     44     m.insert(make_pair(2,20));
     45     //第三种
     46     m.insert(map<int, int>::value_type(3, 30));
     47     //第四种,如果保证key存在,那么可以通过[]访问
     48     m[4] = 40;
     49     
     50     for(map<int, int>::iterator it = m.begin(); it != m.end(); it++)
     51     {
     52         cout << "key = " << it->first << "value = " << it->second << endl;
     53     }
     54     
     55     //cout << m[5] << endl;
     56     
     57     for(map<int, int>::iterator it = m.begin(); it != m.end(); it++)
     58     {
     59         cout << "key = " << it->first << "value = " << it->second << endl;
     60     }
     61     
     62     cout << m[4] << endl;
     63     
     64     if(m.empty())
     65     {
     66         cout << "" << endl;
     67     }
     68     else
     69     {
     70         cout << "size = " << m.size() << endl;
     71     }
     72     
     73 }
     74 
     75 /*
     76 //map删除操作
     77 clear();//删除所有元素
     78 erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
     79 erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
     80 erase(keyElem);//删除容器中key为keyElem的对组。
     81 
     82 //map查找操作
     83 find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
     84 count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
     85 lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
     86 upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
     87 equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
     88 
     89 */
     90 
     91 void test02()
     92 {
     93     map<int, int>m;
     94     m.insert(pair<int, int>(1, 10));
     95     m.insert(make_pair(2,20));
     96     m.insert(map<int, int>::value_type(3, 30));
     97     m[4] = 40;
     98     
     99     m.erase(1);
    100     for(map<int, int>::iterator it = m.begin(); it != m.end(); it++)
    101     {
    102         cout << "key = " << it->first << "value = " << it->second << endl;
    103     }
    104     
    105     map<int, int>::iterator pos = m.find(2);
    106     if(pos != m.end())
    107     {
    108         cout << "找到,key:" << pos->first << "value:" << pos->second << endl;
    109     }
    110     else
    111     {
    112         cout << "未找到" << endl;
    113     }
    114     
    115     int num = m.count(3);//map的count要么0,要么1
    116     cout << "num = " << endl;
    117     
    118     //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器
    119     map<int, int>::iterator ret = m.lower_bound(3);
    120     if(ret != m.end())
    121     {
    122         cout << "lower_bound中key:" << ret->first << "value:" << ret->second << endl;
    123     }
    124     else
    125     {
    126         cout << "未找到" << endl;
    127     }
    128     
    129     //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器
    130     map<int, int>::iterator ret = m.upper_bound(3);
    131     if(ret != m.end())
    132     {
    133         cout << "upper_bound中key:" << ret->first << "value:" << ret->second << endl;
    134     }
    135     else
    136     {
    137         cout << "未找到" << endl;
    138     }
    139     
    140     //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
    141     pair<map<int, int>::iterator, map<int, int>::iterator> ret2 = m.equal_range(3);
    142     
    143     if(ret2.first != m.end())
    144     {
    145         cout << "找到了equal_range中的lower_bound的key" << ret2.first->first << "value:" << ret2.first->second << endl;
    146     }
    147     else
    148     {
    149         cout << "未找到" << endl;
    150     }
    151     
    152     if(ret2.second != m.end())
    153     {
    154         cout << "找到了equal_range中的upper_bound的key" << ret2.second->first << "value:" << ret2.second->second << endl;
    155     }
    156     else
    157     {
    158         cout << "未找到" << endl;
    159     }
    160     
    161 }
    162 
    163 //指定排序规则
    164 class myCompare
    165 {
    166 public:
    167     bool operator()(int v1, int v2)
    168     {
    169         return v1 > v2;
    170     }
    171 };
    172 
    173 
    174 void test03()
    175 {
    176     //从大到小排序
    177     map<int, int, myCompare>m;
    178     m.insert(pair<int, int>(1, 10));
    179     m.insert(make_pair(2,20));
    180     m.insert(map<int, int>::value_type(3, 30));
    181     m[4] = 40;
    182     
    183     for(map<int, int, myCompare>::iterator it = m.begin(); it != m.end(); it++)
    184     {
    185         cout << "key = " << it->first << "value = " << it->second << endl;
    186     }
    187     
    188 }
    189 
    190 
    191 
    192 int main()
    193 {
    194     test01();
    195     
    196     system("pause");
    197     return EXIT_SUCCESS;
    198 }

    7、STL容器使用时机

     

    vector

    deque

    list

    set

    multiset

    map

    multimap

    典型内存结构

    单端数组

    双端数组

    双向链表

    二叉树

    二叉树

    二叉树

    二叉树

    可随机存取

    对key而言:不是

    元素搜寻速度

    非常慢

    对key而言:快

    对key而言:快

    元素安插移除

    尾端

    头尾两端

    任何位置

    -

    -

    -

    -

    vector的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。

    deque的使用场景:比如排队购票系统,对排队者的存储可以采用deque,支持头端的快速移除,尾端的快速添加。如果采用vector,则头端移除时,会移动大量的数据,速度慢。
         vector与deque的比较:
        一:vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的开始位置    却是不固定的。
        二:如果有大量释放操作的话,vector花的时间更少,这跟二者的内部实现有关。
        三:deque支持头部的快速插入与快速移除,这是deque的优点。

    list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。

    set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。

    map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是vector容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

    二、总结

    1    stack栈容器
    1.1    先进后出
    1.2    栈顶 top
    1.3    压栈 push
    1.4    弹出栈顶 pop
    1.5    大小 size
    1.6    为空 empty
    2    queue 队列容器
    2.1    先进先出
    2.2    队头 front 队尾 back
    2.3    入队 push
    2.4    弹出队头 pop
    2.5    大小 size
    2.6    为空 empty
    3    List容器
    3.1    赋值、构造、大小、为空、删除 、添加
    3.2    移除 remove( 10 )  删除容器中所有与10 匹配的元素
    3.3    双向循环链表
    3.4    迭代器是不支持随机访问的
    3.5    反转排序
    3.5.1    reverse 反转
    3.5.2    排序 成员函数 sort
    3.5.3    默认排序 从小到大
    3.5.4    自定义数据类型,必须指定排序规则
    3.5.5    高级
    3.6    remove删除list容器中自定义数据类型
    4    set容器
    4.1    关联式容器
    4.2    插入数据自动排序 按照key
    4.3    insert 插入值
    4.4    erase  参数可以传值 或者 迭代器
    4.5    find() 返回值 迭代器  找不到返回的  end()
    4.6    count 计数  对于set而言  结果 就是 0 或者1
    4.7    lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
    4.8    upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
    4.9    equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
    4.10    对组 pair
    4.10.1     第一个值 first
    4.10.2     第二个值 second
    4.10.3     默认括号
    4.10.4     make_pair()
    4.11    set插入返回值是 对组  < 迭代器, 是否成功标示>
    4.12    指定set排序规则,利用仿函数
    4.13    set插入自定义数据类型
    5    map容器
    5.1    每个元素 都是一个pair
    5.2    对于map而言 key是不可以重复
    5.3    multimap可以
    5.4    4中插入方式  
    5.5    count 统计 map 0 或1  multimap可能大于1
    5.6    排序规则自己指定


    在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    Proguard 混淆的一些经验教训!!!
    记一个奇怪的编码转换问题,及探讨“错误: 编码GBK的不可映射字符” 的原因
    我的chrome 智能扩展插件copier开源了!!!
    js 日期格式化小问题
    最后的记忆——Spring ApplicationContext
    最后的记忆——Spring BeanFactory
    归去来兮!田园将芜胡不归?
    一个线程 就是一个 人!!!
    痛苦的 java.net.BindException: Address already in use: connect —— Nacos的坑
    Mysql 的异常:The last packet successfully received from the server was 90 milliseconds ago. The last packet sent successfully to the server was 43,603,303 milliseconds ago. is longer than the server con
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_ImprovedLearning_02.html
Copyright © 2011-2022 走看看