从C语言到C++_26(set+map+multiset+multimap)力扣692+349+牛客_单词识别

news2024/11/24 15:31:20

目录

1. 关联式容器

1.1 树形结构的关联式容器

2. set的相关介绍

2.1 set的构造和迭代器

2.2 set的容量和操作函数

2.3 set使用代码

2.4 multiset使用

3. map的相关介绍

3.1 键值对

3.2 map的构造和迭代器

3.3 map的容量和操作函数

3.4 map使用代码

3.5 multimap使用

4. 笔试OJ题

692. 前K个高频单词 - 力扣(LeetCode)

priority_queue解析代码:

sort解析代码:

stable_sort解析代码:

multimap解析代码:

349. 两个数组的交集 - 力扣(LeetCode)

set解析代码:

单词识别_牛客题霸_牛客网 (nowcoder.com)

set解析代码:

multimap解析代码:

5. 笔试选择题

答案:

本章完。


1. 关联式容器

我们已经接触过STL中的部分容器,比如:vector、list、deque、这些容器统称为序列式容器,

因为其底层为线性序列的数据结构,里面存储的是元素本身

关联式容器也是用来存储数据的,与序列式容器不同的是,

其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

总结:
1、容器本身底层采用线性序列存储数据的结构叫做序列式容器,比如vector、list
2、容器本身底层采用键值对存储数据的结构叫做关联式容器,比如map、set

1.1 树形结构的关联式容器

根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。

树型结构的关联式容器主要有四种:map、set、multimap、multiset。

这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,

容器中的元素是一个有序的序列。下面一依次介绍每一个容器。

2. set的相关介绍

1. set是按照一定次序存储元素的容器
2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行
排序。
4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
子集进行直接迭代。
5. set在底层是用二叉搜索树(红黑树)实现的。

 注意:
1. 与map / multimap不同,map / multimap中存储的是真正的键值对<key, value>,set中只放
value,但在底层实际存放的是由<value, value>构成的键值对。
2. set中插入元素时,只需要插入value即可,不需要构造键值对。
3. set中的元素不可以重复(因此可以使用set进行去重)。
4. 使用set的迭代器遍历set中的元素,可以得到有序序列
5. set中的元素默认按照小于来比较
6. set中查找某个元素,时间复杂度为:O(logN)
7. set中的元素不允许修改(为什么 ? )

2.1 set的构造和迭代器

2.2 set的容量和操作函数

2.3 set使用代码

#include <iostream>
#include <set>
#include <map>
#include <functional>
using namespace std;

