Hashing

本文探讨了哈希函数的性质及静态哈希的不足之处,并介绍了两种动态调整哈希表的技术——可扩展哈希(Extendible Hashing)与线性哈希(Linear Hashing),包括它们的工作原理、优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hash函数的性质

一致性:具有相同关键字的值被赋给同一个桶中。

随机性:每个桶将会有相同数据的记录,而不考虑文件中关键字的真实分布。

最坏性:把所有的关键字映射到同一个桶中,使得访问时间和文件中关键字的数量成正比。

Static Hashing:

image

如果没有空间剩余,将会分配overflow buckets, 用链表把它们连接起来。(长的链表降低了性能)

Deficiency:

一:如果初始桶的数量很少,随着文件的增长,性能将会因为太多的overflow buckets下降。

二:如果分配期望增长的空间,那么大量的空间在开始的时候都浪费了。

三:如果数据库比较小,空间再次浪费了。

One Solution: 周期的用新的Hash函数重新组织文件。

缺点是:昂贵,打乱了正常的操作。

Better solution: 动态的改变桶的数目。

Extendible Hashing

既然桶装满了,为何不用双倍的桶来组织文件?

一:只需要分裂溢出的桶。(但是读写所有的文件是很昂贵的)

Idea:使用指向桶的指针目录,通过双倍指针目录来双倍桶。因为指针目录比文件小,所以双倍指针目录会更划算。

image 其中,指针目录(Directory)的大小为4。比如要插入5,它的二进制为(0101), 因为Global Depth = 2, 所以找到(01)的指针目录,插入所指向的桶中。

如果要插入20呢?因为20为(10100), 所以要插入00的指针目录中,但Bucket A 已经满了,这个时候,分裂Bucket A, 如果需要的话,还需要双倍指针目录(Directory)。

image

这个时候,可以看出Bucket A 分裂了,它的Local Depth为3了。所以32(100000), 16(10000)分配到一起;而4(100),12(1100), 20(10100)分配到一起。同时双倍了Directory。可以看到,Bucket C没有满,所以Local Depth为2。但是Global Depth中的001和101指向了它。

插入9(1001)呢?(这个时候导致分裂,但是没有导致双倍Directory)

image

Global depth of directory p: Max # of bits needed to tell which bucket an entry belongs to.

Local depth of a bucket q: # of bits used to determine if an entry belongs to this bucket.

Each bucket has image pointers to it from the directory.

When does bucket split cause directory doubling?

If the bucket has only 1 pointer to it from the directory, doubling the directory; Otherwise, simply redistribute the pointers after splitting.

When to merge bucket and shrink directory during deletion?

Merge Bucket: merge with its split image when bucket becomes empty.

Shrink directory: if every directory element and its split image directory entry point to the same bucket, shrink directory by ½.

Deciency:

Directory can grow large if the distribution of hash values is skewed.

Multiple entries with same hash value cause problems!

Linear Hashing

1:Handle long overflow chains.

2:Handle duplicates.

3: Idea: use a family of hash functions h0, h1, h2, ... hi+1 doubles the range of hi (similar to directory doubling) .

4: Splitting proceeds in “round”. (Round ends when all initial buckets are split. ).

5: Current round number is Level, and current function is hLevel。

address(level,key) = hash(key) mod  N * (2level)

image

当插入43 (101011)时, 导致overflow Bucket, 因为指针没有指向它,所以不分裂。但是此时Next指针向后移动而且指针指向的桶分裂。

image

image 

image

image

在Next指针前面的hash用H(level+1). 后面的用H(level).

image

通过指针的移动来分裂桶。

(All Above come from PPT of Ji Liping, HIT Shenzhen Graduate School)

### Voxel Hashing 技术详解 Voxel hashing 是一种用于高效存储和访问三维空间数据的技术,在计算机图形学和3D建模领域广泛应用。它通过将连续的三维空间划分为离散的小立方体(即体素),并利用哈希表来快速定位这些体素的位置。 #### 基本原理 Voxel hashing 的核心在于使用稀疏的数据结构表示三维场景中的体素[^1]。由于大多数实际应用中的三维模型并不完全填充整个空间,因此采用稠密数组会浪费大量内存资源。相反,voxel hashing 使用哈希函数将体素映射到一个紧凑的哈希表中,从而显著减少所需的存储量。 #### 数据结构设计 为了支持高效的查询操作,通常需要定义如下几个关键组件: - **Hash Function**: 将三维坐标 `(x, y, z)` 转换为唯一的键值,以便索引对应的哈希桶。 ```cpp uint64_t hash(uint32_t x, uint32_t y, uint32_t z) { const uint64_t prime = 73856093; return (uint64_t(x * prime ^ y * prime ^ z * prime)) % TABLE_SIZE; } ``` - **Table Entry Structure**: 每个哈希表条目保存有关该体素的信息,例如其位置、属性或其他元数据。 ```cpp struct VoxelEntry { int position_x, position_y, position_z; // 体素的空间位置 float density; // 密度或颜色等属性 bool occupied; // 是否被占用标志位 }; ``` #### 查询与更新机制 当程序接收到一个新的点云或者网格顶点时,可以通过以下方式将其分配至最近的体素单元,并执行相应的处理逻辑: 1. 计算目标点所属的体索单元编号; 2. 利用上述提到的哈希函数计算出对应于该体素的哈希槽地址; 3. 如果发现冲突,则尝试线性探测法解决碰撞问题直至找到空闲位置为止;如果未发生冲突则直接写入即可完成新增记录过程[^2]。 此外还需要注意边界条件以及溢出保护措施等问题以免造成错误结果输出甚至崩溃现象的发生。 ```python def insert_voxel(voxels_table, point_position): """Insert a new voxel into the table.""" key = compute_hash(point_position) while voxels_table[key].occupied and not compare_positions(voxels_table[key], point_position): key += 1 # Linear probing to resolve collisions if not voxels_table[key].occupied: initialize_entry(voxels_table[key], point_position) ``` 以上就是关于如何实现基于hash map方法来进行动态管理大规模复杂几何对象集合的一个简单介绍[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值