请考虑以下接口:
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,我们最好使用基于hashset
的CoordinateSet
:
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);
}
}
当我们具有值x
和y
并且希望检查HashBasedCoordinateSet.contains(x,y)
时,那么这将需要在每次方法调用时创建一个新对象(由于我们总是需要在HashSet
中搜索对象,仅有对象的数据是不够的)。这将是对CPU时间的真正浪费(它需要创建所有的coordine
对象,然后抓取收集它们,因为似乎无法对这些代码执行escape-analysis优化)。
所以最后,我的问题是:
包含(int x,int y)
操作;包含(int x,int y)
期间不必创建额外的对象?在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 现在的情况是,重要的是搜索、复杂性和事情按顺序进行所需的时间 例如,它将首先选择要搜索的第一行,它将首先与不匹配的匹配,然后必须与匹配,然后再与不匹配的匹配,最后与匹配,最后找到键 类似地,如果需要搜索第二个字符串