八、STL中的关联容器set/multiset、map/multimap

STL中的关联容器set/multiset、map/multimap

一、set/multiset

1.1 简介

内部元素有序排列,新元素插入的位置取决于它的值,查找速度快。

除了各容器都有的函数外,还支持以下成员函数:

find: 查找等于某个值 的元素(x小于yy小于x同时不成立即为相等)
lower_bound : 查找某个下界
upper_bound : 查找某个上界
equal_range : 同时查找上界和下界
count :计算等于某个值的元素个数(x小于yy小于x同时不成立即为相等)
insert: 用以插入一个元素或一个区间

1.2 multiset的定义

template<class Key, class Pred = less<Key>,
class A = allocator<Key> >
class multiset { …… };

Pred类型的变量决定了multiset 中的元素,“一个比另一个小”是怎么定义的。multiset运行过程中,比较两个元素x,y的大小的做法,就是生成一个 Pred类型的变量,假定为 op,若表达式op(x,y) 返回值为true,则 x比y小。

Pred的缺省类型是 less< Key>。

less 模板的定义:

template < class T>
struct less : public binary_function<T, T, bool>
{ 
    bool operator()(const T& x, const T& y) { return x < y ; } const; 
};

1.3 成员函数


八、STL中的关联容器set/multiset、map/multimap_第1张图片

1.4 程序示例

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

template <class T>
void print(T first, T second)
{
    for(; first!=second; first++)
        cout<<*first<<" ";
    cout<<endl; 
}

class A
{
    private:
        int n;
    public:
        A(int n):n(n) { }
    friend bool operator<(const A & a1, const A & a2);  
    friend ostream & operator<<(ostream & o, const A & a);
    friend class MyLess;
};

bool operator<(const A & a1, const A & a2)
{
    return a1.n<a2.n;
}

ostream & operator<<(ostream & o, const A &a)
{
    o<<a.n;
    return o;
}

struct MyLess
{
    bool operator()(const A & a1, const A & a2){
        return (a1.n % 10) < (a2.n % 10);
    }
};

typedef multiset<A> MSET1;
typedef multiset<A, MyLess> MSET2; 

int main()
{
    const int SIZE = 6;
    int a[SIZE] = { 53, 4, 39, 15, 82, 22};

    MSET1 m1;
    m1.insert(a, a+SIZE);
    m1.insert(22);
    cout<<m1.count(22)<<endl;

    print(m1.begin(), m1.end());
    MSET1::iterator p = m1.find(39);
    if(p != m1.end()) cout<<"found"<<endl;

    cout<<*m1.lower_bound(22)<<", "<<*m1.upper_bound(22)<<endl;

    m1.erase(m1.lower_bound(22), m1.upper_bound(22));
    print(m1.begin(), m1.end());

    MSET2 m2;
    m2.insert(a, a+SIZE);
    print(m2.begin(), m2.end());

    set<int> s1;
    s1.insert(a, a+SIZE);
    typedef set<int>::iterator IT;
    pair<IT, bool> result;
    result = s1.insert(22);
    if(result.second) cout<<"succeed"<<endl;
    else cout<<"faild"<<endl;

    pair<IT, IT> bounds = s1.equal_range(22);
    cout<<*bounds.first<<", "<<*bounds.second<<endl;

    return 0;
}

输出:

2
4 15 22 22 39 53 82
found
22, 39
4 15 39 53 82
82 22 53 4 15 39
faild
22, 39

二、预备知识-pair模板

template<class _T1, class _T2>
struct pair
{
    typedef _T1 first_type;
    typedef _T2 second_type;
    _T1 first;
    _T2 second;
    pair(): first(), second() { }
    pair(const _T1& __a, const _T2& __b): first(__a), second(__b) { }
    template<class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p): first(__p.first), second(__p.second) { }
};

map/multimap容器里放着的都是pair模版类的对象,且按first从小到大排序。

第三个构造函数用法示例:

pair<int,int>
p(pair<double,double>(5.5,4.6));
// p.first = 5, p.second = 4

