STL 常用容器

stack

#include <iostream>
#include <stack>
using namespace std;

int main()
{
    stack<int> S;
    S.push(1);
    S.push(2);
    S.pop();
    cout << S.empty() << endl;
    cout << S.size() << endl;
    S.top() = 3;
    cout << S.top() << endl;
    getchar();
    return true;
}

程序执行结果:
这里写图片描述

queue

#include <iostream>
#include <queue>
using namespace std;

int main()
{
    queue<int> Q;
    Q.push(1);
    Q.push(2);
    Q.pop();
    cout << Q.empty() << endl;
    cout << Q.size() << endl;
    Q.front() = 3;
    cout << Q.front() << endl;
    Q.back() = 4;
    cout << Q.back() << endl;
    getchar();
    return true;
}

程序执行结果:
这里写图片描述

vector

#include <iostream>  
#include <vector>  

using namespace std;

int main() {
    int ary[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    vector<int> v;                          //声明一个空的vector  
    vector<int> v1(v);                      //复制一个v的vector  
    vector<int> v2(10, 1);                  //v2中有10个元素,每个元素的值为1  
    vector<int> v3(ary + 1, ary + 4);       //v3中以区间[ary[1], ary[4])赋值  

    v.assign(ary, ary + 10);                //v中以区间[ary[0], ary[10])赋值  
    v1.assign(10, 2);                       //v1中有10个元素,每个元素的值为2  

    cout << v.at(1) << endl;                //输出v中在位置1中的元素  
    cout << v[1] << endl;                   //等同于上,不过他不会做位置越界的检查  
    cout << v.front() << endl;              //输出v中第一个位置的元素  
    v.front() = 100;                        //为第一个位置的元素赋值      
    v.back() = 200;                         //为v中最后一个元素赋值  
    cout << v.back() << endl;               //输出v中的最后一个位置的元素  

    v.insert(v.begin(), 10);                //在开头插入元素10  
    v.insert(v.begin(), 5, 2);              //在开头插入5个元素,每个元素为2  
    v.insert(v.begin() + 2, ary + 5, ary + 6);    //在v[2]的位置开始插入[ary[5], ary[6])的元素  

    v.erase(v.begin() + 2);                 //删除v[2]  
    v.erase(v.begin(), v.begin() + 5);      //删除[v[0], v[5])元素  

    for (vector<int>::iterator itor = v.begin(); itor != v.end(); itor++)
        cout << *itor << ' ';               //正向遍历vector数组 v  
    cout << endl;

    for (vector<int>::reverse_iterator ritor = v.rbegin(); ritor != v.rend(); ritor++)
        cout << *ritor << ' ';              //逆向遍历vector数组 v  
    cout << endl;

    cout << v.size() << endl;               //输出vector数组中元素的个数  

    while (!v.empty())                      //判断v是否为空  
        v.pop_back();                       //删除v中最后一个元素  

    v1.clear();                             //清空vector数组v1  

    v.swap(v2);                             //交换v和v2  
    getchar();
    return 0;
}

程序执行结果:
这里写图片描述

priority_queue

#include <iostream>
#include <string>
#include <queue>
#include <time.h>
#include <algorithm>
#include <functional>
using namespace std;

typedef pair<int, int> int2;
struct cmp{
    bool operator() (int2 a, int2 b){
        return a.first < b.first;
    }
};

int main()
{
    priority_queue<int2, vector<int2>, cmp> p1;//降序排列
    //priority_queue<int2, vector<int2>, less<int2>> p1;//降序排列
    //priority_queue<int2, vector<int2>, greater<int2>> p1;//升序排列
    p1.push(int2(1, 2));
    p1.push(int2(3, 4));
    p1.push(int2(2, 8));
    p1.push(int2(5, 0));
    for (int i = 0; i < 4; i++)
    {
        cout << p1.top().first << " , " << p1.top().second << endl;
        p1.pop();
    }
    getchar();
    return 0;
}

程序执行结果:
这里写图片描述

map

map内建一颗红黑数(一种非常严格意义上的平衡二叉数)
1、数据插入

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;
    //插入数据方式1
    //mapStudent.insert(pair<int, string>(1, "student_one"));
    //mapStudent.insert(pair<int, string>(2, "student_two"));
    //mapStudent.insert(pair<int, string>(3, "student_three"));
    //插入数据方式2
    //mapStudent.insert(map<int, string>::value_type (1, "student_one"));
    //mapStudent.insert(map<int, string>::value_type (2, "student_two"));
    //mapStudent.insert(map<int, string>::value_type (3, "student_three"));
    //插入数据方式3
    mapStudent[1] =  "student_one";
    mapStudent[2] =  "student_two";
    mapStudent[3] =  "student_three";

    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "  " << iter->second << endl;
    }
    //int nSize = mapStudent.size();
    //for (int nIndex = 0; nIndex <= nSize; nIndex++)
    //{
    //  cout << mapStudent[nIndex] << endl;
    //}
    getchar();
    return 0;
}

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值。

