优化将一个数组插入另一个数组 C/C++

Posted

技术标签:

【中文标题】优化将一个数组插入另一个数组 C/C++【英文标题】:Optimizing Inserting One Array into Another Array C/C++ 【发布时间】:2011-11-16 14:31:38 【问题描述】:

我的自定义动态数组类中有这个函数,它允许用户将另一个数组插入到这个数组中。它有效,但我有 99% 的把握这不是最快的解决方案,我想知道是否可以结合两个 for 循环来提高性能?如果是这样,怎么做?我有点卡住了。

提前致谢。

void insertrange(T item[], int sizerange, int index) 
    
        int k = this->size;
        int j = 0;
        if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
        
            this->enlarge(this->capacity + sizerange); //enlarge the array
        
        for(k; k >= index; k--) //for every element from the end to the index where to add the new array
        
            this->array[k + sizerange] = a[k]; //replace the element to his new spot
        
        for(j; j < sizerange; j++) //vor every element in the new array
        
            this->array[index + j] = item[j]; //place it in the new spot
        
        size += sizerange; 
    

【问题讨论】:

在尝试优化之前测量性能。如果有,瓶颈在哪里? 您是否通过分析发布版本证明这是您应用程序中的真正瓶颈? 我假设这是家庭作业 - 否则你只会使用 std::vector! 这不是真正的瓶颈,也不是功课。我试图制作一个比 std::vector 更快的数组,所以我试图压缩我能做到的每一点性能:) 可能发现std::copystd::reverse_copyfor循环快,如果T是一个POD类型并且你的库有一个汇编优化执行。你必须测量它才能确定。 (无论如何,这可能是一个好主意,既为了可读性,又为了减少引入像第一个循环中的错误这样的错误的机会)。 【参考方案1】:

我认为关键是您不必复制空单元格。

   void insertrange(T item[], int sizerange, int index) 
    
        // This actually points past the end of the current array, right?
        int onePastLastEntry = this->size;
        // Still need to make sure the new array is large enough
        if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
        
            this->enlarge(this->capacity + sizerange); //enlarge the array
        
        // you should be able to go forward instead of backwards
        for(i = index; i < onePastLastEntry ; i++)
        
            // move the current element
            this->array[i + sizerange] = a[i];
            // then copy the new value
            this->array[i] = item[i - index];
        

您实际上可以从零开始循环,也可以转到onePastLastEntry - index,但这会使数学变得奇怪:

        // you should be able to go forward instead of backwards
        for(i = 0; i < onePastLastEntry - index; i++)
        
            // now you have to add the index in two places here
            this->array[i + index + sizerange] = a[i + index];
            // and add the index in the copy as well
            this->array[i + index] = item[i];
        

【讨论】:

【参考方案2】:

我看到的唯一可能的性能优势是,每次数组变大时,动态分配都会减少。在大多数情况下,每次需要重新分配时将容量乘以 2 会更好。

【讨论】:

我猜这是通过放大功能在幕后处理的。如果不是,应该是。 我明白了,我明白了。谢谢:) 我认为以某种方式组合两个循环会更快。感谢您的回答【参考方案3】:

你的 k for 循环中有一个额外的副本。 k 索引应该从 size-1 开始,而不是 size,因此您将复制一个超出数组末尾的额外元素。但是,这将提供可以忽略不计的加速。如果需要大幅提升性能,您应该考虑优化放大功能或使用与数组不同的数据结构。

【讨论】:

【参考方案4】:

您可以移动元素,而不是复制它们:

for(k; k >= index; k--)

    this->array[k + sizerange] = std::move(a[k]);

另一个可能的改进,特别是对于具有昂贵的默认构造函数的类,是使用移动构造函数就地构造 T。当您分配时,而不是使用new T[] 进行分配,它默认构造每个元素,而是使用new char[]malloc 分配原始字节。然后你可以使用placement new来移动构造对象。

【讨论】:

以上是关于优化将一个数组插入另一个数组 C/C++的主要内容,如果未能解决你的问题,请参考以下文章

在c语言中,将一个数插入一个数组中的程序怎么写?

如何在另一个数组中的用户指定位置插入一个数组并获取结果数组?

将多维数组插入另一个多维数组

有一个从小到大排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。

有一个从小到大排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。

在c语言中,如何在数组中插入一个数