void test_set()
{
	//set<int> s;
	//s.insert(4);
	//s.insert(2);
	//s.insert(1);

	//set<int> s = { 1, 2, 1, 6, 3, 8, 5 }; C++11

	int arr[] = { 1, 2, 1, 6, 3, 8, 5 };
	set<int> s(arr, arr + sizeof(arr) / sizeof(arr[0]));
	//set<int, greater<int>> s(arr, arr + sizeof(arr) / sizeof(arr[0]));

	// 排序 + 去重
	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		//*it = 10; // 和前面二叉搜索树一样不能修改
		cout << *it << " ";
		++it;
	}
	cout << endl;

	for (const auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << "size = " << s.size() << endl;

	s.erase(2);
	s.erase(30); // 直接用erase,没有删除的元素什么事都没
	for (const auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	set<int>::iterator pos = s.find(20); // 用find删除,要判断,不然崩溃
	if (pos != s.end())
	{
		s.erase(pos);
	}
	pos = s.find(8); // 用find删除,要判断,不然崩溃
	if (pos != s.end())
	{
		s.erase(pos);
	}

	for (const auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << "size = " << s.size() << endl;
	cout << s.empty() << endl;
}

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

2.4 multiset使用

set是不允许的键值冗余的,而multiset是允许键值冗余的,也就这个区别而已:

void test_multiset()
{
	int arr[] = { 1, 2, 1, 6, 3, 8, 5, 3, 3 };
	multiset<int> ms(arr, arr + sizeof(arr) / sizeof(arr[0]));
	for (const auto& e : ms)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << ms.count(1) << endl; // set也有这个接口,是为了和multiset一致,在set中可以用来找元素在不在

	// find时,如果有多个值,返回中序的第一个
	auto pos = ms.find(3);
	while (pos != ms.end())
	{
		cout << *pos << " ";
		++pos; // ++是+到中序的下一个
	}
	cout << endl;

	ms.erase(3); // 删除所有的3
	for (const auto& e : ms)
	{
		cout << e << " ";
	}
	cout << endl;

	pos = ms.find(1); // 删除一个1
	if (pos != ms.end())
	{
		ms.erase(pos);
	}
	for (const auto& e : ms)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	//test_set();
	test_multiset();
	
	return 0;
}

3. map的相关介绍

 1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的
内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
value_type绑定在一起,为其取别名称为pair :
typedef pair<const key, T> value_type;
3. 在内部,map中的元素总是按照键值key进行比较排序的。
4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序
对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

3.1 键值对

map中存储的键值对介绍:

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

key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,

那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是壹壹

对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() : first(T1()), second(T2())
	{}

	pair(const T1& a, const T2& b) : first(a), second(b)
	{}
};

常用的:

3.2 map的构造和迭代器

 

key: 键值对中key的类型

T: 键值对中value的类型

Compare : 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,

一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),

需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的

空间配置器

注意:在使用map时,需要包含头文件#include <map>,键值对的头文件也在里面了。 

3.3 map的容量和操作函数

方括号是map的很特别的操作,其它不是连续空间存储的都没有,但是map的方括号

和普通的也不一样,它返回的是键值对中key对应的value的引用。

当key不在map中时,通过operator[ ] 获取对应value时会发生什么问题?

 在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,

都是通过key找到与key对应的value然后返回其引用,

不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,

返回该默认value,at()函数直接抛异常。

上面方括号调用的那句代码分成两句就是这样:

3.4 map使用代码

用map来创建字典:

