Set方法实现原理
- add方法:
- 原理:Set 内部维护一个存储元素的数据结构(通常是哈希表)。当调用
add
方法时,会先计算要添加元素的哈希值,通过哈希值找到对应的存储位置。如果该位置为空,则直接将元素存储;如果该位置已有元素,且该元素与要添加的元素相同(通过 SameValueZero
算法比较),则不重复添加,否则通过冲突解决策略(如链地址法)处理冲突并存储元素。
- 时间复杂度:平均情况下为 $O(1)$,在最坏情况下(哈希冲突严重)为 $O(n)$,$n$ 为 Set 中元素的数量。
- 空间复杂度:$O(n)$,其中 $n$ 是 Set 中元素的数量,用于存储这些元素。
- delete方法:
- 原理:同样根据要删除元素的哈希值找到对应的存储位置,然后查找该位置及冲突链上是否存在该元素(通过
SameValueZero
算法比较),如果存在则将其删除。
- 时间复杂度:平均情况下为 $O(1)$,最坏情况下为 $O(n)$。
- 空间复杂度:$O(1)$,因为操作过程中不额外占用与元素数量相关的空间。
- has方法:
- 原理:计算要检查元素的哈希值,找到对应的存储位置,然后在该位置及冲突链上查找是否存在该元素(通过
SameValueZero
算法比较)。
- 时间复杂度:平均情况下为 $O(1)$,最坏情况下为 $O(n)$。
- 空间复杂度:$O(1)$,不额外占用与元素数量相关的空间。
Map方法实现原理
- set方法:
- 原理:Map 通常也是基于哈希表实现。当调用
set
方法时,先计算键的哈希值,根据哈希值找到存储位置。如果该位置为空,则存储键值对;如果有冲突,通过冲突解决策略(如链地址法)存储键值对。
- 时间复杂度:平均情况下为 $O(1)$,最坏情况下为 $O(n)$,$n$ 为 Map 中键值对的数量。
- 空间复杂度:$O(n)$,用于存储键值对。
- get方法:
- 原理:计算键的哈希值,找到对应的存储位置,然后在该位置及冲突链上查找与键匹配的键值对(通过
SameValueZero
算法比较键),如果找到则返回对应的值。
- 时间复杂度:平均情况下为 $O(1)$,最坏情况下为 $O(n)$。
- 空间复杂度:$O(1)$,不额外占用与元素数量相关的空间。
- has方法:
- 原理:计算键的哈希值,找到对应存储位置,在该位置及冲突链上查找是否存在匹配的键(通过
SameValueZero
算法比较)。
- 时间复杂度:平均情况下为 $O(1)$,最坏情况下为 $O(n)$。
- 空间复杂度:$O(1)$,不额外占用与元素数量相关的空间。
对包含大量元素的Set进行去重和排序
- 利用Set去重:由于 Set 本身就具有去重特性,所以无需额外操作,直接将数据添加到 Set 中,就已经完成去重。
- 排序:
- 方法一:转换为数组后排序:将 Set 转换为数组(如
Array.from(set)
或 [...set]
),然后使用数组的 sort
方法进行排序。sort
方法在 V8 引擎下平均时间复杂度为 $O(n log n)$,空间复杂度为 $O(n)$。示例代码如下:
let set = new Set([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]);
let sortedArray = Array.from(set).sort((a, b) => a - b);
console.log(sortedArray);
- **方法二:使用TreeSet(需自行实现)**:JavaScript 原生没有 `TreeSet`,但可以自己实现一个基于二叉搜索树的 `TreeSet`。插入操作时间复杂度平均为 $O(log n)$,排序可以通过中序遍历二叉搜索树实现,时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。实现相对复杂,但对于大规模数据且频繁插入和排序操作时性能较好。