三、map/multimap

3.1 multimap定义

template<class Key, class T, class Pred = less<Key>,class A = allocator<T> >
class multimap {
    …
    typedef pair<const Key, T> value_type;
    ……
}; //Key 代表关键字的类型

multimap中的元素由 <关键字,值>组成,每个元素是一个pair对象,关键字就是first成员变量,其类型是Key。

multimap 中允许多个元素的关键字相同。元素按照first成员变量从小到大排列,缺省情况下用 less< Key> 定义关键字的“小于”关系。

3.2 程序示例

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

template <class Key, class Value>
ostream & operator << (ostream & os, const pair<Key, Value> & p)
{
    os<<"("<<p.first<<", "<<p.second<<")";
    return os;
}


int main()
{
    typedef map<int, double, less<int> > mmid;
    mmid pairs;

    cout<<pairs.count(15)<<endl;
    pairs.insert(mmid::value_type(15, 2.7));
    pairs.insert(make_pair(15, 99.3));
    cout<<pairs.count(15)<<endl;

    pairs.insert(make_pair(20, 9.3));
    mmid::iterator i;
    for(i=pairs.begin(); i!=pairs.end(); i++)
        cout<<*i<<", ";
    cout<<endl;

    int n = pairs[40];
    for(i=pairs.begin(); i!=pairs.end(); i++)
        cout<<*i<<", ";
    cout<<endl;

    pairs[15] = 6.28;
    for(i=pairs.begin(); i!=pairs.end(); i++)
        cout<<*i<<", ";
    cout<<endl;

    return 0;
}

输出:

0
1
(15, 2.7), (20, 9.3),
(15, 2.7), (20, 9.3), (40, 0),
(15, 6.28), (20, 9.3), (40, 0),

3.3 multimap例题

写一个学生成绩录入和查询系统,接受以下两种输入:

Add name id score
Query score

name是个字符串,中间没有空格,代表学生姓名。 id是个整数,代表学号。 score是个整数,表示分数。学号不会重复,分数和姓名都可能重复。两种输入交替出现。第一种输入表示要添加一个学生的信息,碰到这种输入,就记下学生的姓名、 id和分数。第二种输入表示要查询,碰到这种输入,就输出已有记录中分数比score低的最高分获得者的姓名、学号和分数。如果有多个学生都满足条件,就输出学号最大的那个学生的信息。如果找不到满足条件的学生,则输出“ Nobody”。

输入样例:

Add Jack 12 78
Query 78
Query 81
Add Percy 9 81
Add Marry 8 81
Query 82
Add Tom 11 79
Query 80
Query 81

输出结果样例:

Nobody
Jack 12 78
Percy 9 81
Tom 11 79
Tom 11 79

程序:

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

class Student
{
    public:
        struct Info
        {
            int id;
            string name;
        };
        int score;
        Info info;
};

typedef multimap<int, Student::Info> MAP_STU;

int main()
{
    MAP_STU map;
    Student stu;
    string cmd;
    while(cin>>cmd){

        if(cmd == "Add"){
            cin>>stu.info.name>>stu.info.id>>stu.score;
            map.insert(MAP_STU::value_type(stu.score, stu.info));
        }else if(cmd == "Query"){
            int score;
            cin>>score;
            MAP_STU::iterator p = map.lower_bound(score);
            if(p!=map.begin()){
                --p;
                MAP_STU::iterator maxp = p;
                int maxId = p->second.id;
                for(; p!=map.begin() && p->first==score; --p){
                    if(p->second.id > maxId){
                        maxp = p;
                        maxId = p->second.id;
                    }
                }
                //如果p=map.begin 
                if(p->first == score && p->second.id > maxId){
                    maxp = p;
                    maxId = p->second.id;
                }
                cout<<maxp->second.name<<" "<<maxp->second.id<<" "<<maxp->first<<endl;
            }else{
                cout<<"No body"<<endl;
            }

        }

    }

    return 0;
}

你可能感兴趣的:(C++,map,set,STL)