void test_map1()
{
	map<string, string> dict;
	//pair<string, string> kv1("sort", "排序");
	//dict.insert(kv1);

	dict.insert(pair<string, string>("sort", "排序")); // 等价于上面注释
	dict.insert(pair<string, string>("test", "测试"));
	dict.insert(pair<string, string>("string", "字符串"));
	typedef pair<string, string> DictKV;
	dict.insert(DictKV("string", "xxx"));
	dict.insert(make_pair("left", "左边")); // 常用这种插入
	dict["right"] = "右边"; // 更常用这种插入

	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin(); // 等价于上面注释
	while (it != dict.end())
	{
		//cout << (*it).first << (*it).second <<endl;
		cout << it->first << ":" << it->second << endl; // 等价于上面注释
		++it;
	}
	cout << endl;

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

int main()
{
	//test_set();
	//test_multiset();
	test_map1();

	return 0;
}

用map来计算次数:

void test_map2()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
	//map<string, int> countMap;
	//for (const 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));
	//	}
	//}
	map<string, int> countMap;
	for (const auto& str : arr) // 等同于上面一大段注释
	{
		// 1、str不在countMap中,插入pair(str, int()),然后在对返回次数++
		// 2、str在countMap中,返回value(次数)的引用,次数++;
		countMap[str]++;
	}

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

int main()
{
	//test_set();
	//test_multiset();
	//test_map1();
	test_map2();

	return 0;
}

3.5 multimap使用

multimap和multiset一样是允许键值冗余的,

1. multimap是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,
    value>,其中多个键值对之间的key是可以重复的。
2. 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内
    容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,
    value_type是组合key和value的键值对 :
typedef pair<const Key, T> value_type;
3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对
key进行排序的。
4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代
器直接遍历multimap中的元素可以得到关于key有序的序列。
5. multimap在底层用二叉搜索树(红黑树)来实现。
注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以
重复的。

multimap中的接口可以参考map,功能都是类似的。
注意:
1. multimap中的key是可以重复的。
2. multimap中的元素默认将key按照小于来比较
3. multimap中没有重载operator[]操作。
4. 使用时与map包含的头文件相同:

void test_multimap()
{
	map<string, string> dict;
	dict.insert(make_pair("sort", "排序"));
	dict["insert"];
	dict["insert"] = "插入";
	dict["left"] = "左边";
	dict["left"] = "左边";
	for (const auto& kv : dict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << dict.size() << endl;

	multimap<string, string> mdict;
	mdict.insert(make_pair("sort", "排序"));
	mdict.insert(make_pair("right", "右边"));
	mdict.insert(make_pair("right", "正确"));
	mdict.insert(make_pair("right", "右边")); // 正常插入,不管key值
	for (const auto& kv : mdict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << mdict.size() << endl;
}

int main()
{
	//test_set();
	//test_multiset();
	//test_map1();
	//test_map2();
	test_multimap();

	return 0;
}

4. 笔试OJ题

set和map在很多统计次数的OJ中都能用,这里先写两道:

692. 前K个高频单词 - 力扣(LeetCode)

难度中等

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

示例 1:

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

示例 2:

输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
    出现次数依次为 4, 3, 2 和 1 次。

注意:

  • 1 <= words.length <= 500
  • 1 <= words[i] <= 10
  • words[i] 由小写英文字母组成。
  • k 的取值范围是 [1, 不同 words[i] 的数量]

进阶:尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {

    }
};

priority_queue解析代码:

这道题是topk问题和统计次数的融合,就是先排次数(val)多的k个,次数一样多的按key排降序

map里面是不管key的,这样我们就要写一个排序的仿函数了,先用优先级队列(堆)写一写:

优先级队列默认大的优先级高,传的是 less 仿函数,底层是一个大堆;

如果想控制小的优先级高,需手动传 greater 仿函数,其底层是一个小堆。

我们要弄一个大堆,大堆key一样的时候,按val弄一个小堆:

class Solution {
public:
    struct Less
    {
        bool operator()(const pair<string,int>& kv1,const pair<string,int>& kv2) const
        {
            if(kv1.second < kv2.second) // second(int)升序,小的在前面就ture
            {
                return true;
            }
            if(kv1.second == kv2.second && kv1.first > kv2.first) // first(string)降序
            {
                return true;
            }
            return false;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }

        /*priority_queue<pair<string,int>,vector<pair<string,int>>,Less> MaxHeap;
        for(const auto& kv : countMap) // 也可以迭代器区间初始化,就是太长了,长就typedef
        {
            MaxHeap.push(kv);
        }*/
        typedef priority_queue<pair<string,int>,vector<pair<string,int>>,Less> MaxHeapType;
        MaxHeapType MaxHeap(countMap.begin(),countMap.end());

        vector<string> v;
        while(k--)
        {
            v.push_back(MaxHeap.top().first);
            MaxHeap.pop();
        }
        return v;
    }
};

sort解析代码:

在上面的基础上想想,如果我们用一个稳定的排序来排序string,是不是就能解决?

虽然sort不能排序map,但是可以把map转移到vector里然后在sort,直接sort是不稳定的,

但我们可以控制仿函数来间接控制:

(下面几种方法已经不是为了解题了,只是为了熟悉各个方法的使用,

因为priority的仿函数是反过来的,这里只需改下仿函数的大于小于号,把Less改成Great:)

class Solution {
public:
    struct Great
    {
        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;
            }
            return false;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }

        vector<pair<string,int>> sortV(countMap.begin(),countMap.end());
        sort(sortV.begin(),sortV.end(),Great());

        vector<string> v;
        for(int i = 0; i < k; ++i)
        {
            v.push_back(sortV[i].first);
        }
        return v;
    }
};

