C++--map和set--1027

1. 背景概念

1.1 键值对

用来表示具有一一对应关系的结构,一般包含两个成员变量,key和value

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

1.2 关联式容器

存储的是<key,value>结构的键值对。一一对应,所以数据检索的效率高。

1.3 树形关联式容器

map、set、multimap、multiset。底层使用的是平衡搜索树(红黑树),容器中的元素是一个有序的序列。

2. set

2.1 set简介

  • set是按照一定次序存储元素的容器。
  • 不允许冗余数据,所以可以去重。因为有序,数据不能修改。
  • 可以插入可以删除
  • 默认排升序
  • set中只放value,但在底层实际存放的是由<key,key>构成的键值对
  • 没有支持operator[]

2.2 set的使用

2.2.1 构造set

#include<set>
using namespace std;
int main()
{
    // 1234567
    set<int>s1;
    s1.insert(1);s1.insert(2);s1.insert(3);//...

    set<int>s2={1,2,3,4,5,6,7};

    int a[]={1,2,3,4,5,6,7};
    set<int>s3(a,a+sizeof(a)/sizeof(int));

    return 0;
}

 2.2.2 使用迭代器更新

string str={sadhjwiajh};
set<char> s4(str.begin(),str.end());

打印

void print(set<int>& s)
{
    set<int>::iterator it = s.begin();
    while (it != s.end())
    {
        //*it = 10;
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

2.2.3 升序和降序

默认都排升序

#include<set>
using namespace std;
void test2()
{
    set<int>s1={9,5,6,2,4,1,8};//升序
    
    //great<int>的使用需要包含头文件 #include <functional>
    set<int,great<int>> s2={9,5,6,2,4,1,8};//降序
    //print(s2);这里会传参报错 还是手动打印
    set<int>::iterator it = s2.begin();
    while (it != s2.end())
    {
        //*it = 10;
        cout << *it << " ";
        ++it;
    }
    cout << endl; 
    
}

2.2.4 修改

s1.insert(value);//插入value

s1.erase(value);//删除值为value的键值对,返回删除的元素的个数

s1.erase(iterator first,iterator last);//删除 迭代器区间[first,last)区间中的元素

set<int>::iterator pos=s1.find(20);

if(pos!=s1.end())

s1.earese(pos);//删除迭代器值为pos的键值对

 2.2.5 统计

s1.count(val);//返回值为value的元素个数,不存在返回0

2.2.6 lower_bound   upper_bound

lower_bound(value);//返回>=value的值的迭代器

upper_bound(value);//返回>value的值得迭代器

void test3()
{
    std::set<int> myset;
    std::set<int>::iterator itlow, itup;

    for (int i = 1; i < 10; i++) 
    	myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90

    itlow = myset.lower_bound(25); // >= val
    itup = myset.upper_bound(60);  // > val             
    cout << "["<<*itlow <<","<<*itup<<"]"<<endl;

    myset.erase(itlow, itup);                     // 10 20 70 80 90
    print(myset);
}

3. multiset

3.1 multiset介绍

  • 支持数据冗余。即不能去重。
  • 构造方法同set。
  • 使用find(value)函数时,返回的是中序遍历中第一个value值对应的键值对的迭代器。
  • 使用erase(value)时,删除所有的value值对应的键值对。

4. map

在内部,map中的元素总是按照键值key进行比较排序的
map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序
对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列
map支持下标访问符,即在[]中放入key,就可以找到与key对应的value

map默认以key的升序排列

key不能直接修改

4.1 map的使用

打印

写法一

map<string, string>::iterator it = dict.begin();
    //auto it = dict1.begin();
    while (it != dict1.end())
    {
        //cout << (*it).first << (*it).second <<endl;
        cout << it->first << it->second << endl;
        ++it;
    }
    cout << endl;

 写法二

for (const auto& kv : dict1)
    {
        cout << kv.first << ":" << kv.second << endl; 
    }
    cout << endl;

4.1.1 插入数据

方法一 实例化pair对象
    map<string, string>dict1;
    pair<string, string>kv1("sort", "排序");
    dict1.insert(kv1);
方法二 利用匿名对象
    dict1.insert(pair<string, string>("left", "左边"));
方法三 make_pair 函数模板
    dict1.insert(make_pair("right", "右边"));

 

4.1.2 map中元素的修改

s1.erase(x);//删除键值为x的键值对,返回删除的元素的个数

s1.erase(iterator first,iterator last);//删除 迭代器区间[first,last)区间中的元素

m1.find(x);//在map中查找key为x的元素,找到返回该位置的迭代器,找不到返回m1.end()

m1.count(x);//返回key为x的键值在map中的个数

4.2 更新value值的方法

方法一

void test5()
{
    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果",
        "西瓜", "苹果", "香蕉", "苹果", "香蕉","香蕉","香蕉" };
    map<string, int>countmap;
    for (auto& str : arr)
    {
        map<string, int>::iterator it = countmap.find(str);
        if (it != countmap.end())
        {
            //(*it).second++;
            it->second++;
        }
        else
        {
            countmap.insert(make_pair(str,1));
        }
    }

 

 方法二  operator[]

countmap[key];

在map中寻找key,找了就返回对应pair的value的引用。

找不到就插入一个pair<key,v()>,然后返回v()(value类型的构造函数创建的匿名对象)的引用

void test6()
{
    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果",
        "西瓜", "苹果", "香蕉", "苹果", "香蕉","香蕉","香蕉" };
    map<string, int>countmap;
    for (auto& str : arr)
    {
        countmap[str]++;
        //创建"苹果"时,value创建一个int() 默认构造函数给的值是0 
        //然后 0++ 变成1
    }


    for (const auto& kv : countmap)
    {
        cout << kv.first << ":" << kv.second << endl;
    }
    cout << endl;
}

5.multimap

multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以
重复的。

不支持operator[ ]

6. 在oj中的应用

 前K个高频单词

力扣

class Solution {
public:
    struct less
    {
        //因为是优先级队列,排降序 要写成排升序
        bool operator()(const pair<string,int>& kv1,const pair<string,int>& kv2) const
        {
            if(kv1.second<kv2.second) return true;
            if(kv1.second==kv2.second && kv1.first>kv2.first) return true;
            // def cde bcd abc
            return false;
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        map<string,int>countmap;
        for(auto& str:words)
        {
            countmap[str]++;
        }
        priority_queue<pair<string,int>,vector<pair<string,int>>, less> maxmap;
        for(auto pair:countmap)
        {
            maxmap.push(pair);
        }
        vector<string> result;
        while(k--)
        {
            result.push_back(maxmap.top().first);
            maxmap.pop();
        }
        return result;

    }
};

两个数组的交集

力扣

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
        
        // vector<int>result;
        // unordered_set<int>m1(nums1.begin(),nums1.end());
        // for(auto& e:nums2)
        // {
        //     if(m1.find(e)!=m1.end())
        //     {
        //         result.push_back(e);
        //     }
        // }
        // return result;
        //这样结果会出现 {2,2} 要的是去重之后的结果 {2}
        
        unordered_set<int>result_set;
        unordered_set<int>m1(nums1.begin(),nums1.end());
        for(auto& e:nums2)
        {
            if(m1.find(e)!=m1.end())
            {
                result_set.insert(e);
            }
        }
        return vector<int>(result_set.begin(),result_set.end());
    }
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值