// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
// Default initial capacity
let default_init_capacity = 8
///|
/// Create new indexed hash set.
///|
/// Create new indexed hash set.
pub fn new[K](capacity~ : Int = default_init_capacity) -> T[K] {
{
core: {
hash_to_idx: @hashmap.new(),
entries: [],
head: -1,
tail: -1,
position_to_idx: [], // 初始化为空数组
idx_to_position: @hashmap.new(), // 初始化为空映射
},
size: 0,
capacity,
growAt: calc_grow_threshold(capacity),
key_to_idx: @hashmap.new(),
}
}
///|
/// Create new indexed hash set from array.
pub fn from_array[K : Hash + Eq](arr : Array[K]) -> T[K] {
let set = new()
arr.each(fn(e) { set.add(e) })
set
}
///|
pub fn of[K : Hash + Eq](arr : FixedArray[K]) -> T[K] {
let set = new()
arr.each(fn(e) { set.add(e) })
set
}
///|
/// Insert a key into hash set.
/// @alert unsafe "Panic if the hash set is full."
#deprecated("Use `add` instead.")
#coverage.skip
pub fn insert[K : Hash + Eq](self : T[K], key : K) -> Unit {
self.add(key)
}
///|
/// Add a key to the hash set.
pub fn add[K : Hash + Eq](self : T[K], key : K) -> Unit {
// 检查是否需要扩容
if self.capacity == 0 || self.size >= self.growAt {
self.grow()
}
// 计算哈希值
let hash = key.hash()
// 检查键是否已存在
if self.contains(key) {
return
}
// 创建新的桶
let bucket_idx = self.core.entries.length()
let new_bucket = {
hash,
key,
next: -1, // 无后继
prev: self.core.tail,
} // 前驱为当前尾节点
// 添加到桶数组
self.core.entries.push(new_bucket)
// 在映射中记录键到索引的映射
self.key_to_idx.set(key, bucket_idx)
// 更新链表结构
if self.core.tail != -1 {
// 更新原尾节点的后继为新节点
self.core.entries[self.core.tail].next = bucket_idx
}
// 更新尾节点
self.core.tail = bucket_idx
// 如果这是第一个元素,也更新头节点
if self.core.head == -1 {
self.core.head = bucket_idx
}
// 在哈希表中记录
self.insert_into_table(hash, bucket_idx)
// 更新位置到索引的映射
self.core.position_to_idx.push(bucket_idx)
// 更新索引到位置的映射
self.core.idx_to_position.set(bucket_idx, self.size)
// 更新大小
self.size += 1
}
///|
/// Get element at specific index
pub fn get_at[K](self : T[K], index : Int) -> K? {
if index < 0 || index >= self.size {
return None
}
// 直接从位置映射获取索引
let bucket_idx = self.core.position_to_idx[index]
// 返回对应的元素
Some(self.core.entries[bucket_idx].key)
}
///|
/// Get the index of a key
pub fn index_of[K : Hash + Eq](self : T[K], key : K) -> Int? {
// 先检查键是否存在
match self.key_to_idx.get(key) {
Some(bucket_idx) =>
// 从桶索引到位置的映射获取位置索引
match self.core.idx_to_position.get(bucket_idx) {
Some(position) => Some(position)
None => None // 理论上不应该发生
}
None => None // 键不存在
}
}
///|
/// Check if the hash set contains a key.
pub fn contains[K : Hash + Eq](self : T[K], key : K) -> Bool {
if self.size == 0 {
return false
}
// 直接检查 key_to_idx 中是否存在该键
self.key_to_idx.contains(key)
}
///|
///| Remove a key from hash set with O(1) complexity.
pub fn remove[K : Hash + Eq](self : T[K], key : K) -> Unit {
if self.size == 0 {
return
}
// 直接从映射中获取索引,O(1)操作
match self.key_to_idx.get(key) {
Some(idx) => {
// 获取被删除元素的链表信息
let entry = self.core.entries[idx]
let hash = entry.hash
// 从索引到位置的映射中获取位置
let position = match self.core.idx_to_position.get(idx) {
Some(pos) => pos
None => return // 应该不会发生,防御性编程
}
// 如果要删除的不是最后一个元素,则进行交换
if position < self.size - 1 {
// 获取最后一个元素的索引
let last_idx = self.core.position_to_idx[self.size - 1]
ignore(self.core.entries[last_idx].key)
// 将最后一个元素移动到被删除元素的位置
self.core.position_to_idx[position] = last_idx
self.core.idx_to_position.set(last_idx, position)
}
// 从位置映射中移除最后一个位置
ignore(self.core.position_to_idx.pop())
// 从索引到位置的映射中移除被删除元素
self.core.idx_to_position.remove(idx)
// 从哈希表中移除
self.core.hash_to_idx.remove(hash)
// 修复链表指针
// 如果有前一个元素,更新它的next指针
if entry.prev != -1 {
self.core.entries[entry.prev].next = entry.next
} else {
// 如果是头节点,更新head指针
self.core.head = entry.next
}
// 如果有后一个元素,更新它的prev指针
if entry.next != -1 {
self.core.entries[entry.next].prev = entry.prev
} else {
// 如果是尾节点,更新tail指针
self.core.tail = entry.prev
}
// 从映射中移除被删除的键
self.key_to_idx.remove(key)
// 更新大小
self.size -= 1
}
None => return // 键不存在,不执行任何操作
}
}
///|
/// Get the number of keys in the set.
pub fn size[K](self : T[K]) -> Int {
self.size
}
///|
/// Get the capacity of the set.
pub fn capacity[K](self : T[K]) -> Int {
self.capacity
}
///|
/// Check if the hash set is empty.
pub fn is_empty[K](self : T[K]) -> Bool {
self.size == 0
}
///|
/// Iterate over all keys of the set.
pub fn each[K](self : T[K], f : (K) -> Unit) -> Unit {
self.eachi(fn(_i, k) { f(k) })
}
///|
/// Iterate over all keys of the set, with index.
pub fn eachi[K](self : T[K], f : (Int, K) -> Unit) -> Unit {
let mut current = self.core.head
let mut index = 0
while current != -1 {
f(index, self.core.entries[current].key)
current = self.core.entries[current].next
index += 1
}
}
///|
/// Clears the set, removing all keys. Keeps the allocated space.
pub fn clear[K](self : T[K]) -> Unit {
self.core.hash_to_idx = @hashmap.new() // 重置为新的哈希表
self.core.entries = []
self.core.head = -1
self.core.tail = -1
self.core.position_to_idx = [] // 清空位置映射
self.core.idx_to_position = @hashmap.new() // 清空索引到位置的映射
self.size = 0
self.key_to_idx = @hashmap.new()
}
///|
/// Union of two hash sets.
/// @alert unsafe "Panic if the hash set is full."
pub fn union[K : Hash + Eq](self : T[K], other : T[K]) -> T[K] {
let result = new()
self.each(fn(k) { result.add(k) })
other.each(fn(k) { result.add(k) })
result
}
///|
/// Intersection of two hash sets.
pub fn intersection[K : Hash + Eq](self : T[K], other : T[K]) -> T[K] {
let result = new()
self.each(fn(k) { if other.contains(k) { result.add(k) } })
result
}
///|
/// Difference of two hash sets.
pub fn difference[K : Hash + Eq](self : T[K], other : T[K]) -> T[K] {
let result = new()
self.each(fn(k) { if not(other.contains(k)) { result.add(k) } })
result
}
///|
/// Symmetric difference of two hash sets.
pub fn symmetric_difference[K : Hash + Eq](self : T[K], other : T[K]) -> T[K] {
let result = new()
self.each(fn(k) { if not(other.contains(k)) { result.add(k) } })
other.each(fn(k) { if not(self.contains(k)) { result.add(k) } })
result
}
///|
pub fn iter[K](self : T[K]) -> Iter[K] {
Iter::new(fn(yield_) {
let mut current = self.core.head
while current != -1 {
let key = self.core.entries[current].key
if yield_(key) == IterEnd {
break
}
current = self.core.entries[current].next
}
IterContinue
})
}
///|
pub fn from_iter[K : Hash + Eq](iter : Iter[K]) -> T[K] {
let s = new()
iter.each(fn(e) { s.add(e) })
s
}
///|
/// Convert set to array, preserving insertion order.
pub fn to_array[K](self : T[K]) -> Array[K] {
if self.size == 0 || self.core.head == -1 {
return []
}
let result = Array::make(self.size, self.core.entries[self.core.head].key)
let mut current = self.core.head
let mut index = 0
while current != -1 && index < self.size {
result[index] = self.core.entries[current].key
current = self.core.entries[current].next
index += 1
}
result
}
///|
/// Insert an entry into the hash table
fn insert_into_table[K : Hash](
self : T[K],
hash : Int,
bucket_idx : Int
) -> Unit {
// 直接在哈希表中设置键值对,无需线性探测
self.core.hash_to_idx.set(hash, bucket_idx)
}
///|
///|
///|
fn grow[K : Hash + Eq](self : T[K]) -> Unit {
// 保存旧数据
let old_entries = self.core.entries
let old_head = self.core.head
// 创建新的存储
self.capacity = self.capacity * 2
self.growAt = calc_grow_threshold(self.capacity)
self.core.hash_to_idx = @hashmap.new() // 使用新的哈希表
self.core.entries = []
self.core.head = -1
self.core.tail = -1
self.core.position_to_idx = [] // 重置位置映射
self.core.idx_to_position = @hashmap.new() // 重置索引到位置的映射
self.size = 0
self.key_to_idx = @hashmap.new()
// 重新添加所有元素,保持原顺序
let mut current = old_head
while current != -1 {
let entry = old_entries[current]
self.add(entry.key)
current = entry.next
}
}
///|
fn calc_grow_threshold(capacity : Int) -> Int {
capacity * 13 / 16
}
///|
pub impl[K : Show] Show for T[K] with output(self, logger) {
logger.write_iter(self.iter(), prefix="@IndexSet.of([", suffix="])")
}
///|
/// 移除并返回最后一个插入的元素(尾部元素)
/// 如果集合为空,返回 None
pub fn pop[K : Hash + Eq](self : T[K]) -> K? {
if self.size == 0 {
return None
}
// 获取尾部元素
let tail_idx = self.core.tail
let tail_element = self.core.entries[tail_idx]
let key = tail_element.key
// 从哈希表中移除映射 - 直接操作
self.core.hash_to_idx.remove(tail_element.hash)
// 调整链表
if tail_element.prev != -1 {
self.core.entries[tail_element.prev].next = -1
self.core.tail = tail_element.prev
} else {
// 集合中只有一个元素,清空链表
self.core.head = -1
self.core.tail = -1
}
// 从映射中移除
self.key_to_idx.remove(key)
// 从索引到位置的映射中移除
self.core.idx_to_position.remove(tail_idx)
// 从位置映射中移除最后一个元素
ignore(self.core.position_to_idx.pop())
// 更新大小
self.size -= 1
// 返回移除的元素
Some(key)
}
///|
/// 移除并返回第一个插入的元素(头部元素)
/// 时间复杂度:O(1)
pub fn shift[K : Hash + Eq](self : T[K]) -> K? {
if self.size == 0 {
return None
}
// 获取头部元素
let head_idx = self.core.head
let head_element = self.core.entries[head_idx]
let key = head_element.key
// 从哈希表中移除映射
self.core.hash_to_idx.remove(head_element.hash)
// 调整链表
if head_element.next != -1 {
self.core.entries[head_element.next].prev = -1
self.core.head = head_element.next
} else {
// 集合中只有一个元素,清空链表
self.core.head = -1
self.core.tail = -1
}
// 从键到索引的映射中移除
self.key_to_idx.remove(key)
// 从索引到位置的映射中移除
self.core.idx_to_position.remove(head_idx)
// 使用交换策略:将最后一个元素移动到第一个位置
if self.size > 1 {
// 获取最后一个元素的索引
let last_idx = self.core.position_to_idx[self.size - 1]
// 将最后一个元素移动到第一个位置
self.core.position_to_idx[0] = last_idx
self.core.idx_to_position.set(last_idx, 0)
}
// 移除最后一个位置的映射(现在已经被移动或者是被删除的元素)
ignore(self.core.position_to_idx.pop())
// 更新大小
self.size -= 1
// 返回移除的元素
Some(key)
}
///| 返回集合中第一个插入的元素,但不移除它
/// 如果集合为空,返回 None
pub fn peek_first[K](self : T[K]) -> K? {
if self.size == 0 || self.core.head == -1 {
return None
}
// 获取头部元素
let head_idx = self.core.head
let head_element = self.core.entries[head_idx]
// 返回元素,但不修改集合
Some(head_element.key)
}
///| 返回集合中最后一个插入的元素,但不移除它
/// 如果集合为空,返回 None
pub fn peek_last[K](self : T[K]) -> K? {
if self.size == 0 || self.core.tail == -1 {
return None
}
// 获取尾部元素
let tail_idx = self.core.tail
let tail_element = self.core.entries[tail_idx]
// 返回元素,但不修改集合
Some(tail_element.key)
}
///|
pub impl[X : @quickcheck.Arbitrary + Eq + Hash] @quickcheck.Arbitrary for T[X] with arbitrary(
size,
rs
) {
@quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter
}
///| 返回一个按照指定比较函数排序的新集合
/// 原集合不会被修改
pub fn sorted[K : Hash + Eq](self : T[K], compare : (K, K) -> Int) -> T[K] {
// 将集合转换为数组
let arr = self.to_array()
// 对数组进行排序
arr.sort_by(compare)
// 创建新的有序集合
from_array(arr)
}
///|
pub fn sorted_by_key[K : Hash + Eq + Compare](self : T[K]) -> T[K] {
self.sorted(fn(a, b) { a.compare(b) })
}
///| 返回一个按照键映射函数排序的新集合
/// 原集合不会被修改
pub fn sorted_by[K : Hash + Eq, B : Compare](
self : T[K],
key_fn : (K) -> B
) -> T[K] {
// 将集合转换为数组
let arr = self.to_array()
// 对数组进行排序
arr.sort_by(fn(a, b) { key_fn(a).compare(key_fn(b)) })
// 创建新的有序集合
from_array(arr)
}
///|
/// 就地排序集合元素
/// 时间复杂度: O(n log n),其中n是集合大小
pub fn sort[K : Hash + Eq](self : T[K], compare : (K, K) -> Int) -> Unit {
if self.size <= 1 {
return
}
// 将集合转换为数组
let arr = self.to_array()
// 对数组进行排序
arr.sort_by(compare)
// 清空当前集合
self.clear()
// 重新添加排序后的元素
for i in 0.. Unit {
self.sort(fn(a, b) { a.compare(b) })
}
///|
/// 就地按照键映射函数排序集合
pub fn sort_by[K : Hash + Eq, B : Compare](
self : T[K],
key_fn : (K) -> B
) -> Unit {
self.sort(fn(a, b) { key_fn(a).compare(key_fn(b)) })
}
///|
/// 返回一个按照指定比较函数反向排序的新集合
pub fn sorted_desc[K : Hash + Eq](self : T[K], compare : (K, K) -> Int) -> T[K] {
self.sorted(fn(a, b) { compare(b, a) })
}
///|
/// 返回一个按照自然顺序反向排序的新集合
pub fn sorted_by_key_desc[K : Hash + Eq + Compare](self : T[K]) -> T[K] {
self.sorted(fn(a, b) { b.compare(a) })
}
///|
/// 就地按照指定比较函数反向排序集合
pub fn sort_desc[K : Hash + Eq](self : T[K], compare : (K, K) -> Int) -> Unit {
self.sort(fn(a, b) { compare(b, a) })
}
///|
/// 就地按照自然顺序反向排序集合
pub fn sort_by_key_desc[K : Hash + Eq + Compare](self : T[K]) -> Unit {
self.sort(fn(a, b) { b.compare(a) })
}