【问题标题】:C: clever way to "shift" a matrix?C:“移动”矩阵的巧妙方法?
【发布时间】:2010-11-02 13:54:23
【问题描述】:

我有一个整数矩阵,它应该像一个缓冲区:

x = {{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}};

现在,如果我添加一个新行 {3, 3, 3, 3, 3},新矩阵应该如下所示:

x = {{1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}, {3, 3, 3, 3, 3}};

有没有一种巧妙的方法可以在不复制所有元素的情况下做到这一点?

【问题讨论】:

  • 以下多个答案在技术上是正确的,但它们都涉及不同的权衡。你能扩展一下你的预期用途吗?这些矩阵有多大?与您从矩阵中访问数据的次数相比,您希望添加一行的频率是多少?您将访问矩阵的各个元素,还是仅将其从头到尾作为整个实体读取?您是否希望能够不时释放部分矩阵?如果是这样,只是从末尾开始,还是从开头开始,还是从任意行开始?
  • 矩阵不大(总共有 100 个元素)。我将始终访问整个矩阵,“旧”行可以消失(fifo 队列行为),更新经常发生。
  • 在这种情况下,@ruslik 提出的模数方法可能是您最好的选择。只需分配一个可以处理最大大小的数组,维护一个指向当前头部的指针,并在空间不足时环绕数组的末尾。

标签: c matrix shift


【解决方案1】:

如果您的矩阵被定义为 int ** 并且您分别分配每一行,那么您只需交换行指针。

【讨论】:

  • 听起来不错。我真的需要学会更多地面向指针思考。 :)
  • 唯一的问题是,与其他地方提出的链表解决方案不同,在这里您必须预先分配指向您将拥有的最大行数的指针。否则,它是比链表更有效的方法。 编辑我刚刚注意到,在您的问题中,添加新行后您仍然保留 3 行。如果这是有代表性的,那么您对@mikerobi 的回答就可以了。一旦行被交换,你只需要管理你的指针。
  • @ysap,偶尔的 O(n) 操作来增加行数,通常会比频繁的 O(n) 更有效地访问一个值。
  • 我一般同意,但归根结底,它归结为分析应用程序的确切行为。
【解决方案2】:

模运算怎么样?

如果您以matrix[x + SZ * y] 身份访问元素,您可以将其更改为:

matrix[x + SZ * ((y + FIRST_ROW) % SZ)]

通过这种方式来实现这种转变,您只需将新行 {3, 3, 3..} 放在行 {0, 0, 0} 所在的位置,并增加 FIRST_ROW 计数器以指向新的起始行.

【讨论】:

  • +1 基于原始问题的 cmets 中的额外规范,这可能是提供最佳性能的替代方案。
  • 我现在实现了它,它工作正常。再次感谢,感谢所有其他答案!
【解决方案3】:

使用链表。

struct node
{
    int row[5];
    struct node *next;
};

追加一行就像将列表遍历到末尾一样简单,然后将 NULL 下一个指针替换为一个新节点(其下一个指针为 NULL)。

【讨论】:

  • 这适用于算法,但是当您实际使用矩阵进行操作时,它不会给出非常慢的结果吗?
  • 这取决于你用它做什么。如果你不是一直在扩展你的矩阵,你最好吸收偶尔的 memcpy。
  • 请注意,在问题中,新行不是“添加”到矩阵中,而是替换了第一行。因此,如果您选择链表解决方案,请确保您取消列表中的第一项。
  • 是的,我写的时候没有注意到。如果矩阵不需要增长,@mikerobi 的答案是一个更好的方法。
【解决方案4】:

你能增加x 使其指向第二行,然后释放第一行吗?显然,您需要一次分配一行,这不能保证矩阵是连续的。如果你需要,你可以分配一大块内存来保存你的矩阵,然后在你到达终点时破坏未使用的部分。

【讨论】:

    【解决方案5】:

    如果您使用指向数组的指针数组(而不是普通的二维数组),则可以只复制指向行的指针,而不是复制所有元素。

    如果您对过度分配指针数组感到满意,您可以在末尾添加一个新指针并将指针前进到数组的“开始”。但是,如果您可能想要多次进行这种转变,这不是一个好主意。当然,您需要确保在某处拥有原始指针,以便正确地free() 您的资源。

    【讨论】:

      【解决方案6】:

      懒惰地编写代码示例 - 您可以使用模算术来处理行。推新行时,只需增加一个起始偏移变量,加上矩阵高度,然后以矩阵高度取模。这样您就可以得到一个圆形矩阵,无需复制整个矩阵并保持矩阵数组紧凑。

      【讨论】:

        猜你喜欢
        • 2023-03-07
        • 1970-01-01
        • 1970-01-01
        • 2015-11-03
        • 2021-07-28
        • 2012-04-24
        • 2016-04-19
        • 1970-01-01
        • 2020-10-12
        相关资源
        最近更新 更多