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