C++之STL set和map解析(4)---《C++ STL》

8 篇文章 0 订阅

详情见:https://zcheng.ren/2016/09/09/STLSetAndMap/

今天的内容需要用到红黑树的知识,因为set和map都是通过RBTree实现的,因此,推荐大家先看这两篇博客,理解红黑树的性质:

一、set模块:

  1. set以红黑树作为其底层容器,实现set其实就在调用红黑树的接口而已;
  2. 所有元素都会被自动排序,因为RBTree是一种加限定使其平衡的一种二叉搜素树;
  3. 键值不许重复,不能出现重复元素,set中键就是值啦;
  4. 通过迭代器无法改变set的值,因为set的值就是键,如果需要修改,则需要删除对应的键节点,然后调整set的结构,然后插入节点之后又需要调整set的结构,这样可能(大部分情况)会导致迭代器失效,所以set中不许修改set中的值;
  5. set中的迭代器是const的,不允许改变;
    6. set的迭代器一旦被赋值,便不会改变了,容易出现问题。

下面我们来看第5个特性的问题实例,不同情况:
1)最大的元素之后设置为set的begin():

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

int main(){
    set<int> s;
    s.insert(100);
    set<int>::iterator iter = s.begin();
    s.insert(20);
    s.insert(80);
    while (iter != s.end()){
        cout << *(iter++) << endl;
    }
    return 0;
}

运行结果:
这里写图片描述
2)中间的元素之后设置为set的begin():

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

int main(){
    set<int> s;
    s.insert(80);
    set<int>::iterator iter = s.begin();
    s.insert(20);
    s.insert(100);
    while (iter != s.end()){
        cout << *(iter++) << endl;
    }
    return 0;
}

运行结果:
这里写图片描述
3)最小的元素之后设置为set的begin():

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

int main(){
    set<int> s;
    s.insert(20);
    set<int>::iterator iter = s.begin();
    s.insert(80);
    s.insert(100);
    while (iter != s.end()){
        cout << *(iter++) << endl;
    }
    return 0;
}

运行结果:
这里写图片描述

结果分析:set是通过RBTree实现的,然而由于set的iter在赋值之后就不会变了,而新插入元素之后会调整RBTree的结构,导致起先设置的begin iterator不是实际中该有的,然后其就损失了一些部分,导致上述情况发生。

multiset模块:
multiset相较set来说,只是键值重复而已,multiset和set的insert函数调用了RBTree的不同的函数接口,multiset调用insert_euqal,set调用insert_unique,因此不同啦!

二、map模块

1)map中不允许键重复,值无所谓的;
2)所有元素是通过键值对方式存在的;
3)map中的所有元素都是排序过的,通过键排序哈;
4)map中的键不许修改,因为map中的RBTree的结构是通过键实现的,和set中不允许修改值的原因一样的,因此无法修改的,但其中的值可是想怎样都可以怎样的啦;
5)map是通过RBTree(红黑树)的结构实现的。

map的实现结构(简易版):
这里写图片描述
现在我们证明一下map的第3个特性:

#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <string>
using namespace std;
int main(){
    map<int, string> m;
    m.insert(map<int, string>::value_type(20,"hello"));
    m.insert(map<int, string>::value_type(9, "yello"));
    m.insert(map<int, string>::value_type(30, "xello"));

    map<int, string>::iterator iterM=m.begin();
    while (iterM!=m.end()){
        cout << iterM->first << " " << iterM->second << endl;
        iterM++;
    }
    cout << endl;
    return 0;
}

运行结果:
这里写图片描述
multimap模块
multimap允许插入的键相同,因为multimap和map的insert函数调用的是RBTree的不同的insert接口,multimap调用insert_equal(),而map调用insert_unique(),其他与map相同!

注意:
multiset和multimap都允许在RBTree中插入相同的元素,所以它们的RBTree不是二叉(排序)搜索树!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值