Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.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# - Fatal编程技术网

C# 高效地将对象矩阵复制到更大的对象矩阵

C# 高效地将对象矩阵复制到更大的对象矩阵,c#,C#,我正在编写一个类似四叉树的数据结构,其中包含通用对象的矩阵T。如果四个子节点都包含定义的T矩阵,我将把它们聚合成一个更大的矩阵,然后删除子节点。有没有比循环遍历每个引用并复制它更有效的方法呢?我可以复制内存块吗 示例: T[,] _leaf1 = new T[64,64]; T[,] _leaf2 = new T[64,64]; T[,] _leaf3 = new T[64,64]; T[,] _leaf4 = new T[64,64]; // Populate leafs T[,] _r

我正在编写一个类似四叉树的数据结构,其中包含通用对象的矩阵
T
。如果四个子节点都包含定义的
T
矩阵,我将把它们聚合成一个更大的矩阵,然后删除子节点。有没有比循环遍历每个引用并复制它更有效的方法呢?我可以复制内存块吗


示例:

T[,] _leaf1 = new T[64,64];
T[,] _leaf2 = new T[64,64];
T[,] _leaf3 = new T[64,64];
T[,] _leaf4 = new T[64,64];

// Populate leafs

T[,] _root = new T[128,128];

CopyInto(ref _root, ref _leaf1, 64, 64);
CopyInto(ref _root, ref _leaf2, 0, 64);
CopyInto(ref _root, ref _leaf3, 0, 0);
CopyInto(ref _root, ref _leaf4, 64, 0);

也许我在这里偏离了基准,但是如果您将
T
约束为引用类型,那么您将只复制引用而不是数据本身。因此,只需在新矩阵中创建对
T
对象的新引用,并将它们从旧矩阵中删除即可。下面是如何约束
T
。注意
where
class
关键字的使用

public class Foo<T> where T: class
{
}
公共类Foo其中T:class
{
}

如果你能使结构不可变,你也许可以省去大量复制的麻烦。埃里克·利珀特有一些

编辑: 同样,我不知道在您的情况下它是否会提高性能,但下面是一个使用不可变对象的可能设计示例:

abstract class QuadTree<T>
{
    public QuadTree(int width, int height)
    {
        this.Width = width;
        this.Heigth = heigth;
    }

    public int Width { get; private set; }
    public int Height { get; private set; }

    public abstract T Get(int x, int y); 
}

class MatrixQuadTree<T> : QuadTree<T>
{
    private readonly T[,] matrix;

    public QuadTree(T[,] matrix, int width, int heigth)
        : base(width, heigth)
    {
        this.matrix = matrix;
    }

    public override T Get(int x, int y)
    {
       return this.matrix[x, y];
    }
}

class CompositeQuadTree<T> : QuadTree<T>
{
    private readonly QuadTree<T> topLeft;
    private readonly QuadTree<T> topRight;
    private readonly QuadTree<T> bottomLeft;
    private readonly QuadTree<T> bottomRight;

    public CompositeQuadTree(QuadTree<T> topLeft,
        QuadTree<T> topRight, QuadTree<T> bottomLeft,
        QuadTree<T> bottomRight)
        : base(topLeft.Width + topRight.Width, 
            topLeft.Height + bottomLeft.Heigth)
    {
        // TODO: Do proper checks.
        if (this.Width != topLeft.Width + bottomRight.Width)
            throw Exception();

        this.topLeft = topLeft;
        this.topRight = topRight;
        this.bottomLeft = bottomLeft;
        this.bottomRight = bottomRight;
    }

