数据结构和算法之map/set

数据结构和算法之map/set

map和set都是STL关联容器的一种,一般当用来快速查找一个元素是否存在或者是否重复,可以通过所谓的哈希集合和哈希映射来解决。除了熟悉各自的底层原理之外,也要会灵活的使用各个容器。

map

几个需要熟记的点

  1. 通过key-value实现映射功能,底层实现是红黑树,而key是有序的,并且不可重复的,查询和增删的效率都是o(logn)。

使用
按照程序来介绍

//包含头文件
#include<map>
//创建+初始化
map<type(key),type(value)>mymap;
map<int,string>mymap{{1,"1"}}
map<int,string>newmymap(mymap);
map<int,string>newmymap(++mymap.begin(),mymap.end());
//迭代器
//用法:++p,p++,--p,p--,*p,迭代器之间只能==和!=进行比较
for(auto iter=mymap.begin();iter!=mymap.end();iter++){
	cout<<iter->first<<iter->second<<endl;

插入元素
insert和[];[]:若 map 容器内部没有存储以 [ ] 运算符内指定数据为键的键值对,则使用 [ ] 运算符会向当前 map 容器中添加一个新的键值对。insert先来看下源码。
其中value_type为pair类型的数据。

pair<iterator,bool>insert(const value_type&x){return.. }
iterator insert (const_iterator position, const value_type& val)
..
int main() {

	map<int, string>mymap{ {1,"1"} };
	pair<int, string>value(2, "2");
	pair<int, string>value1(0, "5");
	mymap.insert(value);
	mymap.insert(++mymap.begin(), value1);
	mymap[3] = "3";
	for (auto iter = mymap.begin(); iter != mymap.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	return 0;
	
}

在这里插入图片描述
查找一个元素
常用find和count.find(key):在map容器中查找键值为key的键值对,成功找到返回指向该键值对的双向迭代器,反之,返回和end()一样的迭代器。
count:查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。
//如果想查找一个key是否存在,一般有两种写法:
if (hash.find(key) != hash.end()),说明key存在
if (hash.count(key) != 0)

int main() {
	map<int, string>mymap{ {1,"1"} };
	pair<int, string>value(2, "2");
	pair<int, string>value1(0, "5");
	mymap.insert(value);
	mymap.insert(++mymap.begin(), value1);
	mymap[3] = "3";
	mymap[1] = "a";
	for (auto iter = mymap.begin(); iter != mymap.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	int a=mymap.count(1);
	cout << a;
	auto it = mymap.find(1);
	if (it != mymap.end()) {
		cout << "存在"<<endl;
	}
	auto it1 = mymap.find(6);
	if (it1 != mymap.end()) {
		cout << "key不存在不会输出这部分";
	}
	if (mymap.count(1) != 0) {
		cout << "存在"<<endl;
	}
	return 0;
}

在这里插入图片描述

修改value
利用mymap.[key]:如果key不存在就会将key添加进去
利用mymap.at(key):会检测key,不存在就会抛出异常
在这里插入图片描述

删除键值对
迭代器失效问题

C++11
(1) 
iterator  erase (const_iterator position);
(2) 
size_type erase (const key_type& k);
(3) 
iterator  erase (const_iterator first, const_iterator last);
int main() {
	map<int, string>mymap{ {1,"1"} };
	pair<int, string>value(2, "2");
	pair<int, string>value1(0, "5");
	mymap.insert(value);
	mymap.insert(++mymap.begin(), value1);
	mymap[3] = "3";
	mymap[1] = "a";
	for (auto iter = mymap.begin(); iter != mymap.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	mymap.erase(++mymap.begin());
	mymap.erase(2);
	for (auto iter = mymap.begin(); iter != mymap.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	mymap.erase(mymap.begin(), mymap.end());
	for (auto iter = mymap.begin(); iter != mymap.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	return 0;
}

在这里插入图片描述

其他

//统计key出现的频率
static bool cmp(const pair<int, int>&a, const pair<int, int>&b) {
	return a.second > b.second;// 按照频率从大到小排序
}
int main() {
	map<int, int>myhash;
	//统计value出现的频率
	vector<int>ans{ 1,2,3,1,2,3,1,2,3,1,2,2 ,5,6};
	for (int i = 0; i < ans.size(); i++) {
		myhash[ans[i]]++;
	}
	cout << myhash[1] << endl;
	//找出value最大的,善于利用pair
	int m = INT_MIN;
	for (auto iter = myhash.begin(); iter != myhash.end(); iter++) {
		if (iter->second > m) {
			m = iter->second;
		}
	}
	cout << m<<endl;
	//对value排序,要先转成vector,自定义排序方式
	vector<pair<int, int>>vec(myhash.begin(), myhash.end());
	sort(vec.begin(), vec.end(), cmp);
	for (auto iter = vec.begin(); iter != vec.end(); iter++) {
		cout << iter->first ;
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

unordered_map

  1. 同样通过key-value实现映射功能,不过底层实现是散列表,通过将关键码映射到hash表中的一个位置来访问记录,查找o(1),海量数据处理经常使用。元素的排序是无序的,key也不可重复。(LRU哈希链表就可以实现有序)

set

  1. key和value包装在一起,key就是value。底层也是红黑树,也是key有序,查询效率也是o(logn)和map不同,因为不是键值对的形式,所以也就没有[]这个插入方式,另外,map是key不可重复,set是值不可重复(key-value合一)。

unordered_set

  1. 底层实现是哈希表,元素是无序的,查询和增删效率是O(1)。

经典题型:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值