STL 关联容器

1. 映射

在这里插入图片描述

  • 最大的优点就是找东西快,检索效率高,因为内部的平衡有序二叉树(红黑树)。
  • 从红黑树的任何一个节点往下看,左右子树的层级可以差一层但不能超过一层。
  • 找1的话,从根节点往下看,1小于3,找左子树,1又小于2,找左子树,找到1。只找了两次,这就不是线性级的效率,而是对数级别的效率,一砍砍一半。
    t

在这里插入图片描述

  • 映射容器中的节点们的物理模型是红黑树,每个节点都是pair对象,pair对象有first和second构成。
  • 迭代器it中的当前指向,指向的是容器的节点,*it是节点的引用, 而映射容器中的每个节点都是pair对象,所以可以理解为映射的迭代器相当于指向 pair对象的指针。

在这里插入图片描述

  • 映射中的键不能改(要是改了红黑树就不是红黑树了)。而且每当添加一个节点,可能就会有好多节点的顺序需要发生变化,构建和修改性能差。
  • 上图中的insert不是重载,而是不同的写法
    • 1 利用pair类的构造函数来构造一个pair对象
    • 2 make_pair函数来构造pair对象
  • find不是全局那个,而是映射容器的成员函数,利用红黑树去找, 贼快。
#include <iostream>
#include <map>

using namespace std;
class Candidate{
public:
    Candidate(string name = ""):m_name(name), m_vote(0){}
    string m_name;
    int m_vote;
};
void print(map<char, Candidate>& m){
    typedef map<char, Candidate>::iterator IT;
    for(IT it = m.begin(); it != m.end(); ++it){
        cout << "(" << (*it).first<< ")" << (*it).second.m_name << ' ';
    }
    cout << endl;
}

int main() {
    map<char, Candidate> m;
    // 3种添加映射容器节点的方式, 每加一个节点,映射容器内部会按键值重新排序
    // 1. 用pair的构造函数
    m.insert(pair<char , Candidate>('B',  Candidate("关羽")));
    // 2. 用make_pair函数
    m.insert(make_pair('A', Candidate("张飞")));
    // 3. 用下标,返回新节点值的引用
    m['C'] = Candidate("赵云");
    
    
    typedef map<char, Candidate>::iterator IT;
    // 让5个人进行投票
    for(int i = 0; i < 5; i++){
        print(m);
        char ch;
        cin >> ch;
        // find, 成功返回找到的迭代器, 失败返回终止迭代
        IT fit = m.find(ch);
        if(fit == m.end()){
            cout << "废票" << endl;
            continue;
        }
        ++(*fit).second.m_vote;
    }
    for(IT it=m.begin(); it != m.end(); ++it){
        cout << (*it).second.m_name << ":" << (*it).second.m_vote << endl;
    }
    return 0;
}
$ ./a.out 
(A)张飞 (B)关羽 (C)赵云 
A
(A)张飞 (B)关羽 (C)赵云 
1
废票
(A)张飞 (B)关羽 (C)赵云 
A
(A)张飞 (B)关羽 (C)赵云 
C
(A)张飞 (B)关羽 (C)赵云 
B
张飞:2
关羽:1
赵云:1

2. 多重映射

表示一对多的逻辑关系, 允许键重复的映射,所以不支持下标运算,容器内部也是红黑树的逻辑结构,每个节点也是pair对象。

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

int main() {
    multimap<string, int> m;
    m.insert(make_pair("张飞", 100));
    m.insert(make_pair("刘备", 100));
    m.insert(make_pair("薛辉", 100));
    m.insert(make_pair("张飞", 80));
    m.insert(make_pair("刘备", 70));
    m.insert(make_pair("薛辉", 60));
    typedef multimap<string, int>::iterator IT;
    for(IT it = m.begin(); it != m.end(); ++it){
        cout << (*it).first << ": " << (*it).second << endl;
    }
    return 0;
}
$ ./a.out 
刘备: 100
刘备: 70
张飞: 100
张飞: 80
薛辉: 100
薛辉: 60

3. 集合

在这里插入图片描述
内部结构依然是红黑树,比在向量等基本容器找东西快,毕竟对数级别搜索,这里的节点就不是键值对pair,只有value

#include <iostream>

#include <set>
using namespace std;

int main() {
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(2);
    s.insert(3);
    s.insert(3);
    cout << "size: " << s.size()<< endl;
    typedef set<int>::iterator IT;
    for(IT it = s.begin(); it != s.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}
$ ./a.out 
size: 3
1 2 3

4. 多重集合

在这里插入图片描述
内部逻辑还是红黑树结构

#include <iostream>

#include <set>
using namespace std;

int main() {
    multiset<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(2);
    s.insert(3);
    s.insert(3);
    cout << "size: " << s.size()<< endl;
    typedef multiset<int>::iterator IT;
    for(IT it = s.begin(); it != s.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}
$ ./a.out 
size: 5
1 2 2 3 3 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值