C++中“map和set”相关内容整理分析

1. 关联式容器

STL将自己的数据结构分为六大组件,
容器分为:
序列式容器:vector list …
类似于数据结构中的线性表,数据和数据之间没有关联,为了单纯的存储数据,

关联式容器:map和set…
底层是:平衡搜索树,数据和数据之间具有强烈的关系

2. 键值对

3. 树形结构的关联式容器

4. set 和 map简单使用:

set简单使用

insert

#include<set>
#include<iostream>
using namespace std;
void test_set1()
{
	set<int> s;
	s.insert(1);
	s.insert(5);
	s.insert(3);
	s.insert(4);
	s.insert(2);
	s.insert(2);

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

	auto it1 = s.begin();
	for (auto it1 : s)
	{
		cout << it1 << " ";
	}
	cout << endl;
}
int main()
{
	test_set1();
	return 0;
}

1 2 3 4 5
1 2 3 4 5
所以走的是中序
因为没有重复,所以排序+去重

erase

在这里插入图片描述

#include<set>
#include<iostream>
using namespace std;
void test_set1()
{
	set<int> s;
	s.insert(1);
	s.insert(5);
	s.insert(3);
	s.insert(4);
	s.insert(2);
	s.insert(2);

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

	set<int>::iterator pos = s.find(2);
	//当没有找到这个值的时候,还要删除,就会报错
	if (pos != s.end()) {
		//pos必须是一个有效位置的迭代器
		s.erase(pos);
	}
	//直接使用值也是可以的
	//找到就删除,没有找到就直接返回
	s.erase(3);
	s.erase(30);

	auto it1 = s.begin();
	for (auto it1 : s){
		cout << it1 << " ";
	}
	cout << endl;
}
int main()
{
	test_set1();
	return 0;
}

vs multiset

set是排序+去重
multiset是排序
multi:多种

find

void test(){
	multiset<int> s;
	s.insert(2);
	s.insert(1);
	s.insert(5);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(2);
	s.insert(2);

	//找到的是那个2?
	//multiset<int>::iterator pos = s.find(2);
	auto pos = s.find(2);
	while (pos != s.end())
	{
		cout << *pos << " ";
		++pos;
	}
	cout << endl;
}
//2 2 2 2 3 4 5
//中序的第一个一,不一定是叶子
int main()
{
	test();
	return 0;
}

erase

void test() {
	multiset<int> s;
	s.insert(2);
	s.insert(1);
	s.insert(5);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(2);
	s.insert(2);

	auto pos = s.find(2);
	//方式一:
	//while (pos != s.end() && *pos==2)
	//{
	//	auto newpos = pos;
	//	newpos++;
	//	s.erase(pos);
	//	pos = newpos;
	//}
	
	//方式二:
	cout << s.erase(2) << endl;
	//4
	//1 3 4 5

	multiset<int>::iterator it1 = s.begin();
	for (auto it1 : s) {
		cout << it1 << " ";
	}
	cout << endl;
}
int main()
{
	test();
	return 0;
}

map的简单使用

insert

在这里插入图片描述

void test1()
{
	map<string, string> dict;
	pair<string, string> kv1("红色", "red");
	dict.insert(kv1);
	dict.insert(pair<string, string>("蓝色","blue"));
	//自动推导类型
	dict.insert(make_pair("黄色", "yellow"));//推荐
	dict.insert({"苹果","apple"});//C++11语法

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

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

int main()
{
	test1();
	return 0;
}

operator[]

void test()
{
	string arr[] = { "苹果","香蕉", "苹果", "梨", "苹果", "苹果" };
	map<string, int> countMap;
	//first
	//for (auto& str : arr)
	//{
	//	auto ret = countMap.find(str);
	//	if (ret == countMap.end())//没有找到
	//	{
	//		countMap.insert(make_pair(str, 1));
	//	}
	//	else {
	//		ret->second++;
	//	}
	//}
	//second
	//for (auto& str : arr)
	//{
	//	auto kv = countMap.insert(make_pair(str, 1));
	//	if (kv.second==false) {
	//		kv.first->second++;
	//	}
	//}
	//third
	for (auto& str : arr){
		countMap[str]++;
	}
	for (auto& kv : countMap){
		cout << kv.first << " " << kv.second << endl;
	}
}

在这里插入图片描述
operator[]功能:
1.插入
2.查找(key 对应的 value)
3.修改(key 对应的 value)

void test()
{
	map<string, string> dict;
	dict.insert(make_pair("right", "右边"));
	dict.insert(make_pair("left", "左边"));
	dict.insert(make_pair("left", "中间"));//插入,但是不成功

	dict["left"] = "做边";//修改,成功
	dict["test"];//插入,test对应的value=""
	dict["right"];
	cout << dict["mid"] << endl;//先插入,然后在输出""
}
int main()
{
	test();
	return 0;
}

multimap

void test()
{
	multimap<string, string> dict;
	dict.insert(make_pair("left", "左边"));
	dict.insert(make_pair("left", "左边"));
	dict.insert(make_pair("left", "中间"));
	dict.insert(make_pair("right", "右边"));
	for (auto& kv : dict) {
		cout << kv.first << " " << kv.second << endl;
	}
}
//left 左边
//left 左边
//left 中间
//right 右边
int main()
{
	test();
	return 0;
}

延伸:
multimap没有[]
查找也是第一个

5. set和map相关题

1.map关于second的排序

一vector

struct CountVal
{
	bool operator()(const pair<string, int>& left,const pair<string,int>& right)
	{
		return left.second > right.second;
	}

};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
	map<string, int> countMap;
	for (auto& str : fruits)
	{
		countMap[str]++;
	}

	//1.数据量不大,排序
	vector<pair<string, int>> sortV;
	for (auto& kv : countMap)
	{
		sortV.push_back(kv);
	}
	sort(sortV.begin(), sortV.end(), CountVal());
	
	for (int i = 0; i < k; i++)
	{
		cout << sortV[i].first << ":" << sortV[i].second << endl;
	}
}
int main()
{
	vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
		"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
	GetFavoriteFruit(arr, 3);
	return 0;
}

