C++进阶-- map和set

简介: C++进阶-- map和set

关联式容器

在前面,我们所学的vector、list、deque,这些都是序列容器,也就是底层为线性序列的数据结构。

而关联式容器是C++标准库中的一种类别,用于存储键值对(key-value pair),关联式容器中的元素中的元素是按照键值进行有序存储的,同时也支持快速查找、插入、修改等操作。而map和set就是主要的类型;

这些关联式容器在实现上通常采用平衡二叉搜索树或哈希表等数据结构来保证元素的有序性和高效的查找性能。

键值对

键值对是关联式容器中的一种结构,它由一个键(key)和一个对应值(value)组成。在关联式容器中,每个元素都有一个唯一的键,用于标识和访问该元素。键值对的特性使得关联式容器能够通过键快速查找、插入、删除。

在关联式容器中,键通常用于确定元素的顺序和唯一性,而值则是与键关联的数据。键和值可以是任何类型,但通常使用类或结构体作为键类型,以提供自定义的比较规则。通过比较键的值,关联式容器能够按照键的顺序进行有序存储,并支持快速的查找操作。

键值对的定义:

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)
{}
};

set

介绍

set是C++标准库中的一种关联式容器,它用于存储一组有序的、唯一的元素。set中的元素按照键值进行自动排序,并且不允许存在重复的元素

set在底层是由二叉搜索树(红黑树)实现的。

set中只放value,但在底层实际存放的是由<vlaue,value> 构成的键值对。

set中查找某个元素时,时间复杂度为:log_2 n .

使用

void test1()
{
  set<int> s;
  s.insert(1);
  s.insert(3);
  s.insert(3);
  s.insert(4);
  s.insert(6);
  s.insert(9);
  s.insert(7);
  set<int>::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it << " " ;
    it++;
  }
  cout << endl;
  // 使用迭代器逆向打印set中的元素
  for (auto it = s.rbegin(); it != s.rend(); ++it)
  {
    cout << *it << " ";
  }
  cout << endl;
  set<int>::iterator pos = s.find(7);
  if (pos != s.end())
  {
    cout << "找到了" << endl;
    s.erase(pos);
  }
  
}

void test2()
{
  set<int> s;
  s.insert(1);
  s.insert(3);
  s.insert(3);
  //s.insert(4);
  s.insert(6);
  s.insert(9);
  s.insert(7);
  auto start = s.lower_bound(4);
  cout << *start << endl;
  auto finish = s.upper_bound(4);
  cout << *finish << endl;
}

muiltiset

multisetsC++标准库中的一种关联式容器,它与set容器类似,但允许存储重复的元素

muiltiset容器和set容器的主要区别在于对重复元素的处理。在set容器中,每个键值只能出现一次,而在muitiset容器中,同一个键值可以出现多次。multisey中的元素会根据键值自动进行排序。

void test3()
{
  multiset<int> s;
  s.insert(5);
  s.insert(1);
  s.insert(6);
  s.insert(3);
  s.insert(4);
  s.insert(5);
  s.insert(1);
  s.insert(1);
  s.insert(5);
  s.insert(1);
  s.insert(1);
  s.insert(2);
  s.insert(7);
  s.insert(10);
  multiset<int>::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  //统计相同元素的个数
  cout << s.count(1) << endl;
  cout << s.count(5) << endl;
}

map

介绍

map是C++标准库中的一种关联式容器,它用于存储一组键值对每个元素都由一个唯一的键和对应的值组成。map中的元素按照键进行自动排序,并且不允许存在重复键

在map内部,key和value通过成员类型value_type绑定在一起,为其取别名为pair;

typedef pair<const key,T> value_type;

map支持下标访问符,即在[]中放入key,就可以找到与key对应的value值;

map通常被实现为二叉搜索树(平衡二叉搜索树).

使用

void test4()
{
  map<string, string> dict;
  dict.insert(pair<string, string>("sort", "排序"));
  //pair<string, string> kv("string", "字符串");
  pair<string, string> kv = { "string", "字符串" };
  dict.insert(kv);
  // C++11 多参数隐式类型转换(构造函数)
  dict.insert({ "apple", "苹果" });
  // C++98
  dict.insert(make_pair("sort", "排序"));
  for (auto& kv : dict)
  {
    cout << kv.first << ":" << kv.second << endl;
  }
  cout << endl;
}

void test5()
{
  string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "西瓜", "香蕉", "草莓" };
  map<string, int> countMap;
  for (auto& e : arr)
  {
    countMap[e]++;
  }
  for (auto& kv : countMap)
  {
    cout << kv.first << ":" << kv.second << endl;
  }
  cout << endl;
  //通过operator[]进行查找value值
  cout << countMap["苹果"] << endl;
}

multimap

multimapC++标准库中的一种关联式容器,它与map容器类似,但允许存储重复的键

multimap容器和map容器的主要区别在于对重复键的处理方式。在multimap中,可以有很多个元素具有相同的键,这些元素会按照键进行自动排序,但不保证值的顺序

multimap中没有重载operator[]操作;

使用时与map包含的头文件相同。

相关文章
|
18天前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
52 18
你对Collection中Set、List、Map理解?
|
11天前
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
49 20
|
28天前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
30 3
【C++】map、set基本用法
|
28天前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
22 5
|
28天前
|
存储 C++ 容器
【C++】map的模拟实现
C++中的`map`是STL中的一种关联容器,存储键值对且键唯一。`map`基于红黑树实现,自动按键排序,支持动态调整、复杂数据类型、丰富的成员函数及双向迭代器。插入、查找等操作保证了对数时间复杂度,适用于需要快速查找和有序存储的场景。
22 3
|
28天前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
31 3
|
2月前
|
存储 JavaScript 前端开发
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。
|
3月前
|
存储 Java API
【数据结构】map&set详解
本文详细介绍了Java集合框架中的Set系列和Map系列集合。Set系列包括HashSet(哈希表实现,无序且元素唯一)、LinkedHashSet(保持插入顺序的HashSet)、TreeSet(红黑树实现,自动排序)。Map系列为双列集合,键值一一对应,键不可重复,值可重复。文章还介绍了HashMap、LinkedHashMap、TreeMap的具体实现与应用场景,并提供了面试题示例,如随机链表复制、宝石与石头、前K个高频单词等问题的解决方案。
48 6
【数据结构】map&set详解
|
2月前
|
存储 缓存 Java
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
43 1
|
3月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
42 5