stable_sort解析代码:

幸运的是algorithm里面有一个stable_sort,它是稳定的,也就是仿函数里少写了一段:

(下面代码stable_sort换成sort就不行)

class Solution {
public:
    struct Great
    {
        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;
            }*/
            return false;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }

        vector<pair<string,int>> sortV(countMap.begin(),countMap.end());
        stable_sort(sortV.begin(),sortV.end(),Great());

        vector<string> v;
        for(int i = 0; i < k; ++i)
        {
            v.push_back(sortV[i].first);
        }
        return v;
    }
};

multimap解析代码:

这里可以用multimap 代替stable_sort 以用来排序,可以直接用库里的仿函数:

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }

        multimap<int, string, greater<int>> sortMap;
        for(const auto& kv : countMap)
        {
            sortMap.insert(make_pair(kv.second,kv.first));
        }

        vector<string> v;
        multimap<int, string, greater<int>>::iterator it = sortMap.begin();
        for(int i = 0; i < k; ++i)
        {
            v.push_back(it->second);
            ++it;
        }
        return v;
    }
};

349. 两个数组的交集 - 力扣(LeetCode)

难度简单

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {

    }
};

set解析代码:

如果两个数组是有序的,则可以使用双指针的方法得到两个数组的交集。

这里还需要去重,(库里还有一个去重的函数unique,加上sort也可以解决这题)

unique是不改变size的,所以很麻烦,用set(排序+去重)就是很好的选择: 

两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,

如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,

输出到vector,然后两个指针右移。当至少有一个指针超出数组范围时,遍历结束。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> s1(nums1.begin(),nums1.end());
        set<int> s2(nums2.begin(),nums2.end());

        set<int>::iterator it1 = s1.begin();
        auto it2 = s2.begin();

        vector<int> v;
        while(it1 != s1.end() && it2 != s2.end())
        {
            if(*it1 > *it2)
            {
                ++it2;
            }
            else if(*it1 < *it2)
            {
                ++it1;
            }
            else
            {
                v.push_back(*it1); // 相等,进哪个都行
                ++it1;
                ++it2;
            }
        }
        return v;
    }
};

单词识别_牛客题霸_牛客网 (nowcoder.com)

中等  通过率:22.37%  时间限制:1秒  空间限制:32M

知识点字符串哈希

描述

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

输入描述:

输入为一行,由若干个单词和句号组成

输出描述:

输出格式参见样例。

示例1

输入:

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>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

set解析代码:

 1. 遍历语句字符串,从语句字符串中分离出单词

 2. 每分离出一个单词,就将该单词插入到map中,map会自动统计该单词出现的次数

 3. 将统计到的结果按照要求排序

 4. 输出

 注意:1. 统计单词时,要将单词的大小写统一,因为题目说不区分大小写,注意循环输入

      2. 利用set将统计的结果按照次数由大到小排序,如果次数一样按照字典序排序

      3. 输出排序之后的结果

#include <iostream>
using namespace std;
#include <map>
#include <set>

class Compare
{
public:
    bool operator()(const pair<string,int>& left, const pair<string,int>& right)
    {
        // 次数从大到小排序,如果次数相同,再按照单词字典序排序
        return left.second > right.second || left.first < right.first;
    }
};

int main()
{
    string s;
    while(getline(cin, s))
    {
        map<string, int> m;
        string temp;
        
        // 分割单词,采用map统计每个单词出现的次数
        for(size_t i = 0; i < s.size(); ++i)
        {
            if(s[i] == ' ' || s[i] == '.')
            {
                if(temp != "")// 一个单词解析结束
                {
                    m[temp]++;
                }
                temp = "";
            }
            else
            {
                temp += tolower(s[i]); // 题目说不区分大小写
            }
        }
        
        set<pair<string,int>, Compare> s;
        // 将map中的<单词,次数>放到set中,并按照次数升序,次数相同按照字典序规则排序
        for(auto& e : m)
        {
            s.insert(e);
        }
        for(auto& e : s) // 将统计到的结果按照要求输出
        {
            cout<<e.first<<":"<<e.second<<endl;
        }
    }
    return 0;
}

