18次发布

0.8.3 2024年2月24日
0.8.2 2023年12月26日
0.8.1 2023年10月26日
0.7.3 2023年7月5日
0.1.0 2022年7月13日

#87 in 数据结构

Download history 4858/week @ 2024-04-21 4261/week @ 2024-04-28 3727/week @ 2024-05-05 4099/week @ 2024-05-12 3824/week @ 2024-05-19 3454/week @ 2024-05-26 4044/week @ 2024-06-02 4343/week @ 2024-06-09 4260/week @ 2024-06-16 5797/week @ 2024-06-23 4610/week @ 2024-06-30 6387/week @ 2024-07-07 7270/week @ 2024-07-14 6600/week @ 2024-07-21 6578/week @ 2024-07-28 6453/week @ 2024-08-04

27,334 每月下载量
9 个crate(7个直接) 中使用

MIT/Apache

305KB
4.5K SLoC

ph 是由 Piotr Beling 开发的基于完美哈希的数据结构Rust库。

该库包含两种基于指纹的最小完美哈希函数(MPHF)的实现:不带(FMPH)和带(FMPHGO)组优化。最小完美哈希函数(MPHF)是从键集 K 到集合 {0, 1, ..., |K|-1} 的双射。

FMPH 和 FMPHGO 可以为任何给定的可哈希项集 K(提前给出)构造,并且分别使用大约 2.82.1 比特/键进行表示。FMPH 和 FMPHGO 评估速度快(期望为 O(1))。它们的构造需要很少的辅助空间,所需时间短(期望为 O(|K|),对于 FMPH 尤其如此),并且可以并行化或在不将键保留在内存中的情况下执行。

参考文献

在研究目的中使用 ph 时,请引用以下论文,该论文提供了关于 FMPH 和 FMPHGO 的详细信息

示例

以下示例说明了 fmph::Function 的使用,但可以将其替换为 fmph::GOFunction 而无需任何其他更改。

基本示例

use ph::fmph;

let keys = ['a', 'b', 'z'];
let f = fmph::Function::from(keys.as_ref());
// f assigns each key a unique number from the set {0, 1, 2}
for k in keys { println!("The key {} is assigned the value {}.", k, f.get(&k).unwrap()); }
let mut values = [f.get(&'a').unwrap(), f.get(&'b').unwrap(), f.get(&'z').unwrap()];
values.sort();
assert_eq!(values, [0, 1, 2]);

使用 fmph::Function 和位图表示一组给定的可哈希元素的子集的示例

use ph::fmph;
use bitm::{BitAccess, BitVec};  // bitm is used to manipulate bitmaps
use std::hash::Hash;

pub struct Subset { // represents a subset of the given set
    hash: fmph::Function, // bijectively maps elements of the set to bits of bitmap
    bitmap: Box<[u64]> // the bit pointed by the hash for e is 1 <=> e is in the subset
}

impl Subset {
    pub fn of<E: Hash + Sync>(set: &[E]) -> Self { // constructs empty subset of the given set
        Subset {
            hash: set.into(),
            bitmap: Box::with_zeroed_bits(set.len())
        }
    }

    pub fn contain<E: Hash>(&self, e: &E) -> bool { // checks if e is in the subset
        self.bitmap.get_bit(self.hash.get_or_panic(e) as usize) as bool
    }

    pub fn insert<E: Hash>(&mut self, e: &E) { // inserts e into the subset
        self.bitmap.set_bit(self.hash.get_or_panic(e) as usize)
    }

    pub fn remove<E: Hash>(&mut self, e: &E) { // removes e from the subset
        self.bitmap.clear_bit(self.hash.get_or_panic(e) as usize)
    }

    pub fn len(&self) -> usize { // returns the number of elements in the subset
        self.bitmap.count_bit_ones()
    }
}

let mut subset = Subset::of(["alpha", "beta", "gamma"].as_ref());
assert_eq!(subset.len(), 0);
assert!(!subset.contain(&"alpha"));
assert!(!subset.contain(&"beta"));
subset.insert(&"beta");
subset.insert(&"gamma");
assert_eq!(subset.len(), 2);
assert!(subset.contain(&"beta"));
subset.remove(&"beta");
assert_eq!(subset.len(), 1);
assert!(!subset.contain(&"beta"));
// subset.insert(&"zeta"); // may either panic or insert any item into subset

上述的 Subset 是一个具有 1 位有效负载的 可更新检索数据结构 的示例。可以通过用其他有效负载的向量替换位图来泛化。

依赖项

~1.5MB
~26K SLoC