首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用其他数据结构替换二维数组

用其他数据结构替换二维数组
EN

Stack Overflow用户
提问于 2011-09-03 02:50:23
回答 4查看 2.6K关注 0票数 2

我有一个复杂的问题,我不知道我是否能恰当地描述它。

我有一个类的对象的二维数组。目前,我的算法只在这个二维数组上运行,但只占用了该数组的一些位置。(接近40%)

它对于小数据集工作得很好,但是如果我有大数据集( 2d数组中的大量元素,例如10000),那么程序就会耗尽内存。因为我有10000 * 10000 = 100000000次迭代的嵌套循环。

我可以用Hashtable或其他数据结构替换2D数组吗?我的主要目标是通过改变数据结构来减少迭代次数。

请原谅我没有很好地解释。我正在使用C#进行开发

EN

回答 4

Stack Overflow用户

发布于 2011-09-03 02:53:59

听起来您拥有的数据结构是一个稀疏矩阵,我将向您介绍Are there any storage optimized Sparse Matrix implementations in C#?

票数 4
EN

Stack Overflow用户

发布于 2011-09-03 03:09:22

您可以从数组坐标创建字典的键。类似于:

代码语言:javascript
运行
复制
int key = x * 46000 + y;

(这自然适用于类似于46000x46000的数组的坐标,这大约是您在int中可以容纳的大小。如果需要表示更大的数组,可以使用long值作为键。)

有了这个键,您就可以在Dictionary<int, YourClass>中存储和检索对象。从字典中存储和检索值非常快,并不比使用数组慢多少。

您可以迭代字典中的项,但您不会以可预测的顺序获得它们,即不同于循环数组的x和y坐标。

票数 1
EN

Stack Overflow用户

发布于 2011-09-03 03:26:05

如果您需要高性能,您可以降低自己的数据结构。如果对象只能包含在一个容器中,并且不能移动到其他容器中,则可以使用类似于数据结构的自定义哈希集。

将X、Y和Next字段添加到类中。您可以为存储在数组中的对象创建一个单链表,该数组就是您的哈希表。这可以非常非常快。

我从头开始写的,可能有bug。Clear和rehash都没有实现,这只是一个演示。所有运算的平均复杂度为O(1)。

为了便于在跳过空节点的所有节点上枚举,有一个双向链表。从双向链表中插入和删除的复杂度为O(1),并且您将能够枚举跳过未使用节点的所有节点,因此枚举所有节点的复杂度为O(n),其中n是节点的数量,而不是这个稀疏矩阵的“虚拟”大小。

使用双向链接表,您可以按照插入项的相同顺序枚举项。该顺序与X和Y坐标无关。

代码语言:javascript
运行
复制
public class Node
{
    internal NodeTable pContainer;
    internal Node pTableNext;
    internal int pX;
    internal int pY;
    internal Node pLinkedListPrev;
    internal Node pLinkedListNext;
}

public class NodeTable :
    IEnumerable<Node>
{
    private Node[] pTable;
    private Node pLinkedListFirst;
    private Node pLinkedListLast;

    // Capacity must be a prime number great enough as much items you want to store.
    // You can make this dynamic too but need some more work (rehashing and prime number computation).
    public NodeTable(int capacity)
    {
        this.pTable = new Node[capacity];
    }

    public int GetHashCode(int x, int y)
    {
        return (x + y * 104729); // Must be a prime number
    }

    public Node Get(int x, int y)
    {
        int bucket = (GetHashCode(x, y) & 0x7FFFFFFF) % this.pTable.Length;
        for (Node current = this.pTable[bucket]; current != null; current = current.pTableNext)
        {
            if (current.pX == x && current.pY == y)
                return current;
        }
        return null;
    }

    public IEnumerator<Node> GetEnumerator()
    {
        // Replace yield with a custom struct Enumerator to optimize performances.
        for (Node node = this.pLinkedListFirst, next; node != null; node = next)
        {
            next = node.pLinkedListNext;
            yield return node;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public bool Set(int x, int y, Node node)
    {
        if (node == null || node.pContainer != null)
        {
            int bucket = (GetHashCode(x, y) & 0x7FFFFFFF) % this.pTable.Length;

            for (Node current = this.pTable[bucket], prev = null; current != null; current = current.pTableNext)
            {
                if (current.pX == x && current.pY == y)
                {
                    this.fRemoveFromLinkedList(current);

                    if (node == null)
                    {
                        // Remove from table linked list

                        if (prev != null)
                            prev.pTableNext = current.pTableNext;
                        else
                            this.pTable[bucket] = current.pTableNext;
                        current.pTableNext = null;
                    }
                    else
                    {
                        // Replace old node from table linked list

                        node.pTableNext = current.pTableNext;
                        current.pTableNext = null;

                        if (prev != null)
                            prev.pTableNext = node;
                        else
                            this.pTable[bucket] = node;

                        node.pContainer = this;
                        node.pX = x;
                        node.pY = y;

                        this.fAddToLinkedList(node);
                    }

                    return true;
                }
                prev = current;
            }

            // New node.

            node.pContainer = this;
            node.pX = x;
            node.pY = y;

            // Add to table linked list

            node.pTableNext = this.pTable[bucket];
            this.pTable[bucket] = node;

            // Add to global linked list

            this.fAddToLinkedList(node);

            return true;
        }
        return false;
    }

    private void fRemoveFromLinkedList(Node node)
    {
        Node prev = node.pLinkedListPrev;
        Node next = node.pLinkedListNext;

        if (prev != null)
            prev.pLinkedListNext = next;
        else
            this.pLinkedListFirst = next;

        if (next != null)
            next.pLinkedListPrev = prev;
        else
            this.pLinkedListLast = prev;

        node.pLinkedListPrev = null;
        node.pLinkedListNext = null;
    }

    private void fAddToLinkedList(Node node)
    {
        node.pLinkedListPrev = this.pLinkedListLast;
        this.pLinkedListLast = node;
        if (this.pLinkedListFirst == null)
            this.pLinkedListFirst = node;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7287971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档