    public override T Get(int x, int y)
    {
        if (x <= this.topLeft.Width)
        {
            if (y <= this.topLeft.Width)
            {
                return this.topLeft.Get(x, y);
            }
            else
            {
                return this.topLeft.Get(x, y + this.topLeft.Heigth);
            }
        }
        else
        {
            if (y <= this.topLeft.Width)
            {
                return this.topRight.Get(x + this.topLeft.Width, y);
            }
            else
            {
                return this.topRight.Get(x + this.topLeft.Width, 
                    y + this.topLeft.Heigth);
            }
        }
    }
}
抽象类四叉树
{
公共四叉树(整数宽度、整数高度)
{
这个。宽度=宽度;
这个.Heigth=Heigth;
}
公共整数宽度{get;私有集;}
公共整数高度{get;私有集;}
公共摘要T-Get(int x,int y);
}
类矩阵四叉树:四叉树
{
私有只读T[,]矩阵;
公共四叉树(T[,]矩阵,整数宽度,整数高度)
:底座(宽度、高度)
{
这个矩阵=矩阵;
}
公共覆盖无法获取(整数x,整数y)
{
返回这个矩阵[x,y];
}
}
类CompositeQuadTree:四叉树
{
私有只读四叉树左上角;
私有只读四叉树右上角;
私有只读四叉树左下角;
私有只读四叉树右下角;
公共合成树(四叉树左上角,
四叉树右上角,四叉树左下角,
四叉树(右下角)
:底部(左上角宽度+右上角宽度,
左上角。高度+左下角。高度)
{
//TODO:做适当的检查。
if(this.Width!=左上角.Width+右下角.Width)
抛出异常();
this.topLeft=topLeft;
this.topRight=topRight;
this.bottomLeft=bottomLeft;
this.bottomRight=bottomRight;
}
公共覆盖无法获取(整数x,整数y)
{

如果(x可能?那将复制内存块。

如果你不怕使用不安全的代码,并且可以使用引用,那么你可以使用老式的指针。你必须首先对数组使用
固定的
关键字。

多维数组将每个维度依次对齐。

决定将我的评论作为答案


换句话说,您正在将矩阵的元素复制到其他矩阵?您可以使用
数组.CopyTo
缓冲区.BlockCopy
(复制只需几微秒)

此外,如果修改设计使其不是
array[64]
,而是
array[64*64]
,并使用模(
%
)/multiply(
*
)来获取/设置元素,则速度会更快。但不确定性能瓶颈在哪里。这取决于访问矩阵元素的频率与复制的频率

public class Matrix<T>
{
    private int size;
    private T[] elements;

    public Matrix(int size)
    {
        this.size = size;
        this.elements = new T[size];
    }

    T this[int x, int y]
    {
        get
        {
            return elements[x + (y*size)];
        }
        set
        {
            elements[x + (y*size)] = value;
        }
    }

    public void CopyTo(Matrix<T> destination, int x, int y)
    {
        int offset = x + (y*size);
        T[] destinationArray = (T[])destination;
        Buffer.BlockCopy(this.elements, 0, destinationArray, offset, this.elements.Length);
    }

    public static explicit operator T[] (Matrix<T> matrix)
    {
        return matrix.elements;
    }
}
公共类矩阵
{
私有整数大小;
私有T[]元素;
公共矩阵(整数大小)
{
这个。大小=大小;
this.elements=新的T[尺寸];
}
T这[int x,int y]
{
得到
{
返回元素[x+(y*大小)];
}
设置
{
元素[x+(y*大小)]=值;
}
}
公共无效复制目标(矩阵目标,整数x,整数y)
{
整数偏移=x+(y*大小);
T[]目的地阵列=(T[])目的地;
BlockCopy(this.elements,0,destinationArray,offset,this.elements.Length);
}
公共静态显式算子T[](矩阵)
{
返回矩阵元素;
}
}
在代码中:

Matrix<int> leaf = new Matrix<int>(64);
Matrix<int> root = new Matrix<int>(128);
leaf.CopyTo(root, 0, 0);
矩阵叶=新矩阵(64);
矩阵根=新矩阵(128);
叶。复叶(根,0,0);

如何准确地重新表示矩阵?如何聚合?如果项目是引用类型,您只是复制了一个指针(4/8字节),如果速度相当快的话。那里只有4个(列表)项目,对吗?我添加了一个示例。在我的结构中,
\u leafX
将位于子节点中,带有
void copyito(ref T[,],p点)
换句话说:您正在将矩阵的元素复制到其他矩阵?您可以使用
数组.CopyTo
缓冲区.BlockCopy
(复制只需要几微秒)。此外,如果您修改设计,使其不是
数组[64]
,而是
数组[64*64]
,并使用模(
%
)检查行的速度会更快。但不确定性能瓶颈在哪里。这取决于访问矩阵元素的频率与复制的频率。顺便说一句,你所做的与四叉树所做的相反。QT是分裂,你在合成。我知道,但我不确定还能称之为什么。最后,你以一个类似四叉树的结构。这是一个很好的观点,如果需要的话,我可以将泛型限制为对象,但这仍然需要循环遍历要复制的每个指针。@Brian问题的关键是找到一个不需要循环的解决方案。我不认为对于类,我不会复制整个对象的数据。如果我正确理解OP的需求,根矩阵中可能已经有一些数据,您可以简单地覆盖它们。但可能这是他正在寻找的解决方案-这取决于他的需要。他并没有真正使用四叉树,只是一个简单的矩阵。当然很难判断这是否是他需要的。我只是给出了一个可能有趣的方向
Matrix<int> leaf = new Matrix<int>(64);
Matrix<int> root = new Matrix<int>(128);
leaf.CopyTo(root, 0, 0);