map和set的应用总结

目录

一、相同点

二、主要区别

三、衍生容器:multiset和multimap(使用较少)

四、有关map的oj题目

1.给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

2.输入一个英文句子,把句子中的单词(不区分大小写)按出现次数按从多到少把单词和次数在屏幕上输出来,次数一样的按照单词小写的字典序排序输出,要求能识别英文单词和句号。


一、相同点

  1. 底层数据结构
  • map和set底层均采用平衡搜索二叉树(红黑树)实现
  • 红黑树是一种自平衡二叉查找树,能保证最坏情况下基本操作的时间复杂度
  • 查找操作的时间复杂度均为O(logN)
    • 示例:当数据量为100万时,查找次数最多为20次(log₂10⁶≈20)              
  • 两者都基于key值进行排序和插入操作
  • 默认采用升序排列(可通过比较函数修改)
  • 示例:插入顺序为5,3,7时,实际存储顺序为3,5,7
  • 2.自动去重特性
  • set会自动过滤重复元素
    • 示例:插入1,2,2,3后,set中实际存储为1,2,3
  • map会忽略相同key的插入操作
    • 示例:已存在key=5的记录时,再次插入key=5的数据会被忽略
​
int arr[] = {1,2,3,1,1,2};
set<int> se(arr, arr+6);  // 自动去重后元素为{1,2,3}

map<int,int> mp;
mp.insert({1,2});
mp.insert({1,3});  // 因key重复,此操作被忽略

​
  1. 其他共同特性
  • 均属于STL关联容器
  • 迭代时保持有序性
  • 支持反向迭代器(rbegin/rend)

  • 内存分配采用动态增长方式
  1. 插入后的key值不可修改(可删除但不可更改);

  2. 自动排序特性:

    • 默认按升序排列
    • 可通过中序遍历获取有序序列

二、主要区别

  1. 头文件包含不同:map使用#include<map>,set使用#include<set>

  2. 访问方式差异:

    • map支持[]操作符进行数据插入和访问
    • set未重载[]操作符

示例说明:

map<string,string> mp;
mp["insert"];  // 若不存在则自动插入该键值对
mp["insert"] = "插入";  // 修改对应键的值
  1. 内部结构不同:
    • map<T,T>存储的是pair<T,T>键值对
    • set<T>直接存储数据T

三、衍生容器:multiset和multimap(使用较少)

主要特性:

  • 支持存储重复元素
  • find操作会返回中序遍历时遇到的第一个匹配元素

四、有关map的oj题目

1.给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

示例:

输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
    注意,按字母顺序 "i" 在 "love" 之前。

代码+注释:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<map>
#include<algorithm>//sort的头文件算法头文件
#include<vector>
#include<string>
using namespace std;
class myfunc
{
public:
    bool operator()(const pair<string, int>& i, const pair<string, int>& j)
    {
        return i.second > j.second ||
            i.second == j.second && i.first < j.first;//先比较second大的排前面
        //要是相等就比较first把较小的排前面;

    }

};//仿函数控制sort的比较逻辑
class Solution {
public:
 
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> a;
        for (auto e : words)
        {
            a[e]++;//map类的[]使用会返回value也就是key对应的map里的第二个存储值
        }
        vector<pair<string, int>>  v(a.begin(), a.end());//由于sort只能遍历随机迭代器
        //所以我们只能把map里的值其内核pair传到vector里面比较
        sort(v.begin(), v.end(), myfunc());//不使用pair自带的比较不符合题意;自己写仿函数进行比较
        vector<string> vv;
        for (int i = 0;i < k;i++)
        {
            /*vv[i] = v[i].first;*/
            vv.push_back(v[i].first);//把排好队的string输入
        }
        return vv;


    }
};


int main()
{
    Solution s;
    vector<string> wd = { "i","i","a","a","wapd","b","b","b"};
   vector<string> w = s.topKFrequent(wd, 3);
   for (auto e : w)
   {
       cout << e << " ";
   }//返回k个数量最多的单词

}

第一题的进阶版本:

2.输入一个英文句子,把句子中的单词(不区分大小写)按出现次数按从多到少把单词和次数在屏幕上输出来,次数一样的按照单词小写的字典序排序输出,要求能识别英文单词和句号。

示例:

输入:
A blockhouse is a small castle that has four openings through which to shoot.
复制
输出:
a:2
blockhouse:1
castle:1
four:1
has:1
is:1
openings:1
shoot:1
small:1
that:1
through:1
to:1
which:1

代码+注释:

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
class func
{
public:
    bool operator()(const pair<string, int> i, const pair<string, int> j)
    {
        return i.second > j.second || i.second == j.second && i.first < j.first;

    }
};//控制大小比较
int main() {
    map<string, int> mp;
    string str;
    getline(cin, str);//直接输入一整行的字符进入str中;
    for (int c = 0;c < str.size();c++)
    {
        if (str[c] != '.' && str[c] != ' ' && str[c] < 'a')
        {
            str[c] = str[c] + 32;
        }
    }//将大写字母全部转换为小写两者差32;
    size_t i = 0;
    size_t vsize = 0;
    size_t p = 0;
    p = str.find(' ');//找到第一个空格
    while (p != str.find('.'))//不是句号就不停
    {
        string word(str.begin() + i, str.begin() + p);//把句子拆分成单词
        mp[word]++;//插入map树中并进行计数;
        i = p + 1;//下一个单词开头
        p = str.find(' ',i);//下一个单词末尾的空格;
        if (p == string::npos)//要是上面的p没有找到空格,就说明只剩下一个单词了这个单词后必是句号
        {
            p = str.find('.');
            string word(str.begin() + i, str.begin() + p);
            mp[word]++;
        }
        
    }
    vector<pair<string, int>> ma(mp.begin(), mp.end());//以vector容器存储ma里的值便于遍历
    sort(ma.begin(), ma.end(), func());//sort用仿函数func()方法排序;
    for (int n = 0;n < ma.size();n++)
    {
        cout << ma[n].first << ':' << ma[n].second << endl;//输出排好的所有值;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值