当前位置: 首页 > 知识库问答 >
问题:

什么是O(1)搜索内存有效的数据结构来存储成对的整数?

国言
2023-03-14

请考虑以下接口:

public interface CoordinateSet {
    boolean contains(int x, int y);
    default boolean contains(Coordinate coord) {
        return contains(coord.x, coord.y);
    }
}

我们有很多方法可以实现这样的接口。计算效率最高的是由数组备份的实现:

public class ArrayCoordinateSet implements CoordinateSet {
    private final boolean[][] coords = new boolean[SIZE][SIZE];
    // ...
    @Override
    public boolean contains(int x, int y) {
        return coords[x][y];
    }
    public void add(int x,  int y) {
        coords[x][y] = true;
    }
    // ...

}

但是,如果size很大,例如1000,并且在1000×10000矩形的四个角度中,只有例如4个坐标属于集合,这意味着单元格空间的绝对大部分被false值所消耗。对于这样稀疏的CoordinateSet,我们最好使用基于hashsetCoordinateSet:

public final class Coordinate {
    public final int x;
    public final int y;
    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }
    // .equals() and hashCode()
}
public class HashBasedCoordinateSet implements CoordinateSet {
    private final Set<Coordinate> coords = new HashSet<>();
    @Override
    public boolean contains(int x, int y) {
        return coords.contains(new Coordinate(x, y));
    }
    @Override
    public boolean contains(Coordinate coord) {
         return coords.contains(coord);
    }
    public void add(Coordinate coord) {
        coords.add(coord);
    }
}

但是,对于HashBasedCoordinateSet我们有这样一个问题:

for (int x=0; x<1000; x++) {
  for (int y=0; y<1000; y++) {
    hashBasedCoordinateSet.contains(x, y);
  }
}

当我们具有值xy并且希望检查HashBasedCoordinateSet.contains(x,y)时,那么这将需要在每次方法调用时创建一个新对象(由于我们总是需要在HashSet中搜索对象,仅有对象的数据是不够的)。这将是对CPU时间的真正浪费(它需要创建所有的coordine对象,然后抓取收集它们,因为似乎无法对这些代码执行escape-analysis优化)。

所以最后,我的问题是:

  1. 具有O(1)包含(int x,int y)操作;
  2. 有效地使用空间(与基于数组的实现不同);
  3. 包含(int x,int y)期间不必创建额外的对象?

共有1个答案

杨鸿畅
2023-03-14

在Java中,long的大小是整数的两倍,因此可以在一个long中存储两个int。那这样怎么样?

public class CoordinateSet {
    private HashSet<Long> coordinates = new HashSet<>();

    public void add(int x, int y) {
        coordinates.add((x | (long) y << 32));
    }

    public boolean contains(int x, int y) {
        return coordinates.contains((x | (long) y << 32));
    }
}

我非常肯定contains方法上的long存储在堆栈上。

 类似资料:
  • 前面学习 数据结构的过程中,总是使用数组作为 顺序表的底层实现,给我们一种 "数据结构中,数组的作用就是实现顺序表" 的错误认识。其实,数组的作用远不止于此。 本节将从数据结构的角度讲解 数组存储结构。 本节所讲的数组,要将其视为一种存储结构,与平时使用的数组基本数据类型区分开。 一说起数组,我们的印象中数组往往是某一门编程语言中包含的具体数据类型,其实不然。 从本质上讲,数组与顺序表、 链表、

  • 即使在最坏的情况下,是否有任何数据结构可以提供O(1)——即常数——插入复杂性和O(log(n))搜索复杂性? 排序后的向量可以进行O(log(n))搜索,但插入需要O(n)(考虑到我并不总是在前面或后面插入元素这一事实)。而列表可以进行O(1)插入,但不能提供O(log(n))查找。 我想知道这样的数据结构是否可以实现。

  • 主要内容:图存储结构基本常识,图存储结构的分类我们知道,数据之间的关系有 3 种,分别是 "一对一"、"一对多" 和 "多对多",前两种关系的数据可分别用 线性表和树结构存储,本节学习存储具有"多对多"逻辑关系数据的结构—— 图存储结构。 图 1 图存储结构示意图 图 1 所示为存储 V1、V2、V3、V4 的图结构,从图中可以清楚的看出数据之间具有的"多对多"关系。例如,V1 与 V4 和 V2 建立着联系,V4 与 V1 和 V3 建立着

  • 主要内容:树的结点,子树和空树,结点的度和层次,有序树和无序树,森林,树的表示方法,总结之前介绍的所有的 数据结构都是 线性存储结构。本章所介绍的树结构是一种非线性存储结构,存储的是具有“一对多”关系的数据元素的集合。                                                                          (A)                                                          

  • 到目前为止,我们已经讨论了为了实现文件系统而需要存在于硬盘上的数据结构。 在这里,我们将了解要实现文件系统需要存在于内存中的数据结构。 内存数据结构用于文件系统管理以及通过缓存提高性能。 该信息在安装时间加载并在弹出时丢弃。 1. 内存安装表 内存中安装表包含正在安装到系统的所有设备的列表。 每当连接维护到设备时,其输入将在安装表中完成。 2. 内存目录结构缓存 这是CPU最近访问的目录列表。列表

  • 我必须选择一个数据结构为我的需要下面我解释的条件有以下值 现在,举个例子,如果我得到了ytr,那么我将能够检索到R1B1,或者,假设,我得到了rGGty的值,那么我将能够检索到R1B2 现在的情况是,重要的是搜索、复杂性和事情按顺序进行所需的时间 例如,它将首先选择要搜索的第一行,它将首先与不匹配的匹配,然后必须与匹配,然后再与不匹配的匹配,最后与匹配,最后找到键 类似地,如果需要搜索第二个字符串