multimap解析代码:

#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;

int main() 
{
    string str;
    map<string, int> countMap;
    while(getline(cin,str))
    {
        for(int i=0,j=0;i<str.size();i++)
        {
            if(str[i]==' '||str[i]=='.')
            {
                string t=str.substr(j,i-j);
                if(isupper(t[0]))
                {
                    t[0]=tolower(t[0]);
                }
                j=i+1;
                countMap[t]++;
            }
        }
    }

    multimap<int, string, greater<int>> sortMap;
    for(const auto& kv : countMap)
    {
        sortMap.insert(make_pair(kv.second,kv.first));
    }

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

    return 0;
}

5. 笔试选择题

1. 下列说法正确的是()

A.set中的某个元素值不能被直接修改

B.map和unordered_map都是C++11提供的关联式容器

C.因为map和set的底层数据结构相同,因此在实现时set底层实际存储的是<key, key>的键值对

D.map和multimap中都重载了[]运算符

2.下面关于set的说法正确的是()

A.set中一定不能存储键值对,只能存储key

B.set可以将序列中重复性的元素去除掉

C.set中不能存储对象,因为对象字段较多,没有办法比较

D.set默认是升序,因为其默认是按照大于的方式比较的

3. 下面关于map的说法正确的是()

A.map的查询效率是O(log_2N),因为其底层使用的是二叉搜索树

B.map的key和value的类型可以相同

C.map中的有序只能是升序,不能是降序

D.map中的key可以直接修改

4. 下面关于map和set说法错误的是()

A.map中存储的是键值对,set中只储存了key

B.map和set查询的时间复杂度都是O(log_2N)

C.map和set都重载了[]运算符

D.map和set底层都是使用红黑树实现的

答案:

1. A

 A:正确,因为set要保证其有序,因此set中元素不能被直接修改,若要修改可以先删除,在插入

B:错误,map是C++98中已存在的,unordered_map是C++11中才有的

C:错误,map和set底层结构都是红黑树,而其底层红黑树在实现时并没有区分是存k模型还是KV 模型

D:错误,map中key是唯一的,每个key都有与之对应的value,经常需要通过key获取value,因此 map为了形象简    单重载了[]运算符, multimap中key是可以重复的,如果重载了[]运算符,给定 一个key时,就没有办法返回     value了,因此,multimap中没有重载[]运算符

2. B

  A:错误,set中可以存储键值对,实例化set时,将set中元素类型设置为pair即可

  B:正确,因为set中的key是不能重复的

  C:错误,set中任意类型元素都可以存储,存储对象时,需要用户提供比较规则

  D:错误,set默认是升序,正确,但是其内部默认不是按照大于比较,而是按照小于比较

3. B

A:错误,map的查询效率是O(log_2N)是正确的,但map的底层结构不是二叉搜索树,而是红黑树

B:正确,key和value的类型由用户自己设置,可以相同也可以不同,取决于应用场景需要

C:错误,map可以是升序,也可是降序,默认情况下是升序,如果需要降序,需要用户在实例化 map时指定比较规则

D:错误,map中key不能修改,因为如果修改了就不能保证红黑树的特性了,即有序

4. C

  A:正确,map和set的概念

  B:正确,因map和set的底层结构都是红黑树,而红黑树是近似的平衡二叉搜索树,故查询时间 复杂度为O(log_2N)

  C:错误,map中重载了[]运算符,因为其需要通过key获取value,set中没有

  D:正确

本章完。

下一部分:AVL树的介绍和模拟实现,然后是红黑树。再就是set和map的模拟实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/754355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ai绘画软件免费下载哪个好用?探索ai绘画生成器

