我有一个恒定大小的数组x(通常大约100-200个条目),并希望在头部添加一个常数较小(通常在2-10个条目之间)的数组y,同时删除相同的大小结束。例如:
缓冲液: x = [6 5 4 3 2 1]
要添加的新数组: y = [8 7]
产生的缓冲区: x = [8 7 6 5 4 3]
等等......
注意:我需要使用常规C数组,并且需要能够访问整个数组,而不仅仅是头部或尾部。该数组相当小,但该函数经常被调用,所以我正在寻找一个不需要任何过多内存任务的解决方案。在每一步中,数组x和y的大小始终相同。
这是缓冲区,循环/环形缓冲区,队列还是FIFO?我真的不知道这个应用程序的正确搜索词是什么。
语言是C.
答案 0 :(得分:2)
如何使用memmove()
中的<string.h>
来移动数组的切片?如果没有实际测量性能,那就不能排除。使用链表的任何解决方案都可能涉及比高度优化的memmove()
(编译器甚至内联)更长的操作。
这实际上取决于
答案 1 :(得分:2)
如果您需要线性访问数组内容,并且您不想执行频繁的memcpy
操作,可能的解决方案是翻转缓冲区或滑动缓冲区< /强>
翻转缓冲区的大小是数组需要的两倍(如果你愿意的话,甚至更多),这样你就可以在添加到结尾时只移动一个尾指针,而不需要任何环绕,保持数据的线性。
当您达到底层缓冲区的硬限制时,则执行滑动操作:将数组的上半部分移动到下半部分,并从所有索引中减去相同的增量。
当这个幻灯片操作发生时,你知道现在所有的数据和索引都在上层分区,因为缓冲区2 * N
,宽度从不包含超过N
个条目:它是模拟的一个N
大小的环形缓冲区。也就是说,情况永远不会出现尾部已经到达缓冲区的末尾,但是头部仍然在下部分区中(有超过N
个项目。)
由于您想要添加到前面,我们首先填充上部分区,然后向上翻转:
[x x x x x x | 6 5 4 3 2 1 ] -- six-element queue, twelve el. buffer
H T
Add 8 7, remove 2 1:
[x x x x 8 7 | 6 5 4 3 x x ]
H T
Add 2 1 0 9, remove 6 5 4 3:
[2 1 0 9 8 7 | x x x x x x ]
H T
头部已达到-1!使用memcpy
翻转到上部分区,在头部和尾部添加6:
[x x x x x x | 2 1 0 9 8 7 ]
H T
请注意,由于这两个分区不重叠,因此我们不必使用memmove
:我们可以使用memcpy
。
答案 2 :(得分:0)
您需要的是索引偏移量。因此,每次“插入”值时,只需将它们写在虚拟尾部所在的位置并更新索引偏移量。这就是循环缓冲区的工作原理。
答案 3 :(得分:0)
这是重复的。以下是代码审核https://codereview.stackexchange.com/questions/64258/array-implementation-of-queue中的Java实现以及此处C Queue using Arrays中的一个问题。