数据结构map:解决桶排序问题的另一方式

抱歉太久没有更新了,只因本人还在上学,没有时间搞编程。不过寒假期间会不断创作哒!


作为C++的进阶者,相信各位对于桶排序并不陌生。然而,对于大多数进阶者来说,桶排序可以用一种STL库中的数据结构来替代。这就是我们今天要说的map



概念

map是一种关联式容器,是STL库中的一个重要数据类型,由一个键和一个值相对应构成。可以通过键查找到值,但是不可以由值找键!map的查找实现是以红黑树(一种二叉搜索树)为依托的,同时在插入数据时还会自动重载operator[]。

map的出现成为对桶排序算法的优化,由于其自动排序的特性和方便的函数操作收到了众多oier的喜爱。最初,由于指针的开发不全面,map的特性和好处尚不明显;后来auto的出现大大提升了STL库的受欢迎程度,map的遍历也因此变得更加方便快捷。


使用

与其它STL库数据结构不同的是,map的内容共有两个,分别是键和值,统称为键值对。下面是map的创建方法:map<key,value> mp;

key为键,只能出现一次;value为值,可以出现多次。(即为同键同值,同值异键)mp为库的名称,可以根据情况自行选择。

在这里声明一下,map与multimap是两个不同的数据结构,multimap具有的特点之一是可以有相同的键。若有想要了解的请戳这里

言归正传,map可以代替桶排序是因为它也可以对数据进行统计,键值的对应让值的更改可以通过键来完成。下面给出map的插入与删除操作方式:

插入:map[key] = value(对于int类型的值也可以使用自增和自减操作)
删除:mp.erase(key)(该操作会将key键的值设置成0,程序会将map的大小减一)
清空:mp.clear()

erase的更多操作请看此图:
出自oi-wiki
还有更多查询的函数,本人已经整理成一张表了,如下:

函数名返回值时间复杂度
count(x)返回容器内键为 x 的元素数量O(1)
find(x)若容器内存在键为 x 的元素,会返回该元素的迭代器;否则返回 end()O(logn)
lower_bound(x)返回指向首个不小于给定键的元素的迭代器O(logn)
upper_bound(x)返回指向首个大于给定键的元素的迭代器。若容器内所有元素均小于或等于给定键,返回 end()O(logn)
empty()返回容器是否为空O(1)
size()返回容器内元素个数O(1)

例题

题目名称
新建文件夹(1)

题目链接
ATcoder入口
ACGO入口
洛谷入口
(建议通过ATcoder、ACGO答题,因为洛谷搬运自ATcoder、ACGO,数据点不保证强度且数据测试点较少。)

思路分析
STL库模板题。本题我们可以通过STL模板库中的map来解决。新建一个map后,将类型设置为<string,int>,这样就可以通过文件夹名称查询到次数。在计数结束后,只需要判断前面是否出现名称为X的文件,如果有就输出X-1,如果没有就输出0。

代码解析
C++代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    map<string,int> mp;
    int n; cin >> n;
    while(n--){
    	string x; cin >> x;
        if(mp[x] == 0){
        	cout << x << endl;
            mp[x]++;
        }else{
            mp[x]++;
            cout << x << "(" << mp[x] - 1 << ")" << endl;
        }
    }
    return 0;
}

Python代码:

from collections import defaultdict
cnt = defaultdict(int)
for i in range(int(input())):
    s = input()
    print(f'{s}({cnt[s]})' if s in cnt else s)
    cnt[s] += 1

时间复杂度:O(n)


练习

入门题目:(入门)好串(普及-)丢失的数据
进阶题目:(普及+/提高)数字游戏(省选/NOI-)火星人
(以上题目均出自ACGO)


参考文献:oi-wiki 关联式容器

文章创作不易,麻烦各位oier点个赞支持一下吧!(我绝对不会告诉你这是在机场写的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值