二vector+迭代器

struct CountInterVal
{
	bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
		return left->second > right->second;
	}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
	map<string, int> countMap;
	for (auto& str : fruits)
		countMap[str]++;

	vector<map<string, int>::iterator> sortV;
	auto it = countMap.begin();
	while (it != countMap.end()){
		sortV.push_back(it);
		++it;
	}
	sort(sortV.begin(), sortV.end(), CountInterVal());

	for (int i = 0; i < k; i++)
		cout << sortV[i]->first << ":" << sortV[i]->second << endl;
}
int main()
{
	vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
		"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
	GetFavoriteFruit(arr, 3);
	return 0;
}

三multimap+迭代器

struct CountInterVal
{
	bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
		return left->second > right->second;
	}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
	map<string, int> countMap;
	for (auto& str : fruits)
		countMap[str]++;
	multimap<int,string,greater<int>> sortMap;
	for (auto& kv : countMap) {
		sortMap.insert(make_pair(kv.second,kv.first));
	}
}
int main()
{
	vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
		"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
	GetFavoriteFruit(arr, 3);
	return 0;
}

四优先级队列

struct CountVal
{
	bool operator()(const pair<string, int>& left, const pair<string, int>& right)
	{
		return left.second < right.second;
	}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
	map<string, int> countMap;
	for (auto& str : fruits)
		countMap[str]++;
	
	priority_queue<pair<string, int>, vector<pair<string, int>>, CountVal> pq;
	for (auto& kv : countMap) {
		pq.push(kv);
	}
	while (k--) {
		cout << pq.top().first << pq.top().second << endl;
		pq.pop();
	}
}
int main()
{
	vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
		"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
	GetFavoriteFruit(arr, 3);
	return 0;
}

五优先级队列+迭代器

struct CountIterVal
{
	bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
		return left->second < right->second;
	}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
	map<string, int> countMap;
	for (auto& str : fruits)
		countMap[str]++;

	priority_queue<map<string, int>::iterator, vector<map<string, int>::iterator>, CountIterVal> pq;
	auto it = countMap.begin();
	while (it != countMap.end()){
		pq.push(it);
		++it;
	}

	while (k--){
		cout << pq.top()->first << ":" << pq.top()->second << endl;
		pq.pop();
	}
	cout << endl;
}
int main()
{
	vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
		"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
	GetFavoriteFruit(arr, 3);
	return 0;
}

2.前K个高频单词

链接: 前K个高频单词
在这里插入图片描述

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
    map<string,int> CountMap;
    for(auto& str:words) CountMap[str]++;

    multimap<int,string,greater<int>> sortMap;
    for(auto& kv:CountMap)
        sortMap.insert(make_pair(kv.second,kv.first));
    vector<string> v;
    auto it = sortMap.begin();
    while(k--){
        v.push_back(it->second);
        ++it;
    }
    return v;
    }
};

4. 底层结构

4.1AVL树/高度平衡二叉搜索树

概念:
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下
当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是AVL树
左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
在这里插入图片描述
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O( log2n) ,搜索时间复杂度O( log2n)。

4.2简单模拟实现链接:

链接: C++中“AVL”树的模拟实现以及实现中遇见的问题

4.3红黑树

概念:

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的
在这里插入图片描述

性质:

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的(说明:树中没有连续的红色节点)
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点(说明:每条路径黑色节点的数量相等)
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

在这里插入图片描述

思考:为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍?

最短路径:全黑
最长路径:一黑一红

假设每条路径黑节点的数量是:N
N <= 任意路径长度 <= 2N

底层简单模拟实现,以及实现中遇见的问题

https://blog.csdn.net/sakeww/article/details/125036961

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值