【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap

2024-08-22 13:08

本文主要是介绍【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

set

  1. 所有的元素都会根据元素的键值自动被排序。set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值。set不允许两个元素有相同的键值。

  2. 不可以通过set的迭代器改变set的元素值。因为set元素值就是其键值,关系到set元素的排列规则。如果任意改变set元素值,会严重破坏set组织。set源码中,set<T>::iterator被定义为底层RB-tree的const_iterator,杜绝写入操作。换句话,set iterators是一种constant iterators。

  3. set拥有与list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. STL set以RB-tree为底层机制,set的操作几乎都是转调用RB-tree的函数而已。

set测试代码:

  #include<set>#include<iostream>using namespace std;int main(){    int ia[] = { 5, 3, 4, 1, 6, 2 };    set<int> iset(begin(ia), end(ia));    cout << "size=" << iset.size() << endl; //size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(3);    cout << "size=" << iset.size() << endl;//size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(7);    cout << "size=" << iset.size() << endl;//size=7    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.erase(1);    cout << "size=" << iset.size() << endl;//size=6    cout << "1 count=" << iset.count(1) << endl;//1 count=0    set<int>::iterator it;    for (it = iset.begin(); it != iset.end(); ++it)        cout << *it << " "; //2 3 4 5 6 7    cout << endl;    it = find(iset.begin(), iset.end(), 3);    if (it != iset.end())        cout << "3 found" << endl;//3 found    it = find(iset.begin(), iset.end(), 1);    if (it == iset.end())        cout << "1 not found" << endl;//1 not found    system("pause");    return 0;}

map

  1. map的特性是,所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一元素被视为键值,第二元素被视为实值。map不允许两个元素拥有相同的键值。下面是<stl_pair.h>中pair定义:

      template<class T1,class T2>struct pair{    typedef T1 first_type;    typedef T2 second_type;    T1 first;    T2 second;    pair():first(T1()),second(T2()) {}    pair(const T1& a,const T2& b):first(a),second(b) {}}

  2. 不能通过map的迭代器改变map的键值,但通过map的迭代器能改变map的实值。因此map的iterators既不是一种const iterators,也不是一种mutable iterators。

  3. map拥有和list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. 由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL map即以RB-tree为底层机制。又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已。

  #include<map>#include<iostream>#include<string>using namespace std;int main(){    map<string, int> simap;            //以string为键值,以int为实值    simap[string("jjhou")] = 1;        //第一对内容是("jjhou",1)    simap[string("jerry")] = 2;        //第一对内容是("jerry",2)    simap[string("jason")] = 3;        //第一对内容是("jason",3)    simap[string("jimmy")] = 4;        //第一对内容是("jimmy",4)    pair<string, int> value(string("david"), 5);    simap.insert(value);    map<string, int>::iterator simap_iter = simap.begin();    for (; simap_iter != simap.end(); ++simap_iter)        cout << simap_iter->first << ' ' << simap_iter->second << endl;                                                                //david 5   //按键值排序                                                                //jason 3                                                                //jerry 2                                                                //jimmy 4                                                                //jjhou 1    int number = simap[string("jjhou")];    cout << number << endl;                                     //1    map<string, int>::iterator ite1;    //面对关联式容器,应使用其所提供的find函数来搜寻元素,会比STL算法find()更有效率。因为STL find()只是循序搜索    ite1 = simap.find(string("mchen"));    if (ite1 == simap.end())        cout << "mchen not found" << endl;                      //mchen not found    ite1 = simap.find(string("jerry"));    if (ite1 != simap.end())        cout << "jerry found" << endl;                         //jerry found    ite1->second = 9;    int number2 = simap[string("jerry")];    cout << number2 << endl;                                   //9}

multiset

multiset的特性以及用法和set完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  #include<set>#include<iostream>#include<vector>using namespace std;int main() {    vector<int> a = { 5, 3, 4, 1, 6, 2 };    multiset<int> iset(a.begin(),a.end());    cout << "size=" << iset.size() << endl; //size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(3); //和set区别的地方    cout << "size=" << iset.size() << endl;//size=7    cout << "3 count=" << iset.count(3) << endl;//3 count=2    iset.insert(7);    cout << "size=" << iset.size() << endl;//size=8    cout << "3 count=" << iset.count(3) << endl;//3 count=2    iset.erase(1);    cout << "size=" << iset.size() << endl;//size=7    cout << "1 count=" << iset.count(1) << endl;//1 count=0    set<int>::iterator it;    for (it = iset.begin(); it != iset.end(); ++it)        cout << *it << " "; //2 3 3 4 5 6 7    cout << endl;    it = find(iset.begin(), iset.end(), 3);    if (it != iset.end())        cout << "3 found" << endl;//3 found    it = find(iset.begin(), iset.end(), 1);    if (it == iset.end())        cout << "1 not found" << endl;//1 not found    system("pause");    return 0;}

multimap

multimap的特性以及用法与map完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  #include<map>#include<string>#include<iostream>using namespace std;int main(){    multimap<string, int> mp;//multimap没有下标操作    mp.insert(pair<string, int>("Jack", 1));    mp.insert(pair<string, int>("John", 2));    mp.insert(pair<string, int>("Lily", 3));    mp.insert(pair<string, int>("Kate", 4));//按键值字典序排序    mp.insert(pair<string, int>("Tom", 5));              //Jack 1    mp.insert(pair<string, int>("John", 8));            //John 2                                                           //John 8       map<string, int>::iterator it;                      //Kate 4    for (it = mp.begin(); it != mp.end(); ++it)         //Lily 3        cout << it->first << " " << it->second << endl; //Tom 5    it = mp.find("John");    if (it != mp.end())        cout << "John found" << endl; //John found    it->second = 8;    it = mp.find("John");    cout << it->second << endl;//8    system("pause");    return 0;}

这篇关于【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096361

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否