曾经有一个年轻的艺术爱好者&#xff0c;名叫小明。他对绘画充满热情&#xff0c;渴望能够通过绘画表达自己的创造力和想法。然而&#xff0c;他并没有接受过正规的美术训练&#xff0c;也没有负担得起的昂贵绘画软件。因此&#xff0c;他开始思考ai绘画软件免费下载哪个好用&a…

SpringCloud——消息总线Bus

SpringCloud Bus将分布式系统的节点与轻量级消息系统链接起来的框架&#xff0c;是对SpringCloud Config的加强&#xff0c;广播自动版的配置。 支持两种消息代理&#xff1a;RabbitMQ和Kafka 一、创建工程&#xff0c;添加依赖 spring-cloud-starter-config spring-cloud-st…

【DeepSpeed 教程】四,DeepSpeed ZeRO++博客和代码解析

0x0. 系列文章 DeepSpeed-Chat 打造类ChatGPT全流程 笔记二之监督指令微调DeepSpeed-Chat 打造类ChatGPT全流程 笔记一【DeepSpeed 教程翻译】三&#xff0c;在 DeepSpeed中使用 PyTorch Profiler和Flops ProfilerDeepSpeed结合Megatron-LM训练GPT2模型笔记&#xff08;上&…

程序员如何制作PPT?

有道无术&#xff0c;术尚可求也&#xff1b;有术无道&#xff0c;止于术。大家好&#xff0c;我是程序员雪球&#xff0c;今天让我们一起探讨如何从零开始制作高质量的 PPT。 上周&#xff0c;领导要求我撰写一份关于 4到6月持续集成运营分析的报告&#xff0c;并通过 PPT 的形…

【Python爬虫与数据分析】爬虫常用标准库(时间、随机数)

目录 一、模块化概述 二、time库 1. 时间获取 2. 时间格式化 3. 程序计时 三、datetime库 1. datetime.datetime类 2. datetime.timedelta类 四、random库 1. 基本随机函数 2. 扩展随机函数 3. 随机时间的生成 一、模块化概述 Python程序由模块组成&#xff0c;一个…

Redis数据结构 — SkipList

目录 跳表结构设计 跳表节点结构设计 跳表节点查询过程 跳表节点层数设置 为什么用跳表不用红黑树&#xff1f; 跳表平均指针数目为1/(1-p)公式推导 跳表的优势是能支持平均 O(logN) 复杂度的节点查找&#xff0c;支持进行高效的范围查询 SkipList&#xff08;跳表&…

idea-控制台输出乱码问题

idea-控制台输出乱码问题 现象描述&#xff1a; 今天在进行IDEA开发WEB工程调式的时候控制台日志输出了乱码&#xff0c;如下截图 其实开发者大多都知道乱码是 编码不一致导致的&#xff0c;但是有时候就是不知到哪些地方不一致&#xff0c;今天我碰到的情况可能和你的不相同…

【C++】多态及原理

文章目录 1.多态的概念2.多态的定义及实现2.1多态的构成条件2.2虚函数的重写2.3析构函数的重写2.4 C11 override和 final2.5重载、重写(覆盖)、重定义(隐藏)的对比 3.抽象类3.1定义 4.多态的原理4.1虚函数表 虚表单继承的虚表多继承的虚表问答题 1.多态的概念 多态&#xff0c;…

(数组与矩阵) 剑指 Offer 03. 数组中重复的数字 ——【Leetcode每日一题】

❓ 剑指 Offer 03. 数组中重复的数字 难度&#xff1a;简单 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出…

新功能: 全新的UI视图、搜索设置和强大的API特性

我们在ftrack Studio中引入的一些超赞的新功能&#xff0c;旨在将用户体验提升到一个新的水平&#xff01;准备好提高生产效率、优化任务流程&#xff0c;并获得有价值的见解&#xff0c;以便为你的所有项目做出数据驱动的决策。 本月&#xff0c;我们为ftrack Studio带来了几个…

