C++ 在数组中间添加新索引 我知道我可以删除一个数组的中间部分,比如 char* cArray = (char*) malloc(sizeof(char) * sizeTracker);

C++ 在数组中间添加新索引 我知道我可以删除一个数组的中间部分,比如 char* cArray = (char*) malloc(sizeof(char) * sizeTracker);,c++,arrays,C++,Arrays,使用memmove功能。这样,在不必使用临时数组、切换到向量等的情况下,可以从数组中移除一些东西。这里的问题是,是否可以在数组的中间添加一个新索引(是否有一个函数)?或者说,使用realloc我在末尾添加了一个新的索引,那么如何有效地向下移动这些值呢 没有自定义的C函数允许使用C内存函数增加数组并在中间插入对象。基本上,您可以使用malloc()、free()、memmove()(当内存中有足够的空间且元素刚刚移回内存时)或memcpy()(如果您需要分配新内存,并且希望避免先复制后移动尾部),

使用
memmove
功能。这样,在不必使用临时数组、切换到向量等的情况下,可以从数组中移除一些东西。这里的问题是,是否可以在数组的中间添加一个新索引(是否有一个函数)?或者说,使用
realloc
我在末尾添加了一个新的索引,那么如何有效地向下移动这些值呢

没有自定义的C函数允许使用C内存函数增加数组并在中间插入对象。基本上,您可以使用
malloc()
free()
memmove()
(当内存中有足够的空间且元素刚刚移回内存时)或
memcpy()
(如果您需要分配新内存,并且希望避免先复制后移动尾部),来构建功能

在C++中,对象位置往往很重要,显然您会使用<代码> STD::Copy[/]代码>,<代码> STD::ReaveScript Copy](和/或代码>和/或<代码> STD::MOVER()/<代码>(两种形式),因为Abor对象可能有相关的结构。很可能您也会获得不同的内存,例如,使用
operator new()
和/或分配器(如果您确实使用原始内存)

实际插入的有趣实现(假设有足够的空间容纳另一个元素)是使用
std::rotate()
构造最后一个元素,然后洗牌元素:

 void insert(T* array, std::size_t size, T const& value) {
     // precodition: array points to at least size+1 elements
     new(array + size) T(value);
     std::rotate(array, array + size, array + size + 1);
 }

当然,这并不能避免在需要重新定位数组时对元素进行不必要的洗牌。在这种情况下,分配新的内存并将初始对象移动到起始点,添加新插入的元素,将尾随对象移动到新对象的位置,更有效。

< P>您已将此帖子标记为C++。p>

可以在数组中间添加一个新索引(是否存在函数) (仅此而已)

编号来自cppreference.com,std::array:

数组是封装固定大小数组的容器

我认为这意味着您可以更改元素,但不能更改索引


(叹气)但我怀疑C风格的数组仍然是允许的。
我注意到Dietmar的回答也是否定的。

如果您使用的是手动分配的内存,您必须这样做,并且您应该希望此操作不会将内存块移动到新位置。那么最好是使用算法

顺便说一下,对于这类任务,我们更喜欢stl容器,比如向量,而不是手动分配内存。如果您使用的是矢量,您应该保留内存。

备选答案 我一直在思考这个问题,@DietmarKühl开始谈论像deque一样插入块。问题在于,deque是块的链接列表,因此不能从数组开始。如果你从一个数组开始,然后想在中间插入一些东西,你必须做其他的事情,我想我有一个想法——它不是很充实,所以它可能不起作用,但是我还是会分享它。请留下评论,告诉我你对这个想法的看法

如果您有一个项目数组,然后想要在中间添加一个项目,那么您真正想要做的就是添加一个块并更新映射。映射是使所有工作正常进行的因素,但它会降低访问速度,因为您需要在每次访问阵列之前检查映射

映射将是一个二叉树。它将开始为空,但节点将包含一个值:如果您想要的索引<您遍历左指针的值,如果它>=您遍历右指针

举个例子:

在插入之前:

root -> (array[100000], offset: 0)
插入5000后:

root -> {value: 5000,
         left:  (array[100000], offset: 0),
         right: {value: 5001,
                 left:  (newarray[10], offset: -5000),
                 right: (array[100000], offset: 1),
                }
        }
我在这里使用了10个块-newarray的大小是10。如果只是在所有位置随机插入索引,则块大小应为1,但如果插入blovk大小大于1的连续索引组,则效果会更好。这真的取决于你的使用模式

当您检查索引7000时,您检查根节点:7000大于等于5000,因此您跟随右指针:7000大于等于5001,因此您跟随右指针:它指向偏移量为1的原始数组,因此您访问数组[索引+偏移量]

当您检查索引700时,您会检查根节点:700小于5000,因此您会跟随左指针:它指向偏移量为0的原始数组,因此您可以访问数组[index+offset]

当您检查索引5000时,您检查根节点:5000大于等于5000,因此您跟随右指针:5000小于5001,因此您跟随左指针:它指向偏移量为-5000的新数组,因此您访问newarray[索引+偏移量]

当然,对这一点进行优化对于使其变得有用非常重要-您必须在每次插入后平衡树,否则右侧将比左侧长得多

这样做的缺点是,现在对阵列的访问是O(日志插入),而不是O(1),因此,如果有大量插入,您可能希望每隔一段时间重新执行一次,以将数据结构压缩回阵列,但您可以将其保存到适当的时间

就像我说的,它不是很充实,所以在实践中可能不起作用,但我希望它无论如何都值得分享

原始答案

如果你有一个C风格的数组,并且想要在中间插入一个索引,那么你需要一个比你需要的数组大的数组(加上一个变量,比如sisi跟踪器来跟踪大小)。

那么如果有剩余的空间,你可以把数组的最后一半移动到中间来创建一个点。

如果没有任何剩余空间,您可以将另一个包含额外空间的整个阵列malloc,然后分别将上半部分和下半部分memmove,留下一个间隙

若你们想使malloc摊销时间恒定,你们需要将a的大小增加一倍