mapStudent.insert(map<int, string>::value_type (1, “student_one”));
mapStudent.insert(map<int, string>::value_type (1, “student_two”));

上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下

Pair<map<int, string>::iterator, bool> Insert_Pair;
Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, “student_one”));

我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。
2、map的大小

int nSize = mapStudent.size();

3、数据遍历
见上面代码
4、数据查找
第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;

    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));

    map<int, string>::iterator  iter;
    iter = mapStudent.find(1);
    if (iter != mapStudent.end())
    {
        cout  << "Find, the value is " << iter->second << endl;
    }
    else
    {
        cout << "Not Find!" << endl;
    }
    getchar();
    return 0;
}

第三种:
Lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)
Upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)
5、数据清空与判空
清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map
程序执行结果:
6、数据的删除
这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法

#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));

    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    //mapStudent.erase(iter);


    //如果要删除1,用关键字删除
    //int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0

    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "  " << iter->second << endl;
    }

    //用迭代器,成片的删除
    //一下代码把整个map清空
    mapStudent.erase(mapStudent.find(1), mapStudent.find(2));
    //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合


    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "  " << iter->second << endl;
    }

    getchar();
    return 0;

}

这里写图片描述
7、排序
排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题
第一种:小于号重载,程序举例
以自个研究

#include <map>
#include <string>
#include <iostream>
using namespace std;

typedef struct tagStudentInfo
{
    int       nID;
    string   strName;
    bool operator < (tagStudentInfo const& _A) const
    {
        //这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序
        if (nID < _A.nID)  return true;
        if (nID == _A.nID) return strName.compare(_A.strName) < 0;
        return false;
    }
}StudentInfo, *PStudentInfo;  //学生信息

int main()
{
    int nSize;
    //用学生信息映射分数
    map<StudentInfo, int>mapStudent;
    map<StudentInfo, int>::iterator iter;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first.nID << " " << iter->first.strName << " " << iter->second << endl;
    }
    getchar();
    return 0;
}

这里写图片描述
第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明

#include <map>
#include <string>
#include <iostream>
using namespace std;

typedef struct tagStudentInfo
{
    int       nID;
    string   strName;
    //bool operator < (tagStudentInfo const& _A) const
    //{
    //  //这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序
    //  if (nID < _A.nID)  return true;
    //  if (nID == _A.nID) return strName.compare(_A.strName) < 0;
    //  return false;
    //}
}StudentInfo;  //学生信息

class sort
{
public:
    bool operator() (StudentInfo const &_A, StudentInfo const &_B) const
    {
        if(_A.nID < _B.nID) return true;
        if(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;
        return false;
    }
};

int main()
{
    int nSize;
    //用学生信息映射分数
    //map<StudentInfo, int>mapStudent;
    map<StudentInfo, int, sort>mapStudent;
    map<StudentInfo, int>::iterator iter;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first.nID << " " << iter->first.strName << " " << iter->second << endl;
    }
    getchar();
    return 0;
}

这里写图片描述
8、另外
由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。
还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方很费内存了吧。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值