Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可向任意方向延伸的二维对象网格C++;_C++_Data Structures_Dynamic_Grid - Fatal编程技术网

C++ 可向任意方向延伸的二维对象网格C++;

C++ 可向任意方向延伸的二维对象网格C++;,c++,data-structures,dynamic,grid,C++,Data Structures,Dynamic,Grid,创建二维对象网格的最佳方法是什么?该网格可以在任何方向上动态扩展,而无需在凹形的空部分分配内存 我曾考虑让该类包含指向相邻对象的数据成员(一个用于北、东、南和西),但这似乎不是最好的方法,而且它还缺乏引用具有绝对值(即(6,-5))的某个正方形的能力。 如果这个问题让人困惑,请提问,我会尽力更好地解释这个问题。也许可以存储一个std::deque of std::deque,其中每个内部deque对应于网格中的一行。然后可以存储用于每一行的第一个x坐标。Deques可以从正面或背面高效生长 请注

创建二维对象网格的最佳方法是什么?该网格可以在任何方向上动态扩展,而无需在凹形的空部分分配内存

我曾考虑让该类包含指向相邻对象的数据成员(一个用于北、东、南和西),但这似乎不是最好的方法,而且它还缺乏引用具有绝对值(即(6,-5))的某个正方形的能力。

如果这个问题让人困惑,请提问,我会尽力更好地解释这个问题。

也许可以存储一个std::deque of std::deque,其中每个内部deque对应于网格中的一行。然后可以存储用于每一行的第一个x坐标。Deques可以从正面或背面高效生长

请注意,它不能很好地处理间隙/孔

查找示例:

如果希望元素位于(4,2),则应查看开始的y坐标。假设是-3。然后,行[0]将对应于y=-3,行[5]将对应于y=2


假设行[5]具有起始x坐标2。然后,行[5].cols[0]将表示(2,2)处的任何内容。我们希望(4,2)处的对象有行[5].cols[2]。

这里只是抛出一个想法:

拿一个键/值容器,比如说
std::map
,或者一个自平衡二叉搜索树或类似的


使用64位整数作为键。使用高32位作为X坐标,低32位作为Y坐标。因此,要找到点
(x,y)
,需要查找
((uint64_t)x)两级结构如何:一个带有指向其他矩阵指针的矩阵,当您需要时,您可以分配较小的矩阵。以下是1000x1000个分片的示例,每个分片的大小为100x100。这些矩阵被线性化以简化内存分配。如果您想获得更好的粒度,可以将其作为矩阵矩阵的矩阵丽蒂

#define N 100
#define M 1000
using namespace std;
int *mat[M*M];

void set(int x,int y,int value)
{ int hx=x/N;
  int hy=y/N;
  int lx=x%N;
  int ly=y%N;

  if(mat[hx+hy*N]==NULL)
  { mat[hx+hy*N]=new int[N*N];
  }
  mat[hx+hy*N][lx+ly*N]=value; 
}

int get(int x,int y)
{ int hx=x/N;
  int hy=y/N;
  int lx=x%N;
  int ly=y%N;
  if(mat[hx+hy*N]==NULL)
  { return -1;
  }
  return mat[hx+hy*N][lx+ly*N]; 
}
通过将
N
M
2^k
替换为位移位,可以避免代价高昂的除法和模运算:
x/128
x>>7
x*128
x7
内部)

const int region_size = 16; //powers of two only!  4, 8, 16, 32, 64, etc
const int region_minor = region_size-1;
const int region_major = ~region_minor;
typedef std::array<region_size, std::array<region_size, point> > region; //a 16 by 16 region
std::map<std::pair<int, int>, region> world;

point& getPoint(int x, int y) {
    std::pair<int,int> major_coords(x&region_major, y&region_major);
    region &r = world[major_coords]; //get region
    return r[x&region_minor,y&region_minor]; //return the point in this region
}
//This creates points/regions as they're needed as well.
const int region\u size=16//只有两种力量!4、8、16、32、64等
const int region_minor=region_size-1;
const int region_major=~ region_minor;
typedef std::数组区域//一个16乘16的区域
地图世界;
点和获取点(整数x,整数y){
标准:配对专业(x和地区专业,y和地区专业);
region&r=world[major_coords];//获取区域
返回r[x&区域_小调,y&区域_小调];//返回该区域中的点
}
//这会根据需要创建点/区域。

这允许在所有维度(包括负数,这在数组中很难实现)和间隙中进行无限扩展。根据您所做的工作,您通常希望一次接触一个区域中的多个点,如果您有一张点的地图,这将在内存和时间上产生大量额外的开销。如果你制作一个小区域的地图,它会占用更少的内存和时间。

我们是在分配一小部分可以位于(有效)无限平面上任何位置的对象,还是分配一个非常大的数字网格,其中大多数初始化为某个初始值(如0)?使用你的技术,我不认为它缺少引用某个正方形的能力。你可以有一个0,0的“根”平方。然后,您可以根据输入值从根平方遍历到所需的平方。大量对象初始化为一个值。我忘了提到,在它的应用程序中,新对象只能在一个或多个现有对象附近创建,因此您永远不会有多个对象体完全分离。您需要以何种方式访问这些对象,这是关键问题。有很多方法可以做到这一点,每种方法都专门用于某种类型的查找。@Dalal:如果遍历像他描述的那样稀疏,则遍历速度非常慢。这不能真正扩展,不是吗?它相当于“放大”。还是我弄错了?它并没有扩展到无穷大,它只是一个矩阵矩阵,并不是所有嵌入的矩阵都存在。大多数编译器都会正确地将除法/模替换为位移位。@Titus:不要在std::map中使用哈希函数。如果您想要一个哈希表,请使用哈希表。我认为std::pair在可读性方面比64位整数好得多,在非重复项方面比哈希好得多。使用
std::pair而不是64位int好吗?我最终使用了std::map和std::pair,以避免出现负值问题。事实上,对于密集网格,这可能是一个非常干净的解决方案!比滚动自己的2D链表容易得多(而且可能更节省内存)。无法很好地处理间隙或孔,并且您必须回忆每个子块的偏移量。CPU会缓存16x16磁贴并在后续查询中更快地访问它吗?现在我已经用数组替换了向量(就像我最初所想的那样)是的。16x16区域将保留在缓存中。