PyLab绘制曲线图

PyLab 是一个面向 Matplotlib 的绘图库接口&#xff0c;其语法和 MATLAB 十分相近。它和 Pyplot 模快都够实现 Matplotlib 的绘图功能。PyLab 是一个单独的模块&#xff0c;随 Matplotlib 软件包一起安装&#xff0c;该模块的导包方式和 Pyplot 不同&#xff0c;如下所示&#…

SAP CAP篇十:理解Fiori UI的Annoation定义

本文目录 本系列此前的文章官方文档和基础概念SAP CAP对Fiori UI的支持package.json的新增内容Annotation定义List Page 生成的Edmx文件 对应代码及branch 本系列此前的文章 SAP CAP篇一: 快速创建一个Service&#xff0c;基于Java的实现 SAP CAP篇二&#xff1a;为Service加上…

青岛大学_王卓老师【数据结构与算法】Week05_12_队列的类型定义_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

【学习笔记】[CTSC2017] 网络

我的评价是毒瘤&#x1f605; 首先想到的肯定是原树上的直径。 于是得到第一个结论&#xff1a;这条边的两个端点一定在直径上。 第二个结论&#xff1a;每个点距离最远的那个点是直径的两个端点之一。 发现直径上形成了一个环。显然这个环的长度应该 ≥ L \ge L ≥L&#…

Mysql分区表----分类、优势、特点、优点

范围分区&#xff08;Range Partitioning、哈希分区&#xff08;Hash Partitioning&#xff09;列 表分区&#xff08;List Partitioning&#xff09;、键值分区&#xff08; Key partition &#xff09; 文章目录 mysql分区表概述&#xff1a;MYSQL分区表简单而言就是将一张大…

跨域问题解决

由于同源策略&#xff0c;需要协议&#xff0c;域名&#xff0c;端口三个都相同才能进行访问&#xff0c;是一种浏览器的保护策略 CORS:Cross Origin Resource Sharing SpringBoot 项目中解决跨域 1.在目标方法中加入CrossOrigin注解 2.添加一种过滤器 分别是允许哪些域&#…

分享几种在家就能做的网赚方式,下班暑假都可以做的副业推荐

在当前的互联网时代中&#xff0c;网上赚钱已经成为受到广泛关注的一个话题。越来越多的人渴望通过利用互联网来实现经济上的自由&#xff0c;然而&#xff0c;同时也面临一些风险和挑战。 尽管网上有很多兼职赚钱的机会&#xff0c;但并不是所有方式都可信赖。有些机会可能会…

JVM_00000

JVM 所谓虚拟机&#xff08;Virtual Machine&#xff09;就是一台虚拟的计算机。它是一款软件&#xff0c;用来执行一系列虚拟计算机指令。大体上&#xff0c;虚拟机可以分为系统虚拟机和程序虚拟机。 Visual Box&#xff0c;VMware就属于系统虚拟机&#xff0c;它们完全是对物…

【动手学习深度学习--逐行代码解析合集】18网络中的网络(NiN)

【动手学习深度学习】逐行代码解析合集 18网络中的网络&#xff08;NiN&#xff09; 视频链接&#xff1a;动手学习深度学习–网络中的网络&#xff08;NiN&#xff09; 课程主页&#xff1a;https://courses.d2l.ai/zh-v2/ 教材&#xff1a;https://zh-v2.d2l.ai/ 1、NiN网络…

IDE/VS项目属性中的 <字符集> 配置项,它到底是干什么用的?

文章目录 概述对配置项的基础测试VS默认的字符集配置Unicode字符集和多字节字符集是否影响文本编辑器 使VS像记事本那样显示文件编码VS下编译UTF-8无BOM的代码文件VS可以搞定ANSI和带BOM的源代码文件VS搞不定UTF-8无BOM的源代码文件乱码字符是怎么翻译出来的?猜猜看再起航 使V…