C:聪明的方法;shift";矩阵?

C:聪明的方法;shift";矩阵?,c,matrix,shift,C,Matrix,Shift,我有一个整数矩阵,它应该像一个缓冲区: x={{0,0,0,0,0},{1,1,1,1},{2,2,2} 现在,如果我添加一个新行{3,3,3,3,3},新矩阵应该如下所示: x={{1,1,1,1,1},{2,2,2,2},{3,3,3} 有没有一种聪明的方法可以在不复制周围所有元素的情况下执行此操作?使用链接列表 struct node { int row[5]; struct node *next; }; 追加一行非常简单,只需将列表遍历到底,然后用一个新节点(其下一个指

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

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

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

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

有没有一种聪明的方法可以在不复制周围所有元素的情况下执行此操作?

使用链接列表

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

追加一行非常简单,只需将列表遍历到底,然后用一个新节点(其下一个指针为NULL)替换空的下一个指针即可。

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

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

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


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

懒于编写代码示例-您可以使用模运算来处理行。在推送新行时,只需增加一个起始偏移量变量,添加矩阵高度并按矩阵高度对结果进行模运算。这样,您就可以得到一个循环矩阵,而无需复制整个矩阵并保持矩阵数组的一致性t、 模运算怎么样

如果以矩阵[x+SZ*y]
的形式访问元素,则可以将其更改为:

矩阵[x+SZ*((y+第一行)%SZ)]


通过这种方式来实现这个移位,您只需将新行{3,3,3..}放在行{0,0,0}的位置was,并增加
第一行
计数器以指向新的起始行。

这对算法有效,但当你实际处理矩阵时,它不会给出非常慢的结果吗?这取决于你用它做什么。如果你不一直扩展你的矩阵,你可能会更好地吸收偶然的结果nal memcpy。请注意,问题中的新行未“添加”到矩阵,而是替换第一行。因此,如果选择链表解决方案,请确保取消列表中的第一项。是的,我在编写时没有注意到这一点。如果矩阵不需要增长,@mikerobi的答案是一个更好的方法。听起来不错。我真的需要学习更面向指针的思考。:)唯一的问题是,与其他地方提出的链表解决方案不同,这里必须预先分配指向最大行数的指针。否则,它是一种比链表更有效的方法。编辑我刚刚注意到,在你的问题中,添加新行后,仍保留3行。如果这是有代表性的,那么你对@mikerobi的答案就没问题了。您只需要在交换行后管理指针。@ysap,一种偶尔增加行数的O(n)操作,通常比频繁的O(n)更有效地访问一个值。我通常同意,但是在一天结束时,它归结为分析应用程序的确切行为。下面的多个答案在技术上是正确的,但它们都涉及不同的权衡。你能稍微扩展一下你的预期用途吗?这些矩阵有多大?与从矩阵中访问数据的次数相比,您希望添加一行的频率是多少?您将访问矩阵的各个元素,还是将它作为一个完整的实体从头到尾读取?您是否希望能够不时释放矩阵的某些部分?如果是这样的话,从最后开始,或者从开始,或者从任意一行开始?矩阵并不大(比如总共100个元素)。我将始终访问整个矩阵,“旧”行可以消失(fifo队列行为),更新非常频繁。在这种情况下,@ruslik提出的模方法可能是最好的选择。只需分配一个可以处理最大大小的数组,保持一个指向当前头部的指针,并在空间不足时环绕数组的末尾。+1根据原始问题注释中的额外规范,这可能是提供最佳性能的替代方法。我现在实现了它,它工作正常。再次感谢大家,谢谢大家的回答!