Fortran中创建维度受限的逆映射INVMAP的实现方法问询
解决方案:两种方式实现轻量逆映射(无需大内存)
嘿,你的需求其实很好解决,因为映射是一一对应的,而且只需要处理3个元素,完全不用复杂的哈希表(当然现代Fortran也支持,下面也会讲),先给你两种实用的方案:
方案1:并行数组(兼容所有Fortran版本)
这种方法最稳妥,不需要任何高级特性,用两个小数组就能实现逆映射:
- 一个数组存原A的下标(对应你要的INVMAP的"键")
- 另一个数组存对应的B的下标(对应你要的INVMAP的"值")
代码实现
PROGRAM invmap_demo IMPLICIT NONE INTEGER, DIMENSION(3) :: MAP = [1, 5, 6] ! 已知的B→A映射 INTEGER, DIMENSION(SIZE(MAP)) :: invmap_keys, invmap_vals INTEGER :: i, target_a_idx, b_idx ! 初始化逆映射数组 DO i = 1, SIZE(MAP) invmap_keys(i) = MAP(i) ! 存储原A的下标 invmap_vals(i) = i ! 存储对应的B的下标 END DO ! 示例:查找A下标5对应的B下标 target_a_idx = 5 b_idx = get_b_index(target_a_idx) PRINT *, "A下标", target_a_idx, "对应B下标", b_idx CONTAINS ! 查找函数:输入A的下标,返回对应的B下标(没找到返回-1) FUNCTION get_b_index(x) RESULT(idx) INTEGER, INTENT(IN) :: x INTEGER :: idx, j idx = -1 ! 默认值,表示未匹配到有效下标 DO j = 1, SIZE(invmap_keys) IF (invmap_keys(j) == x) THEN idx = invmap_vals(j) EXIT ! 找到就退出循环 END IF END DO END FUNCTION get_b_index END PROGRAM invmap_demo
这个方案的优势:
- 完全兼容旧版Fortran,没有编译器版本限制
- 内存占用极小,只有两个维度为3的数组,完全符合你"INVMAP维度为3"的要求
- 因为只有3个元素,遍历查找的效率几乎可以忽略不计
方案2:关联数组(现代Fortran推荐)
如果你用的是Fortran 2003及以上版本的编译器(比如GCC 4.6+、Intel Fortran 12+),可以用关联数组(也就是哈希表)来实现,代码更简洁,查找是O(1)时间复杂度:
代码实现
PROGRAM invmap_assoc_demo IMPLICIT NONE INTEGER, DIMENSION(3) :: MAP = [1, 5, 6] ! 已知的B→A映射 INTEGER, ASSOCIATIVE :: invmap(:) ! 键是A的下标(INTEGER),值是B的下标(INTEGER) INTEGER :: i, target_a_idx ! 初始化关联数组 DO i = 1, SIZE(MAP) invmap(MAP(i)) = i END DO ! 示例:直接通过A的下标查找B的下标 target_a_idx = 6 IF (ASSOCIATED(invmap, target_a_idx)) THEN ! 检查键是否存在 PRINT *, "A下标", target_a_idx, "对应B下标", invmap(target_a_idx) END IF END PROGRAM invmap_assoc_demo
这个方案的优势:
- 代码非常简洁,直接通过
invmap(原A下标)就能拿到对应的B下标 - 只存储有效映射,内存占用同样是3个键值对,不会浪费空间
- 查找效率更高(虽然对于3个元素来说差别不大,但如果后续扩展到更多元素,优势会明显)
关键注意点
- 因为你提到A太大无法存入内存,这两个方案都完全不需要实际分配A数组,所有操作都是基于已知的
MAP数组完成的,完美适配你的场景 - 由于
MAP是一一对应的无冲突映射,所以两种方案都不会出现重复键的问题,查找结果唯一 - 如果你不需要主动查找,只是需要存储逆映射关系,方案1的两个并行数组已经完全满足需求,甚至不需要写查找函数——直接遍历就能对应上
内容的提问来源于stack exchange,提问作者sponce
相关产品推荐
相关产品推荐

