Skip to content

Sets, Maps

Sets(集合)

在 library 中有两种集合:

  • set:使用一种名为二叉树的结构实现.
    • 速度相当快;元素以排序顺序存储
    • 值必须有一个 "<" 操作
  • hashset:使用一种称为哈希表的特殊数组实现。
    • 非常快速;元素以不可预测的顺序存储。
    • 值必须有一个 hashCode 函数(大多数标准类型提供)。

这两种的选择取决你是否按照排序顺序存放元素


**#include "set.h"**

**#include "hashset.h"**

MenberSetHashsetdescription(描述)
s.add(value)O(log N)O(1)添加元素到集合中
s.clear()O(N)O(N)清空集合
s.contains(value)O(log N)O(1)判断元素是否存在于集合中
s.isEmpty()O(1)O(1)判断集合是否为空
s.isSubsetOf(set)O(N log N)O(N)判断集合是否是另一个集合的子集
s.remove(value)O(log N)O(1)从集合中删除元素
s.size()O(1)O(1)集合中元素的数量
s.toStirng()O(N)O(N)集合中元素的字符串表示

运算符

  • s1 == s2: 判断两个集合是否相等
  • s1 != s2: 判断两个集合是否不相等
  • s1 + s2: 合并两个集合
  • s1 += s2: 合并两个集合并更新第一个集合
  • s1 - s2: 集合 s1 中元素不在集合 s2 中的元素
  • s1 -= s2: 集合 s1 中元素不在集合 s2 中的元素并更新第一个集合
  • s1 * s2: 集合 s1 和集合 s2 的交集
  • s1 *= s2: 集合 s1 和集合 s2 的交集并更新第一个集合

注意:无法使用 for 循环遍历集合中的元素,因为集合是无序的。

Lexicon(词典)

这就是以字符串构成的 Sets(集合)的例子。

Maps(映射)

Maps(映射)是键值对的集合。

组成部分:

  • key: 映射中的键
  • value: 映射中的值
    alt text

映射是一种存储对集合的数据结构

**#include "map.h"** 使用一种称为二叉搜索树的链接结构实现。

  • 所有操作速度相当快;键以排序顺序存储。

  • 两种映射实现完全相同的操作。

  • 值必须有一个 "<" 操作。

**#include "hashmap.h"** 使用一种称为哈希表的特殊数组实现。

  • 速度非常快;键以不可预测的顺序存储。

  • 值必须有一个 hashCode 函数(大多数标准类型提供)。


运算符

  • m.put(key, value): 添加键值对到映射中
c++
m.put("bobo", "114-514"); //or
m["bobo"] = "114-514";
  • m.get(key): 获取键对应的值
c++
string value = m.get("bobo"); //"114-514" or
string value = m["bobo"];
  • m.remove(key): 从映射中删除键值对
c++
m.remove("bobo");

membership

成员MapHashMap描述
m.clear()O(N)O(N)移除所有键/值对
m.containsKey(key)O(log N)O(1)如果映射中存在给定键的对,则返回 true
m[key] 或 m.get(key)O(log N)O(1)返回映射到给定键的值;如果未找到,则以默认值添加
m.isEmpty()O(1)O(1)如果映射不包含任何对,则为 true
m.keys()O(N)O(N)返回映射中所有键的 Vector 复制
m[key] = value; 或 m.put(key, value);O(log N)O(1)添加键/值对;如果键已存在,替换其值
m.remove(key)O(log N)O(1)移除给定键的任何对
m.size()O(1)O(1)返回映射中的对数
m.toString()O(N)O(N)示例:"{a:90, d:60, c:70}"
m.values()O(N)O(N)返回映射中所有值的 Vector 复制
ostr << mO(N)O(N)将映射打印到流中

Lotto ticket example 嵌套集合

集合之间可以相互嵌套

c++
#include <iostream>
#include <vector>
#include <set>
#include <map>

using namespace std;

int main()
{
    // Set of integers
    set<int> s1 = {1, 2, 3, 4, 5};
    set<int> s2 = {3, 4, 5, 6, 7};
    set<int> s3 = {5, 6, 7, 8, 9};

    // Map of sets
    map<string, set<int>> m;
    m["s1"] = s1;
    m["s2"] = s2;
    m["s3"] = s3;

    // Accessing values using keys
    cout << m["s1"].size() << endl; // Output: 5
    cout << m["s2"].size() << endl; // Output: 5
    cout << m["s3"].size() << endl; // Output: 5

    // Accessing values using iterators
    for(auto it = m.begin(); it != m.end(); it++) {
        cout << it->first << " : ";
        for(auto jt = it->second.begin(); jt != it->second.end(); jt++) {
            cout << *jt << " ";
        }
        cout << endl;
    }

    return 0;
}

big O notation(大 O 记法)

我们可以从不同方面来衡量一个算法的效率。

  • Efficiency(效率):衡量代码使用计算资源的程度。
    • 可能相对速度(运行时间)、内存(空间)等。
    • 最常指的是运行时间。
    • 单个语句的运行时间 = 1。
    • 一个函数调用的运行时间 = (函数体内语句运行时间的总和)。
    • N 次迭代的循环运行时间 = (N * (循环体的运行时间))。

O(1)<O(log N)<O(N)<O(N log N)<O(N^2)<O(2^N)<O(N!)<O(N^N)<O(infinity)